[hdSt, hgiVulkan] Pass bool indicating if draw batch is first draw batch in a
authorclach <clach@users.noreply.github.com>
Tue, 28 Nov 2023 00:31:02 +0000 (16:31 -0800)
committerpixar-oss <pixar-oss@users.noreply.github.com>
Tue, 28 Nov 2023 00:31:02 +0000 (16:31 -0800)
graphics cmds submission to HdSt_DrawBatch::ExecuteDraw, allowing the pipeline
draw batch and related drawing functionality know whether it should clear or
not on a given draw command.

With Vulkan, the clearing of attachments will typically happen at the beginning
of a render pass. A Vulkan render pass is begun in HgiVulkanGraphicsCmds before
drawing. Each pipeline draw batch (which corresponds to one graphics pipeline)
will submit one draw command, but we can have multiple draw batches submit
draws to the same graphics cmds before submission of the graphics cmds. Thus,
we will begin multiple render passes per graphics cmds submission. However, if
the graphics cmds require a clearing of attachments, we really only want that
clearing to happen once, and not EVERY time we begin a render pass, otherwise
we will clear any drawing we just did.

In this change, we pass a bool indicating if the draw batch is the first in the
command buffer's draw batches (and thus the first in a graphics cmd submission)
to HdSt_DrawBatch::ExecuteDraw. HdSt_PipelineDrawBatch can then use this
information in hashing and creating the HgiGraphicsPipeline, which will then
correctly know if it should clear attachments or not. HgiVulkanGraphicsCmds can
then check with HgiVulkanGraphicsPipeline whether it should clear when it
begins a render pass.

(Internal change: 2306451)

14 files changed:
pxr/imaging/hdSt/commandBuffer.cpp
pxr/imaging/hdSt/drawBatch.h
pxr/imaging/hdSt/imageShaderRenderPass.cpp
pxr/imaging/hdSt/indirectDrawBatch.cpp
pxr/imaging/hdSt/indirectDrawBatch.h
pxr/imaging/hdSt/pipelineDrawBatch.cpp
pxr/imaging/hdSt/pipelineDrawBatch.h
pxr/imaging/hdSt/renderPassState.cpp
pxr/imaging/hdSt/renderPassState.h
pxr/imaging/hdSt/testenv/testHdStDrawBatching.cpp
pxr/imaging/hdSt/testenv/testHdStIndirectDrawBatchCodeGen.cpp
pxr/imaging/hgiVulkan/graphicsCmds.cpp
pxr/imaging/hgiVulkan/graphicsPipeline.cpp
pxr/imaging/hgiVulkan/graphicsPipeline.h

index aadac6f81b742af643ea7d76425f320faff9b711..95c0a959b45f4566275fcb24ba0581609cac1f56 100644 (file)
@@ -140,7 +140,8 @@ HdStCommandBuffer::PrepareDraw(
     computeCmds->InsertMemoryBarrier(HgiMemoryBarrierAll);
 
     for (auto const& batch : _drawBatches) {
-        batch->EncodeDraw(renderPassState, resourceRegistry);
+        batch->EncodeDraw(renderPassState, resourceRegistry,
+            /*firstDrawBatch*/batch == *_drawBatches.begin());
     }
 
     computeCmds->InsertMemoryBarrier(HgiMemoryBarrierAll);
@@ -172,7 +173,8 @@ HdStCommandBuffer::ExecuteDraw(
     // draw batches
     //
     for (auto const& batch : _drawBatches) {
-        batch->ExecuteDraw(gfxCmds, renderPassState, resourceRegistry);
+        batch->ExecuteDraw(gfxCmds, renderPassState, resourceRegistry,
+            /*firstDrawBatch*/batch == *_drawBatches.begin());
     }
 
     HD_PERF_COUNTER_SET(HdPerfTokens->drawBatches, _drawBatches.size());
index 5fac207490c99b47ead134fa64d83f805f5ae985..a9a1942fd5fba2523179a96fdade385bb22af53a 100644 (file)
@@ -98,13 +98,15 @@ public:
     /// Encode drawing commands for this batch.
     virtual void EncodeDraw(
         HdStRenderPassStateSharedPtr const & renderPassState,
-        HdStResourceRegistrySharedPtr const & resourceRegistry) = 0;
+        HdStResourceRegistrySharedPtr const & resourceRegistry,
+        bool firstDrawBatch) = 0;
 
     /// Executes the drawing commands for this batch.
     virtual void ExecuteDraw(
         HgiGraphicsCmds *gfxCmds,
         HdStRenderPassStateSharedPtr const &renderPassState,
-        HdStResourceRegistrySharedPtr const & resourceRegistry) = 0;
+        HdStResourceRegistrySharedPtr const & resourceRegistry,
+        bool firstDrawBatch) = 0;
 
     /// Let the batch know that one of it's draw item instances has changed
     /// NOTE: This callback is called from multiple threads, so needs to be
index 859826933da50f6c92e656e445c442c26b646839..eebb10b7c2c6358ae2339072f89f394ed2031e7a 100644 (file)
@@ -180,7 +180,8 @@ HdSt_ImageShaderRenderPass::_Execute(
     // Camera state needs to be updated once per pass (not per batch).
     stRenderPassState->ApplyStateFromCamera();
 
-    _drawBatch->ExecuteDraw(gfxCmds.get(), stRenderPassState, resourceRegistry);
+    _drawBatch->ExecuteDraw(gfxCmds.get(), stRenderPassState, resourceRegistry,
+        /*firstDrawBatch*/true);
 
     gfxCmds->PopDebugGroup();
     _hgi->SubmitCmds(gfxCmds.get());
index 547e22e5db4f29e287a480f77825b78117fc0375..4dd9307e25a35e3f44a054c01700e48d4168e2e5 100644 (file)
@@ -929,7 +929,8 @@ HdSt_IndirectDrawBatch::PrepareDraw(
 void
 HdSt_IndirectDrawBatch::EncodeDraw(
     HdStRenderPassStateSharedPtr const & renderPassState,
-    HdStResourceRegistrySharedPtr const & resourceRegistry)
+    HdStResourceRegistrySharedPtr const & resourceRegistry,
+    bool /*firstDrawBatch*/)
 {
     // No implementation.
 }
@@ -1083,7 +1084,8 @@ void
 HdSt_IndirectDrawBatch::ExecuteDraw(
     HgiGraphicsCmds * gfxCmds,
     HdStRenderPassStateSharedPtr const & renderPassState,
-    HdStResourceRegistrySharedPtr const & resourceRegistry)
+    HdStResourceRegistrySharedPtr const & resourceRegistry,
+    bool /*firstDrawBatch*/)
 {
     HgiGLGraphicsCmds* glGfxCmds = dynamic_cast<HgiGLGraphicsCmds*>(gfxCmds);
 
index 44971f5e6bd09575c278a891f5f76b69bc41d99e..920c8a0eba4631690916d6ceef61fc64c6e9f3c5 100644 (file)
@@ -69,14 +69,16 @@ public:
     HDST_API
     void EncodeDraw(
         HdStRenderPassStateSharedPtr const & renderPassState,
-        HdStResourceRegistrySharedPtr const & resourceRegistry) override;
+        HdStResourceRegistrySharedPtr const & resourceRegistry,
+        bool firstDrawBatch) override;
 
     /// Executes the drawing commands for this batch.
     HDST_API
     void ExecuteDraw(
         HgiGraphicsCmds *gfxCmds,
         HdStRenderPassStateSharedPtr const &renderPassState,
-        HdStResourceRegistrySharedPtr const &resourceRegistry) override;
+        HdStResourceRegistrySharedPtr const &resourceRegistry,
+        bool firstDrawBatch) override;
 
     HDST_API
     void DrawItemInstanceChanged(
index b805e2df31bed71da74533477552cf4c2d18599e..b1b6e381ae503915aa73fa83e84cadeedf95df0c 100644 (file)
@@ -989,7 +989,8 @@ HdSt_PipelineDrawBatch::PrepareDraw(
 void
 HdSt_PipelineDrawBatch::EncodeDraw(
     HdStRenderPassStateSharedPtr const & renderPassState,
-    HdStResourceRegistrySharedPtr const & resourceRegistry)
+    HdStResourceRegistrySharedPtr const & resourceRegistry,
+    bool firstDrawBatch)
 {
     if (_HasNothingToDraw()) return;
 
@@ -1005,7 +1006,8 @@ HdSt_PipelineDrawBatch::EncodeDraw(
 
     _indirectCommands.reset();
     if (drawICB) {
-        _PrepareIndirectCommandBuffer(renderPassState, resourceRegistry);
+        _PrepareIndirectCommandBuffer(renderPassState, resourceRegistry,
+            firstDrawBatch);
     }
 }
 
@@ -1261,7 +1263,8 @@ HgiGraphicsPipelineSharedPtr
 _GetDrawPipeline(
     HdStRenderPassStateSharedPtr const & renderPassState,
     HdStResourceRegistrySharedPtr const & resourceRegistry,
-    _BindingState const & state)
+    _BindingState const & state,
+    bool firstDrawBatch)
 {
     // Drawing pipeline is compatible as long as the shader and
     // pipeline state are the same.
@@ -1272,7 +1275,7 @@ _GetDrawPipeline(
     uint64_t hash = salt;
     hash = TfHash::Combine(hash, programHandle.Get());
     hash = TfHash::Combine(hash, renderPassState->GetGraphicsPipelineHash(
-        state.geometricShader));
+        state.geometricShader, firstDrawBatch));
 
     HdInstance<HgiGraphicsPipelineSharedPtr> pipelineInstance =
         resourceRegistry->RegisterGraphicsPipeline(hash);
@@ -1281,7 +1284,8 @@ _GetDrawPipeline(
         HgiGraphicsPipelineDesc pipeDesc;
 
         renderPassState->InitGraphicsPipelineDesc(&pipeDesc,
-                                                  state.geometricShader);
+                                                  state.geometricShader,
+                                                  firstDrawBatch);
 
         pipeDesc.shaderProgram = state.glslProgram->GetProgram();
         pipeDesc.vertexBuffers = _GetVertexBuffersForDrawing(state);
@@ -1301,7 +1305,8 @@ HgiGraphicsPipelineSharedPtr
 _GetPTCSPipeline(
     HdStRenderPassStateSharedPtr const & renderPassState,
     HdStResourceRegistrySharedPtr const & resourceRegistry,
-    _BindingState const & state)
+    _BindingState const & state,
+    bool firstDrawBatch)
 {
     // PTCS pipeline is compatible as long as the shader and
     // pipeline state are the same.
@@ -1312,7 +1317,7 @@ _GetPTCSPipeline(
     uint64_t hash = salt;
     hash = TfHash::Combine(hash, programHandle.Get());
     hash = TfHash::Combine(hash, renderPassState->GetGraphicsPipelineHash(
-        state.geometricShader));
+        state.geometricShader, firstDrawBatch));
 
     HdInstance<HgiGraphicsPipelineSharedPtr> pipelineInstance =
         resourceRegistry->RegisterGraphicsPipeline(hash);
@@ -1321,7 +1326,8 @@ _GetPTCSPipeline(
         HgiGraphicsPipelineDesc pipeDesc;
 
         renderPassState->InitGraphicsPipelineDesc(&pipeDesc,
-                                                  state.geometricShader);
+                                                  state.geometricShader,
+                                                  firstDrawBatch);
 
         pipeDesc.rasterizationState.rasterizerEnabled = false;
         pipeDesc.multiSampleState.sampleCount = HgiSampleCount1;
@@ -1351,7 +1357,8 @@ void
 HdSt_PipelineDrawBatch::ExecuteDraw(
     HgiGraphicsCmds * gfxCmds,
     HdStRenderPassStateSharedPtr const & renderPassState,
-    HdStResourceRegistrySharedPtr const & resourceRegistry)
+    HdStResourceRegistrySharedPtr const & resourceRegistry,
+    bool firstDrawBatch)
 {
     TRACE_FUNCTION();
 
@@ -1366,8 +1373,8 @@ HdSt_PipelineDrawBatch::ExecuteDraw(
 
     if (_tessFactorsBuffer) {
         // Metal tessellation tessFactors are computed by PTCS.
-        _ExecutePTCS(gfxCmds, renderPassState, resourceRegistry);
-
+        _ExecutePTCS(gfxCmds, renderPassState, resourceRegistry,
+            firstDrawBatch);
         // Finish computing tessFactors before drawing.
         gfxCmds->InsertMemoryBarrier(HgiMemoryBarrierAll);
     }
@@ -1400,8 +1407,9 @@ HdSt_PipelineDrawBatch::ExecuteDraw(
             _GetDrawPipeline(
                 renderPassState,
                 resourceRegistry,
-                state);
-        
+                state,
+                firstDrawBatch);
+
         HgiGraphicsPipelineHandle psoHandle = *pso.get();
         gfxCmds->BindPipeline(psoHandle);
 
@@ -1574,7 +1582,8 @@ _GetCullPipeline(
 void
 HdSt_PipelineDrawBatch::_PrepareIndirectCommandBuffer(
     HdStRenderPassStateSharedPtr const & renderPassState,
-    HdStResourceRegistrySharedPtr const & resourceRegistry)
+    HdStResourceRegistrySharedPtr const & resourceRegistry,
+    bool firstDrawBatch)
 {
     Hgi *hgi = resourceRegistry->GetHgi();
     _DrawingProgram & program = _GetDrawingProgram(renderPassState,
@@ -1593,7 +1602,8 @@ HdSt_PipelineDrawBatch::_PrepareIndirectCommandBuffer(
         _GetDrawPipeline(
             renderPassState,
             resourceRegistry,
-            state);
+            state,
+            firstDrawBatch);
     
     HgiGraphicsPipelineHandle psoHandle = *pso.get();
 
@@ -1767,9 +1777,10 @@ HdSt_PipelineDrawBatch::_ExecuteFrustumCull(
 
 void
 HdSt_PipelineDrawBatch::_ExecutePTCS(
-        HgiGraphicsCmds *ptcsGfxCmds,
-        HdStRenderPassStateSharedPtr const & renderPassState,
-        HdStResourceRegistrySharedPtr const & resourceRegistry)
+    HgiGraphicsCmds *ptcsGfxCmds,
+    HdStRenderPassStateSharedPtr const & renderPassState,
+    HdStResourceRegistrySharedPtr const & resourceRegistry,
+    bool firstDrawBatch)
 {
     TRACE_FUNCTION();
 
@@ -1804,7 +1815,8 @@ HdSt_PipelineDrawBatch::_ExecutePTCS(
     HgiGraphicsPipelineSharedPtr const & psoTess =
         _GetPTCSPipeline(renderPassState,
                          resourceRegistry,
-                         state);
+                         state,
+                         firstDrawBatch);
 
     HgiGraphicsPipelineHandle psoTessHandle = *psoTess.get();
     ptcsGfxCmds->BindPipeline(psoTessHandle);
index 7148b65bc9bba56ffb270bb2e8fdbe77a1c841d9..bbdac8eee1d005c7b1d79d06f72f2c777a87453b 100644 (file)
@@ -72,14 +72,16 @@ public:
     HDST_API
     void EncodeDraw(
         HdStRenderPassStateSharedPtr const & renderPassState,
-        HdStResourceRegistrySharedPtr const & resourceRegistry) override;
+        HdStResourceRegistrySharedPtr const & resourceRegistry,
+        bool firstDrawBatch) override;
 
     /// Executes the drawing commands for this batch.
     HDST_API
     void ExecuteDraw(
         HgiGraphicsCmds *gfxCmds,
         HdStRenderPassStateSharedPtr const & renderPassState,
-        HdStResourceRegistrySharedPtr const & resourceRegistry) override;
+        HdStResourceRegistrySharedPtr const & resourceRegistry,
+        bool firstDrawBatch) override;
 
     HDST_API
     void DrawItemInstanceChanged(
@@ -139,7 +141,8 @@ private:
     
     void _PrepareIndirectCommandBuffer(
         HdStRenderPassStateSharedPtr const & renderPassState,
-        HdStResourceRegistrySharedPtr const & resourceRegistry);
+        HdStResourceRegistrySharedPtr const & resourceRegistry,
+        bool firstDrawBatch);
 
     bool _HasNothingToDraw() const;
 
@@ -159,7 +162,8 @@ private:
     void _ExecutePTCS(
             HgiGraphicsCmds *ptcsGfxCmds,
             HdStRenderPassStateSharedPtr const & renderPassState,
-            HdStResourceRegistrySharedPtr const & resourceRegistry);
+            HdStResourceRegistrySharedPtr const & resourceRegistry,
+            bool firstDrawBatch);
 
     void _BeginGPUCountVisibleInstances(
         HdStResourceRegistrySharedPtr const & resourceRegistry);
index d57eb7def503369462acb09cddbd22c5865146dc..c891ffd25e6fc105428e57929f5be0e26dc2abbf 100644 (file)
@@ -1101,7 +1101,8 @@ HdStRenderPassState::_InitPrimitiveState(
 
 void
 HdStRenderPassState::_InitAttachmentState(
-    HgiGraphicsPipelineDesc * pipeDesc) const
+    HgiGraphicsPipelineDesc * pipeDesc,
+    bool firstDrawBatch) const
 {
     // For Metal and Vulkan, we have to pass the color and depth descriptors 
     // down so that they are available when creating the Render Pipeline State
@@ -1114,6 +1115,13 @@ HdStRenderPassState::_InitAttachmentState(
         _InitAttachmentDesc(
             attachment, binding, binding.renderBuffer, aovIndex);
 
+        // For HgiVulkan, don't want to run a clear operation unless this is 
+        // the first draw batch in a graphics cmds submission.
+        if (!firstDrawBatch) {
+            attachment.loadOp = HgiAttachmentLoadOpLoad;
+            attachment.clearValue = GfVec4f(0);
+        }
+
         if (HdAovHasDepthSemantic(binding.aovName) ||
             HdAovHasDepthStencilSemantic(binding.aovName)) {
             pipeDesc->depthAttachmentDesc = attachment;
@@ -1224,18 +1232,20 @@ HdStRenderPassState::_InitRasterizationState(
 void
 HdStRenderPassState::InitGraphicsPipelineDesc(
     HgiGraphicsPipelineDesc * pipeDesc,
-    HdSt_GeometricShaderSharedPtr const & geometricShader) const
+    HdSt_GeometricShaderSharedPtr const & geometricShader,
+    bool firstDrawBatch) const
 {
     _InitPrimitiveState(pipeDesc, geometricShader);
     _InitDepthStencilState(&pipeDesc->depthState);
     _InitMultiSampleState(&pipeDesc->multiSampleState);
     _InitRasterizationState(&pipeDesc->rasterizationState, geometricShader);
-    _InitAttachmentState(pipeDesc);
+    _InitAttachmentState(pipeDesc, firstDrawBatch);
 }
 
 uint64_t
 HdStRenderPassState::GetGraphicsPipelineHash(
-    HdSt_GeometricShaderSharedPtr const & geometricShader) const
+    HdSt_GeometricShaderSharedPtr const & geometricShader,
+    bool firstDrawBatch) const
 {
     // Hash all of the state that is captured in the pipeline state object.
     uint64_t hash = TfHash::Combine(
@@ -1276,7 +1286,7 @@ HdStRenderPassState::GetGraphicsPipelineHash(
         geometricShader->ResolveCullMode(_cullStyle),
         geometricShader->GetHgiPrimitiveType(),
         geometricShader->GetPrimitiveIndexSize());
-    
+
     // Hash the aov bindings by name and format.
     for (HdRenderPassAovBinding const& binding : GetAovBindings()) {
         HdStRenderBuffer *renderBuffer =
@@ -1284,13 +1294,16 @@ HdStRenderPassState::GetGraphicsPipelineHash(
         
         const uint32_t msaaCount = renderBuffer->IsMultiSampled() ?
             renderBuffer->GetMSAASampleCount() : 1;
-
+        const bool clear =
+            firstDrawBatch ? !binding.clearValue.IsEmpty() : false;
+        
         hash = TfHash::Combine(hash,
                                binding.aovName,
                                renderBuffer->GetFormat(),
-                               msaaCount);
+                               msaaCount,
+                               clear);
     }
-    
+
     return hash;
 }
 
index 990780410d323857c294bb23f3f622cfd9686c93..f47b5984ae0dcd17c4a31d35348f1736196373e5 100644 (file)
@@ -194,12 +194,14 @@ public:
     HDST_API
     void InitGraphicsPipelineDesc(
                 HgiGraphicsPipelineDesc * pipeDesc,
-                HdSt_GeometricShaderSharedPtr const & geometricShader) const;
+                HdSt_GeometricShaderSharedPtr const & geometricShader,
+                bool firstDrawBatch) const;
 
     /// Generates the hash for the settings used to init the graphics pipeline.
     HDST_API
     uint64_t GetGraphicsPipelineHash(
-        HdSt_GeometricShaderSharedPtr const & geometricShader) const;
+        HdSt_GeometricShaderSharedPtr const & geometricShader,
+        bool firstDrawBatch) const;
 
     // A 4d-vector v encodes a 2d-transform as follows:
     // (x, y) |-> (v[0] * x + v[2], v[1] * y + v[3]).
@@ -234,7 +236,8 @@ private:
     void _InitPrimitiveState(
                 HgiGraphicsPipelineDesc * pipeDesc,
                 HdSt_GeometricShaderSharedPtr const & geometricShader) const;
-    void _InitAttachmentState(HgiGraphicsPipelineDesc * pipeDesc) const;
+    void _InitAttachmentState(HgiGraphicsPipelineDesc * pipeDesc,
+                              bool firstDrawBatch) const;
     void _InitDepthStencilState(HgiDepthStencilState * depthState) const;
     void _InitMultiSampleState(HgiMultiSampleState * multisampleState) const;
     void _InitRasterizationState(
index 421f7f7749c900019938a92b64b5d3710cb2c4b5..4be9507b35eebc28587b97d4854db6bf8f73db5e 100644 (file)
@@ -494,7 +494,8 @@ IndirectDrawBatchTest()
         (*batchIt)->PrepareDraw(nullptr, renderPassState, registry);
     }
     TF_FOR_ALL(batchIt, drawBatches) {
-        (*batchIt)->ExecuteDraw(nullptr, renderPassState, registry);
+        (*batchIt)->ExecuteDraw(nullptr, renderPassState, registry,
+            /*firstDrawBatch*/*batchIt == *drawBatches.begin());
     }
     dict = registry->GetResourceAllocation();
     Dump("----- executed -----\n", dict, perfLog);
@@ -754,7 +755,8 @@ EmptyDrawBatchTest()
     HdStRenderPassStateSharedPtr const renderPassState =
         std::make_shared<HdStRenderPassState>();
     batch->PrepareDraw(nullptr, renderPassState, registry);
-    batch->ExecuteDraw(nullptr, renderPassState, registry);
+    batch->ExecuteDraw(nullptr, renderPassState, registry,
+        /*firstDrawBatch*/true);
 
     // ---------------------------------------------------
 
index 24e146bf4abe4ef5accf5fc7e1820d9e88b4a4cf..42e52845fbc5b46bd7041c774cb76997f65ebbc3 100644 (file)
@@ -180,7 +180,8 @@ HdIndirectDrawBatchTest()
     {
         TfErrorMark mark;
 
-        batch->ExecuteDraw(nullptr, passState, registry);
+        batch->ExecuteDraw(nullptr, passState, registry,
+            /*firstDrawBatch*/true);
 
         if (mark.IsClean()) {
             std::cout << "Did not get expected shader compilation error\n";
index 28ea6cef3be4ebf7a83c0ae3d5efdf3b3643cd76..cadd089cb6d7f89bc4108a5b256bba53c25a2335 100755 (executable)
@@ -632,12 +632,18 @@ HgiVulkanGraphicsCmds::_ApplyPendingUpdates()
         VkRenderPassBeginInfo beginInfo =
             {VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO};
         beginInfo.renderPass = pso->GetVulkanRenderPass();
-        beginInfo.framebuffer= pso->AcquireVulkanFramebuffer(_descriptor,&size);
+        beginInfo.framebuffer= pso->AcquireVulkanFramebuffer(
+            _descriptor, &size);
         beginInfo.renderArea.extent.width = size[0];
         beginInfo.renderArea.extent.height = size[1];
-        beginInfo.clearValueCount =
-            static_cast<uint32_t>(_vkClearValues.size());
-        beginInfo.pClearValues = _vkClearValues.data();
+
+        // Only pass clear values to VkRenderPassBeginInfo if the pipeline has
+        // attachments that specify a clear op.
+        if (pso->GetClearNeeded()) {
+            beginInfo.clearValueCount =
+                static_cast<uint32_t>(_vkClearValues.size());
+            beginInfo.pClearValues = _vkClearValues.data();
+        }
 
         VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE;
 
index b6dcc6a9f73a0acde534d83db5822209972f14b9..64e9d82baa1e0d5574f75d4d034e121e1781bb4a 100755 (executable)
@@ -47,6 +47,7 @@ HgiVulkanGraphicsPipeline::HgiVulkanGraphicsPipeline(
     , _vkPipeline(nullptr)
     , _vkRenderPass(nullptr)
     , _vkPipelineLayout(nullptr)
+    , _clearNeeded(false)
 {
     VkGraphicsPipelineCreateInfo pipeCreateInfo =
         {VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO};
@@ -558,8 +559,8 @@ HgiVulkanGraphicsPipeline::GetInflightBits()
     return _inflightBits;
 }
 
-static void
-_ProcessAttachment(
+void
+HgiVulkanGraphicsPipeline::_ProcessAttachment(
     HgiAttachmentDesc const& attachment,
     uint32_t attachmentIndex,
     HgiSampleCount sampleCount,
@@ -599,6 +600,13 @@ _ProcessAttachment(
         attachment.format, isDepthAttachment);
     vkAttachDesc->initialLayout = layout;
     vkAttachDesc->loadOp = HgiVulkanConversions::GetLoadOp(attachment.loadOp);
+
+    // If any attachments specify a clear op, clearing the renderpass will be 
+    // needed.
+    if (attachment.loadOp == HgiAttachmentLoadOpClear) {
+        _clearNeeded = true;
+    }
+
     vkAttachDesc->samples = HgiVulkanConversions::GetSampleCount(sampleCount);
     vkAttachDesc->storeOp= HgiVulkanConversions::GetStoreOp(attachment.storeOp);
     // XXX Hgi doesn't provide stencil ops, assume it matches depth attachment.
index ea663c4ce7138000172fa583628703fafc7ac0b8..67062cbcbfd9daad4b1e9d813db9ee01c3d21402 100755 (executable)
@@ -75,6 +75,14 @@ public:
     HGIVULKAN_API
     uint64_t & GetInflightBits();
 
+    /// Returns true if any of the attachments in HgiGraphicsPipelineDesc 
+    /// specify a clear operation.
+    HGIVULKAN_API
+    bool GetClearNeeded() const
+    {
+        return _clearNeeded;
+    }
+
 protected:
     friend class HgiVulkan;
 
@@ -88,6 +96,12 @@ private:
     HgiVulkanGraphicsPipeline & operator=(const HgiVulkanGraphicsPipeline&) = delete;
     HgiVulkanGraphicsPipeline(const HgiVulkanGraphicsPipeline&) = delete;
 
+    void _ProcessAttachment(
+        HgiAttachmentDesc const& attachment,
+        uint32_t attachmentIndex,
+        HgiSampleCount sampleCount,
+        VkAttachmentDescription2* vkAttachDesc,
+        VkAttachmentReference2* vkRef);
     void _CreateRenderPass();
 
     struct HgiVulkan_Framebuffer {
@@ -102,6 +116,7 @@ private:
     VkRenderPass _vkRenderPass;
     VkPipelineLayout _vkPipelineLayout;
     VkDescriptorSetLayoutVector _vkDescriptorSetLayouts;
+    bool _clearNeeded;
 
     std::vector<HgiVulkan_Framebuffer> _framebuffers;
 };