From c148dba05220e4a8edd27a69cadd2997ea234109 Mon Sep 17 00:00:00 2001
From: Paul Olav Tvete <paul.tvete@qt.io>
Date: Wed, 1 Apr 2020 13:32:17 +0200
Subject: [PATCH] RHI: add support for Buffer.SceneLifetime

Task-number: QTBUG-82550
Change-Id: Id2e8014db0526cd398298e1843e27a7888acb4f7
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
---
 .../qssgrenderdynamicobjectsystemcommands_p.h |  2 +-
 src/runtimerender/qssgrhieffectsystem.cpp     | 38 +++++++++++++++----
 2 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/src/runtimerender/qssgrenderdynamicobjectsystemcommands_p.h b/src/runtimerender/qssgrenderdynamicobjectsystemcommands_p.h
index f157e76fa..19402a109 100644
--- a/src/runtimerender/qssgrenderdynamicobjectsystemcommands_p.h
+++ b/src/runtimerender/qssgrenderdynamicobjectsystemcommands_p.h
@@ -141,7 +141,7 @@ struct QSSGAllocateBuffer : public QSSGCommand
     {
     }
     void addDebug(QDebug &stream) const {
-        stream << "name:" <<  m_name << "format:" << m_format.toString() << "size multiplier:" << m_sizeMultiplier << "filter:" << toString(m_filterOp) << "tiling:" << toString(m_texCoordOp);
+        stream << "name:" <<  m_name << "format:" << m_format.toString() << "size multiplier:" << m_sizeMultiplier << "filter:" << toString(m_filterOp) << "tiling:" << toString(m_texCoordOp) << "sceneLifetime:" << m_bufferFlags.isSceneLifetime();
     }
 };
 
diff --git a/src/runtimerender/qssgrhieffectsystem.cpp b/src/runtimerender/qssgrhieffectsystem.cpp
index d0371449f..7e92a32ca 100644
--- a/src/runtimerender/qssgrhieffectsystem.cpp
+++ b/src/runtimerender/qssgrhieffectsystem.cpp
@@ -49,6 +49,7 @@ struct QSSGRhiEffectTexture
     QByteArray name;
 
     QSSGRhiSamplerDescription desc;
+    QSSGAllocateBufferFlags flags;
 
     ~QSSGRhiEffectTexture()
     {
@@ -125,15 +126,33 @@ QSSGRhiEffectTexture *QSSGRhiEffectSystem::getTexture(const QByteArray &bufferNa
     return result;
 }
 
+//#define DEBUG_ALWAYS_DELETE_TEXTURES // delete and recreate textures instead of reusing old ones
+
 void QSSGRhiEffectSystem::releaseTexture(QSSGRhiEffectTexture *texture)
 {
-    texture->name = {};
+    if (!texture->flags.isSceneLifetime()) {
+#ifdef DEBUG_ALWAYS_DELETE_TEXTURES
+        texture->name = "__toBeDeleted";
+#else
+        texture->name = {};
+#endif
+    }
 }
 
 void QSSGRhiEffectSystem::releaseTextures()
 {
+#ifdef DEBUG_ALWAYS_DELETE_TEXTURES
+    // can't delete immediately, since the QRhiTexture is still used until the end of the frame
+    // therefore, mark textures as still in use, but to be deleted next time; but first delete the marked ones
+    // from last time
+    m_textures.erase(std::remove_if(m_textures.begin(),
+                                    m_textures.end(),
+                                    [](auto *t){return t->name == "__toBeDeleted" && (delete t, true);}),
+                     m_textures.end());
+#endif
+
     for (auto *t : qAsConst(m_textures))
-        t->name = {};
+        releaseTexture(t);
 }
 
 QRhiTexture *QSSGRhiEffectSystem::process(const QSSGRef<QSSGRhiContext> &rhiCtx,
@@ -153,7 +172,7 @@ QRhiTexture *QSSGRhiEffectSystem::process(const QSSGRef<QSSGRhiContext> &rhiCtx,
     //### For now, ignore active state
     m_currentUbufIndex = 0;
     auto *currentEffect = m_firstEffect;
-    QSSGRhiEffectTexture firstTex{ inTexture, nullptr, nullptr, {}, {} };
+    QSSGRhiEffectTexture firstTex{ inTexture, nullptr, nullptr, {}, {}, {} };
     auto *latestOutput = doRenderEffect(currentEffect, &firstTex);
     firstTex = {}; //make sure we don't delete inTexture when we go out of scope
 
@@ -164,7 +183,6 @@ QRhiTexture *QSSGRhiEffectSystem::process(const QSSGRef<QSSGRhiContext> &rhiCtx,
         latestOutput = effectOut;
     }
 
-    //TODO: handle SceneLifeTime -- we probably need a hook in ~QSSGRenderEffect()
     releaseTextures(); //we're done here -- TODO: unify texture handling with AA
     return latestOutput->texture;
 }
@@ -251,8 +269,13 @@ QSSGRhiEffectTexture *QSSGRhiEffectSystem::doRenderEffect(const QSSGRenderEffect
             QRhiTexture::Format rhiFormat = (f == QSSGRenderTextureFormat::Unknown) ? inTexture->texture->format() :
                                 QSSGBufferManager::toRhiFormat(f);
 
-            QSSGRhiEffectTexture *buf = nullptr;
-            if (!(buf = findTexture(allocateCmd->m_name)))
+            QSSGRhiEffectTexture *buf = findTexture(allocateCmd->m_name);
+            if (buf && buf->texture->pixelSize() != bufferSize) {
+                buf->texture->setPixelSize(bufferSize);
+                buf->texture->build();
+                buf->renderTarget->build();
+            }
+            if (!buf)
                 buf = getTexture(allocateCmd->m_name, bufferSize, rhiFormat);
             auto filter = toRhi(allocateCmd->m_filterOp);
             auto tiling = toRhi(allocateCmd->m_texCoordOp);
@@ -263,8 +286,7 @@ QSSGRhiEffectTexture *QSSGRhiEffectSystem::doRenderEffect(const QSSGRenderEffect
                 tiling,
                 tiling
             };
-
-            // TODO: flags sceneLifetime
+            buf->flags = allocateCmd->m_bufferFlags;
             break;
         }
         case CommandType::ApplyDepthValue: {
-- 
GitLab