@@ -51,7 +51,7 @@ class VulkanCommandBuffer
5151 const VkImageSubresourceRange& Subresource)
5252 {
5353 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
54- VERIFY (m_State. RenderPass == VK_NULL_HANDLE ,
54+ VERIFY (! IsInRenderScope () ,
5555 " vkCmdClearColorImage() must be called outside of render pass "
5656 " (https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VUID-vkCmdClearColorImage-renderpass)" );
5757 VERIFY (Subresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT,
@@ -73,7 +73,7 @@ class VulkanCommandBuffer
7373 const VkImageSubresourceRange& Subresource)
7474 {
7575 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
76- VERIFY (m_State. RenderPass == VK_NULL_HANDLE ,
76+ VERIFY (! IsInRenderScope () ,
7777 " vkCmdClearDepthStencilImage() must be called outside of render pass "
7878 " (https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VUID-vkCmdClearDepthStencilImage-renderpass)" );
7979 // clang-format off
@@ -96,7 +96,7 @@ class VulkanCommandBuffer
9696 __forceinline void ClearAttachment (const VkClearAttachment& Attachment, const VkClearRect& ClearRect)
9797 {
9898 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
99- VERIFY (m_State. RenderPass != VK_NULL_HANDLE ,
99+ VERIFY (IsInRenderScope () ,
100100 " vkCmdClearAttachments() must be called inside render pass "
101101 " (https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VUID-vkCmdClearAttachments-renderpass)" );
102102
@@ -113,7 +113,7 @@ class VulkanCommandBuffer
113113 __forceinline void Draw (uint32_t VertexCount, uint32_t InstanceCount, uint32_t FirstVertex, uint32_t FirstInstance)
114114 {
115115 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
116- VERIFY (m_State. RenderPass != VK_NULL_HANDLE ,
116+ VERIFY (IsInRenderScope () ,
117117 " vkCmdDraw() must be called inside render pass "
118118 " (https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VUID-vkCmdDraw-renderpass)" );
119119 VERIFY (m_State.GraphicsPipeline != VK_NULL_HANDLE, " No graphics pipeline bound" );
@@ -124,7 +124,7 @@ class VulkanCommandBuffer
124124 __forceinline void DrawIndexed (uint32_t IndexCount, uint32_t InstanceCount, uint32_t FirstIndex, int32_t VertexOffset, uint32_t FirstInstance)
125125 {
126126 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
127- VERIFY (m_State. RenderPass != VK_NULL_HANDLE ,
127+ VERIFY (IsInRenderScope () ,
128128 " vkCmdDrawIndexed() must be called inside render pass "
129129 " (https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VUID-vkCmdDrawIndexed-renderpass)" );
130130 VERIFY (m_State.GraphicsPipeline != VK_NULL_HANDLE, " No graphics pipeline bound" );
@@ -136,7 +136,7 @@ class VulkanCommandBuffer
136136 __forceinline void DrawIndirect (VkBuffer Buffer, VkDeviceSize Offset, uint32_t DrawCount, uint32_t Stride)
137137 {
138138 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
139- VERIFY (m_State. RenderPass != VK_NULL_HANDLE ,
139+ VERIFY (IsInRenderScope () ,
140140 " vkCmdDrawIndirect() must be called inside render pass "
141141 " (https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VUID-vkCmdDrawIndirect-renderpass)" );
142142 VERIFY (m_State.GraphicsPipeline != VK_NULL_HANDLE, " No graphics pipeline bound" );
@@ -147,7 +147,7 @@ class VulkanCommandBuffer
147147 __forceinline void DrawIndexedIndirect (VkBuffer Buffer, VkDeviceSize Offset, uint32_t DrawCount, uint32_t Stride)
148148 {
149149 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
150- VERIFY (m_State. RenderPass != VK_NULL_HANDLE ,
150+ VERIFY (IsInRenderScope () ,
151151 " vkCmdDrawIndexedIndirect() must be called inside render pass "
152152 " (https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VUID-vkCmdDrawIndexedIndirect-renderpass)" );
153153 VERIFY (m_State.GraphicsPipeline != VK_NULL_HANDLE, " No graphics pipeline bound" );
@@ -160,7 +160,7 @@ class VulkanCommandBuffer
160160 {
161161#if DILIGENT_USE_VOLK
162162 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
163- VERIFY (m_State. RenderPass != VK_NULL_HANDLE ,
163+ VERIFY (IsInRenderScope () ,
164164 " vkCmdDrawIndirectCountKHR() must be called inside render pass "
165165 " (https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VUID-vkCmdDrawIndirectCount-renderpass)" );
166166 VERIFY (m_State.GraphicsPipeline != VK_NULL_HANDLE, " No graphics pipeline bound" );
@@ -175,7 +175,7 @@ class VulkanCommandBuffer
175175 {
176176#if DILIGENT_USE_VOLK
177177 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
178- VERIFY (m_State. RenderPass != VK_NULL_HANDLE ,
178+ VERIFY (IsInRenderScope () ,
179179 " vkCmdDrawIndexedIndirectCountKHR() must be called inside render pass "
180180 " (https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VUID-vkCmdDrawIndexedIndirectCount-renderpass)" );
181181 VERIFY (m_State.GraphicsPipeline != VK_NULL_HANDLE, " No graphics pipeline bound" );
@@ -191,7 +191,7 @@ class VulkanCommandBuffer
191191 {
192192#if DILIGENT_USE_VOLK
193193 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
194- VERIFY (m_State. RenderPass != VK_NULL_HANDLE , " vkCmdDrawMeshTasksEXT() must be called inside render pass" );
194+ VERIFY (IsInRenderScope () , " vkCmdDrawMeshTasksEXT() must be called inside render pass" );
195195 VERIFY (m_State.GraphicsPipeline != VK_NULL_HANDLE, " No graphics pipeline bound" );
196196
197197 vkCmdDrawMeshTasksEXT (m_VkCmdBuffer, TaskCountX, TaskCountY, TaskCountZ);
@@ -204,7 +204,7 @@ class VulkanCommandBuffer
204204 {
205205#if DILIGENT_USE_VOLK
206206 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
207- VERIFY (m_State. RenderPass != VK_NULL_HANDLE , " vkCmdDrawMeshTasksIndirectEXT() must be called inside render pass" );
207+ VERIFY (IsInRenderScope () , " vkCmdDrawMeshTasksIndirectEXT() must be called inside render pass" );
208208 VERIFY (m_State.GraphicsPipeline != VK_NULL_HANDLE, " No graphics pipeline bound" );
209209
210210 vkCmdDrawMeshTasksIndirectEXT (m_VkCmdBuffer, Buffer, Offset, DrawCount, Stride);
@@ -217,7 +217,7 @@ class VulkanCommandBuffer
217217 {
218218#if DILIGENT_USE_VOLK
219219 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
220- VERIFY (m_State. RenderPass != VK_NULL_HANDLE , " vkCmdDrawMeshTasksIndirectCountEXT() must be called inside render pass" );
220+ VERIFY (IsInRenderScope () , " vkCmdDrawMeshTasksIndirectCountEXT() must be called inside render pass" );
221221 VERIFY (m_State.GraphicsPipeline != VK_NULL_HANDLE, " No graphics pipeline bound" );
222222
223223 vkCmdDrawMeshTasksIndirectCountEXT (m_VkCmdBuffer, Buffer, Offset, CountBuffer, CountBufferOffset, MaxDrawCount, Stride);
@@ -233,7 +233,7 @@ class VulkanCommandBuffer
233233 {
234234#if DILIGENT_USE_VOLK
235235 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
236- VERIFY (m_State. RenderPass != VK_NULL_HANDLE , " vkCmdDrawMultiEXT() must be called inside render pass" );
236+ VERIFY (IsInRenderScope () , " vkCmdDrawMultiEXT() must be called inside render pass" );
237237 VERIFY (m_State.GraphicsPipeline != VK_NULL_HANDLE, " No graphics pipeline bound" );
238238
239239 vkCmdDrawMultiEXT (m_VkCmdBuffer, DrawCount, pVertexInfo, InstanceCount, FirstInstance, sizeof (VkMultiDrawInfoEXT));
@@ -249,7 +249,7 @@ class VulkanCommandBuffer
249249 {
250250#if DILIGENT_USE_VOLK
251251 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
252- VERIFY (m_State. RenderPass != VK_NULL_HANDLE , " vkCmdDrawMultiIndexedEXT() must be called inside render pass" );
252+ VERIFY (IsInRenderScope () , " vkCmdDrawMultiIndexedEXT() must be called inside render pass" );
253253 VERIFY (m_State.GraphicsPipeline != VK_NULL_HANDLE, " No graphics pipeline bound" );
254254 VERIFY (m_State.IndexBuffer != VK_NULL_HANDLE, " No index buffer bound" );
255255
@@ -265,7 +265,7 @@ class VulkanCommandBuffer
265265 __forceinline void Dispatch (uint32_t GroupCountX, uint32_t GroupCountY, uint32_t GroupCountZ)
266266 {
267267 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
268- VERIFY (m_State. RenderPass == VK_NULL_HANDLE ,
268+ VERIFY (! IsInRenderScope () ,
269269 " vkCmdDispatch() must be called outside of render pass "
270270 " (https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VUID-vkCmdDispatch-renderpass)" );
271271 VERIFY (m_State.ComputePipeline != VK_NULL_HANDLE, " No compute pipeline bound" );
@@ -277,7 +277,7 @@ class VulkanCommandBuffer
277277 __forceinline void DispatchIndirect (VkBuffer Buffer, VkDeviceSize Offset)
278278 {
279279 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
280- VERIFY (m_State. RenderPass == VK_NULL_HANDLE ,
280+ VERIFY (! IsInRenderScope () ,
281281 " vkCmdDispatchIndirect() must be called outside of render pass "
282282 " (https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#VUID-vkCmdDispatchIndirect-renderpass)" );
283283 VERIFY (m_State.ComputePipeline != VK_NULL_HANDLE, " No compute pipeline bound" );
@@ -295,6 +295,7 @@ class VulkanCommandBuffer
295295 {
296296 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
297297 VERIFY (m_State.RenderPass == VK_NULL_HANDLE, " Current pass has not been ended" );
298+ VERIFY (!m_State.RenderingBegan , " Current dynamic render pass has not been ended" );
298299
299300 if (m_State.RenderPass != RenderPass || m_State.Framebuffer != Framebuffer)
300301 {
@@ -353,10 +354,35 @@ class VulkanCommandBuffer
353354 vkCmdNextSubpass (m_VkCmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
354355 }
355356
357+ __forceinline void BeginRendering (const VkRenderingInfoKHR& RenderingInfo)
358+ {
359+ VERIFY (m_State.RenderPass == VK_NULL_HANDLE, " Another render pass has already been started" );
360+ VERIFY (!m_State.RenderingBegan , " Rendering has already begun" );
361+ VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
362+ vkCmdBeginRenderingKHR (m_VkCmdBuffer, &RenderingInfo);
363+ m_State.RenderingBegan = true ;
364+ }
365+
366+ __forceinline void EndRendering ()
367+ {
368+ VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
369+ VERIFY (m_State.RenderingBegan , " Rendering has not begun" );
370+ vkCmdEndRenderingKHR (m_VkCmdBuffer);
371+ m_State.RenderingBegan = false ;
372+ }
373+
374+ __forceinline void EndRenderScope ()
375+ {
376+ if (m_State.RenderPass != VK_NULL_HANDLE)
377+ EndRenderPass ();
378+ else if (m_State.RenderingBegan )
379+ EndRendering ();
380+ }
381+
356382 __forceinline void EndCommandBuffer ()
357383 {
358384 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
359- VERIFY (m_State. RenderPass == VK_NULL_HANDLE , " Render pass has not been ended" );
385+ VERIFY (! IsInRenderScope () , " Render pass has not been ended" );
360386 FlushBarriers ();
361387 vkEndCommandBuffer (m_VkCmdBuffer);
362388 }
@@ -478,11 +504,8 @@ class VulkanCommandBuffer
478504 const VkBufferCopy* pRegions)
479505 {
480506 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
481- if (m_State.RenderPass != VK_NULL_HANDLE)
482- {
483- // Copy buffer operation must be performed outside of render pass.
484- EndRenderPass ();
485- }
507+ // Copy buffer operation must be performed outside of render pass.
508+ EndRenderScope ();
486509 FlushBarriers ();
487510 vkCmdCopyBuffer (m_VkCmdBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
488511 }
@@ -495,11 +518,8 @@ class VulkanCommandBuffer
495518 const VkImageCopy* pRegions)
496519 {
497520 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
498- if (m_State.RenderPass != VK_NULL_HANDLE)
499- {
500- // Copy operations must be performed outside of render pass.
501- EndRenderPass ();
502- }
521+ // Copy operations must be performed outside of render pass.
522+ EndRenderScope ();
503523 FlushBarriers ();
504524 vkCmdCopyImage (m_VkCmdBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
505525 }
@@ -511,11 +531,8 @@ class VulkanCommandBuffer
511531 const VkBufferImageCopy* pRegions)
512532 {
513533 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
514- if (m_State.RenderPass != VK_NULL_HANDLE)
515- {
516- // Copy operations must be performed outside of render pass.
517- EndRenderPass ();
518- }
534+ // Copy operations must be performed outside of render pass.
535+ EndRenderScope ();
519536 FlushBarriers ();
520537 vkCmdCopyBufferToImage (m_VkCmdBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
521538 }
@@ -527,11 +544,8 @@ class VulkanCommandBuffer
527544 const VkBufferImageCopy* pRegions)
528545 {
529546 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
530- if (m_State.RenderPass != VK_NULL_HANDLE)
531- {
532- // Copy operations must be performed outside of render pass.
533- EndRenderPass ();
534- }
547+ // Copy operations must be performed outside of render pass.
548+ EndRenderScope ();
535549 FlushBarriers ();
536550 vkCmdCopyImageToBuffer (m_VkCmdBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
537551 }
@@ -545,11 +559,8 @@ class VulkanCommandBuffer
545559 VkFilter filter)
546560 {
547561 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
548- if (m_State.RenderPass != VK_NULL_HANDLE)
549- {
550- // Blit must be performed outside of render pass.
551- EndRenderPass ();
552- }
562+ // Blit must be performed outside of render pass.
563+ EndRenderScope ();
553564 FlushBarriers ();
554565 vkCmdBlitImage (m_VkCmdBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter);
555566 }
@@ -562,11 +573,8 @@ class VulkanCommandBuffer
562573 const VkImageResolve* pRegions)
563574 {
564575 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
565- if (m_State.RenderPass != VK_NULL_HANDLE)
566- {
567- // Resolve must be performed outside of render pass.
568- EndRenderPass ();
569- }
576+ // Resolve must be performed outside of render pass.
577+ EndRenderScope ();
570578 FlushBarriers ();
571579 vkCmdResolveImage (m_VkCmdBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
572580 }
@@ -593,7 +601,7 @@ class VulkanCommandBuffer
593601
594602 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
595603 vkCmdBeginQuery (m_VkCmdBuffer, queryPool, query, flags);
596- if (m_State. RenderPass != VK_NULL_HANDLE )
604+ if (IsInRenderScope () )
597605 m_State.InsidePassQueries |= queryFlag;
598606 else
599607 m_State.OutsidePassQueries |= queryFlag;
@@ -605,7 +613,7 @@ class VulkanCommandBuffer
605613 {
606614 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
607615 vkCmdEndQuery (m_VkCmdBuffer, queryPool, query);
608- if (m_State. RenderPass != VK_NULL_HANDLE )
616+ if (IsInRenderScope () )
609617 {
610618 VERIFY ((m_State.InsidePassQueries & queryFlag) != 0 , " No active inside-pass queries found." );
611619 m_State.InsidePassQueries &= ~queryFlag;
@@ -630,11 +638,8 @@ class VulkanCommandBuffer
630638 uint32_t queryCount)
631639 {
632640 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
633- if (m_State.RenderPass != VK_NULL_HANDLE)
634- {
635- // Query pool reset must be performed outside of render pass (17.2).
636- EndRenderPass ();
637- }
641+ // Query pool reset must be performed outside of render pass (17.2).
642+ EndRenderScope ();
638643 FlushBarriers ();
639644 vkCmdResetQueryPool (m_VkCmdBuffer, queryPool, firstQuery, queryCount);
640645 }
@@ -648,11 +653,8 @@ class VulkanCommandBuffer
648653 VkQueryResultFlags flags)
649654 {
650655 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
651- if (m_State.RenderPass != VK_NULL_HANDLE)
652- {
653- // Copy query results must be performed outside of render pass.
654- EndRenderPass ();
655- }
656+ // Copy query results must be performed outside of render pass.
657+ EndRenderScope ();
656658 FlushBarriers ();
657659 vkCmdCopyQueryPoolResults (m_VkCmdBuffer, queryPool, firstQuery, queryCount,
658660 dstBuffer, dstOffset, stride, flags);
@@ -664,11 +666,8 @@ class VulkanCommandBuffer
664666 {
665667#if DILIGENT_USE_VOLK
666668 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
667- if (m_State.RenderPass != VK_NULL_HANDLE)
668- {
669- // Build AS operations must be performed outside of render pass.
670- EndRenderPass ();
671- }
669+ // Build AS operations must be performed outside of render pass.
670+ EndRenderScope ();
672671 FlushBarriers ();
673672 vkCmdBuildAccelerationStructuresKHR (m_VkCmdBuffer, infoCount, pInfos, ppBuildRangeInfos);
674673#else
@@ -680,11 +679,8 @@ class VulkanCommandBuffer
680679 {
681680#if DILIGENT_USE_VOLK
682681 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
683- if (m_State.RenderPass != VK_NULL_HANDLE)
684- {
685- // Copy AS operations must be performed outside of render pass.
686- EndRenderPass ();
687- }
682+ // Copy AS operations must be performed outside of render pass.
683+ EndRenderScope ();
688684 FlushBarriers ();
689685 vkCmdCopyAccelerationStructureKHR (m_VkCmdBuffer, &Info);
690686#else
@@ -696,11 +692,8 @@ class VulkanCommandBuffer
696692 {
697693#if DILIGENT_USE_VOLK
698694 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
699- if (m_State.RenderPass != VK_NULL_HANDLE)
700- {
701- // Write AS properties operations must be performed outside of render pass.
702- EndRenderPass ();
703- }
695+ // Write AS properties operations must be performed outside of render pass.
696+ EndRenderScope ();
704697 FlushBarriers ();
705698 vkCmdWriteAccelerationStructuresPropertiesKHR (m_VkCmdBuffer, 1 , &accelerationStructure, queryType, queryPool, firstQuery);
706699#else
@@ -719,10 +712,7 @@ class VulkanCommandBuffer
719712#if DILIGENT_USE_VOLK
720713 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
721714 VERIFY (m_State.RayTracingPipeline != VK_NULL_HANDLE, " No ray tracing pipeline bound" );
722- if (m_State.RenderPass != VK_NULL_HANDLE)
723- {
724- EndRenderPass ();
725- }
715+ EndRenderScope ();
726716 FlushBarriers ();
727717 vkCmdTraceRaysKHR (m_VkCmdBuffer, &RaygenShaderBindingTable, &MissShaderBindingTable, &HitShaderBindingTable, &CallableShaderBindingTable, width, height, depth);
728718#else
@@ -739,10 +729,7 @@ class VulkanCommandBuffer
739729#if DILIGENT_USE_VOLK
740730 VERIFY_EXPR (m_VkCmdBuffer != VK_NULL_HANDLE);
741731 VERIFY (m_State.RayTracingPipeline != VK_NULL_HANDLE, " No ray tracing pipeline bound" );
742- if (m_State.RenderPass != VK_NULL_HANDLE)
743- {
744- EndRenderPass ();
745- }
732+ EndRenderScope ();
746733 FlushBarriers ();
747734 vkCmdTraceRaysIndirectKHR (m_VkCmdBuffer, &RaygenShaderBindingTable, &MissShaderBindingTable, &HitShaderBindingTable, &CallableShaderBindingTable, indirectDeviceAddress);
748735#else
@@ -828,8 +815,11 @@ class VulkanCommandBuffer
828815 uint32_t FramebufferHeight = 0 ;
829816 uint32_t InsidePassQueries = 0 ;
830817 uint32_t OutsidePassQueries = 0 ;
818+ bool RenderingBegan = false ;
831819 };
832820
821+ __forceinline bool IsInRenderScope () const { return m_State.RenderPass != VK_NULL_HANDLE || m_State.RenderingBegan ; }
822+
833823 const StateCache& GetState () const { return m_State; }
834824
835825private:
0 commit comments