From d328832552057aa67c09231498e05b5783ed5fbb Mon Sep 17 00:00:00 2001 From: Sylvain Doremus Date: Mon, 29 May 2023 17:03:24 +0200 Subject: [PATCH] Added support for indirect compute and draw. --- .../RenderGraph/FrameGraphPrerequisites.hpp | 26 ++++++++++++++++++- include/RenderGraph/GraphContext.hpp | 3 +++ .../RunnablePasses/ComputePass.hpp | 11 ++++++++ .../RunnablePasses/RenderMeshConfig.hpp | 11 ++++++++ .../RunnablePasses/RenderQuadConfig.hpp | 11 ++++++++ source/RenderGraph/GraphContext.cpp | 3 +++ .../RunnablePasses/ComputePass.cpp | 14 ++++++++-- .../RunnablePasses/RenderMeshHolder.cpp | 19 +++++++++++--- .../RunnablePasses/RenderQuadHolder.cpp | 13 ++++++++-- 9 files changed, 103 insertions(+), 8 deletions(-) diff --git a/include/RenderGraph/FrameGraphPrerequisites.hpp b/include/RenderGraph/FrameGraphPrerequisites.hpp index 7ac1292..56a9ef4 100644 --- a/include/RenderGraph/FrameGraphPrerequisites.hpp +++ b/include/RenderGraph/FrameGraphPrerequisites.hpp @@ -341,7 +341,21 @@ namespace crg VkDeviceMemory memory; }; - using IndexBufferPtr = std::unique_ptr< IndexBuffer >; + struct IndirectBuffer + { + explicit IndirectBuffer( Buffer pbuffer + , uint32_t pstride + , VkDeviceSize poffset = {} ) + : buffer{ std::move( pbuffer ) } + , offset{ poffset } + , stride{ pstride } + { + } + + Buffer buffer; + VkDeviceSize offset; + uint32_t stride; + }; static constexpr VkPipelineColorBlendAttachmentState DefaultBlendState{ VK_FALSE , VK_BLEND_FACTOR_ONE @@ -383,6 +397,16 @@ namespace crg } }; + template<> + struct DefaultValueGetterT< IndirectBuffer > + { + static IndirectBuffer get() + { + IndirectBuffer const result{ Buffer{ VkBuffer{}, std::string{} }, 0u }; + return result; + } + }; + template< typename TypeT > struct RawTyperT { diff --git a/include/RenderGraph/GraphContext.hpp b/include/RenderGraph/GraphContext.hpp index 5636d10..e903c8a 100644 --- a/include/RenderGraph/GraphContext.hpp +++ b/include/RenderGraph/GraphContext.hpp @@ -537,8 +537,11 @@ namespace crg DECL_vkFunction( CmdClearColorImage ); DECL_vkFunction( CmdClearDepthStencilImage ); DECL_vkFunction( CmdDispatch ); + DECL_vkFunction( CmdDispatchIndirect ); DECL_vkFunction( CmdDraw ); DECL_vkFunction( CmdDrawIndexed ); + DECL_vkFunction( CmdDrawIndexedIndirect ); + DECL_vkFunction( CmdDrawIndirect ); DECL_vkFunction( CmdBeginRenderPass ); DECL_vkFunction( CmdEndRenderPass ); DECL_vkFunction( CmdPushConstants ); diff --git a/include/RenderGraph/RunnablePasses/ComputePass.hpp b/include/RenderGraph/RunnablePasses/ComputePass.hpp index 24551e5..c5d869b 100644 --- a/include/RenderGraph/RunnablePasses/ComputePass.hpp +++ b/include/RenderGraph/RunnablePasses/ComputePass.hpp @@ -160,6 +160,15 @@ namespace crg m_groupCountZ = config; return *this; } + /** + *\param[in] config + * The buffer used during indirect compute. + */ + auto & indirectBuffer( IndirectBuffer config ) + { + m_indirectBuffer = config; + return *this; + } pp::ConfigT< WrapperT > m_baseConfig{}; WrapperT< RunnablePass::InitialiseCallback > m_initialise{}; @@ -171,6 +180,7 @@ namespace crg WrapperT< uint32_t > m_groupCountX{}; WrapperT< uint32_t > m_groupCountY{}; WrapperT< uint32_t > m_groupCountZ{}; + WrapperT< IndirectBuffer > m_indirectBuffer{}; }; template<> @@ -185,6 +195,7 @@ namespace crg RawTypeT< uint32_t > groupCountX{ 1u }; RawTypeT< uint32_t > groupCountY{ 1u }; RawTypeT< uint32_t > groupCountZ{ 1u }; + RawTypeT< IndirectBuffer > indirectBuffer{ defaultV< IndirectBuffer > }; }; using Config = ConfigT< std::optional >; diff --git a/include/RenderGraph/RunnablePasses/RenderMeshConfig.hpp b/include/RenderGraph/RunnablePasses/RenderMeshConfig.hpp index 9396142..ba9f1d7 100644 --- a/include/RenderGraph/RunnablePasses/RenderMeshConfig.hpp +++ b/include/RenderGraph/RunnablePasses/RenderMeshConfig.hpp @@ -169,6 +169,15 @@ namespace crg } /** *\param[in] config + * The indirect buffer. + */ + auto & indirectBuffer( IndirectBuffer config ) + { + m_indirectBuffer = config; + return *this; + } + /** + *\param[in] config * The primitive count retrieval callback. */ auto & getPrimitiveCount( GetPrimitiveCountCallback config ) @@ -218,6 +227,7 @@ namespace crg WrapperT< VkExtent2D > m_renderSize{}; WrapperT< VertexBuffer > m_vertexBuffer{}; WrapperT< IndexBuffer > m_indexBuffer{}; + WrapperT< IndirectBuffer > m_indirectBuffer{}; }; template<> @@ -235,6 +245,7 @@ namespace crg RawTypeT< GetCullModeCallback > getCullMode{}; RawTypeT< VertexBuffer > vertexBuffer{}; RawTypeT< IndexBuffer > indexBuffer{}; + RawTypeT< IndirectBuffer > indirectBuffer{ defaultV< IndirectBuffer > }; }; using Config = ConfigT< std::optional >; diff --git a/include/RenderGraph/RunnablePasses/RenderQuadConfig.hpp b/include/RenderGraph/RunnablePasses/RenderQuadConfig.hpp index 6d64529..9eb723b 100644 --- a/include/RenderGraph/RunnablePasses/RenderQuadConfig.hpp +++ b/include/RenderGraph/RunnablePasses/RenderQuadConfig.hpp @@ -158,6 +158,15 @@ namespace crg m_instances = config; return *this; } + /** + *\param[in] config + * The indirect buffer. + */ + auto & indirectBuffer( IndirectBuffer config ) + { + m_indirectBuffer = config; + return *this; + } pp::ConfigT< WrapperT > m_baseConfig{}; WrapperT< Texcoord > m_texcoordConfig{}; @@ -170,6 +179,7 @@ namespace crg WrapperT< RunnablePass::RecordCallback > m_end{}; WrapperT< uint32_t > m_instances{}; WrapperT< VkExtent2D > m_renderSize{}; + WrapperT< IndirectBuffer > m_indirectBuffer{}; }; template<> @@ -184,6 +194,7 @@ namespace crg RawTypeT< RunnablePass::RecordCallback > recordInto; RawTypeT< RunnablePass::RecordCallback > end; RawTypeT< uint32_t > m_instances; + RawTypeT< IndirectBuffer > indirectBuffer{ Buffer{ VkBuffer{}, std::string{} }, 0u }; }; using Config = ConfigT< std::optional >; diff --git a/source/RenderGraph/GraphContext.cpp b/source/RenderGraph/GraphContext.cpp index bd456fc..b82352b 100644 --- a/source/RenderGraph/GraphContext.cpp +++ b/source/RenderGraph/GraphContext.cpp @@ -102,8 +102,11 @@ namespace crg DECL_vkFunction( CmdClearColorImage ); DECL_vkFunction( CmdClearDepthStencilImage ); DECL_vkFunction( CmdDispatch ); + DECL_vkFunction( CmdDispatchIndirect ); DECL_vkFunction( CmdDraw ); DECL_vkFunction( CmdDrawIndexed ); + DECL_vkFunction( CmdDrawIndexedIndirect ); + DECL_vkFunction( CmdDrawIndirect ); DECL_vkFunction( CmdBeginRenderPass ); DECL_vkFunction( CmdEndRenderPass ); DECL_vkFunction( CmdPushConstants ); diff --git a/source/RenderGraph/RunnablePasses/ComputePass.cpp b/source/RenderGraph/RunnablePasses/ComputePass.cpp index fc2f822..8bad21e 100644 --- a/source/RenderGraph/RunnablePasses/ComputePass.cpp +++ b/source/RenderGraph/RunnablePasses/ComputePass.cpp @@ -34,7 +34,8 @@ namespace crg , cpConfig.m_end ? std::move( *cpConfig.m_end ) : getDefaultV< RunnablePass::RecordCallback >() , cpConfig.m_groupCountX ? std::move( *cpConfig.m_groupCountX ) : 1u , cpConfig.m_groupCountY ? std::move( *cpConfig.m_groupCountY ) : 1u - , cpConfig.m_groupCountZ ? std::move( *cpConfig.m_groupCountZ ) : 1u } + , cpConfig.m_groupCountZ ? std::move( *cpConfig.m_groupCountZ ) : 1u + , cpConfig.m_indirectBuffer ? *cpConfig.m_indirectBuffer : getDefaultV < IndirectBuffer >() } , m_pipeline{ pass , context , graph @@ -80,7 +81,16 @@ namespace crg { m_pipeline.recordInto( context, commandBuffer, index ); m_cpConfig.recordInto( context, commandBuffer, index ); - m_context.vkCmdDispatch( commandBuffer, m_cpConfig.groupCountX, m_cpConfig.groupCountY, m_cpConfig.groupCountZ ); + + if ( auto indirectBuffer = m_cpConfig.indirectBuffer.buffer.buffer( index ) ) + { + m_context.vkCmdDispatchIndirect( commandBuffer, indirectBuffer, m_cpConfig.indirectBuffer.offset ); + } + else + { + m_context.vkCmdDispatch( commandBuffer, m_cpConfig.groupCountX, m_cpConfig.groupCountY, m_cpConfig.groupCountZ ); + } + m_cpConfig.end( context, commandBuffer, index ); } diff --git a/source/RenderGraph/RunnablePasses/RenderMeshHolder.cpp b/source/RenderGraph/RunnablePasses/RenderMeshHolder.cpp index 1a8e224..fa48390 100644 --- a/source/RenderGraph/RunnablePasses/RenderMeshHolder.cpp +++ b/source/RenderGraph/RunnablePasses/RenderMeshHolder.cpp @@ -24,7 +24,8 @@ namespace crg , config.m_getIndexType ? std::move( *config.m_getIndexType ) : getDefaultV< GetIndexTypeCallback >() , config.m_getCullMode ? std::move( *config.m_getCullMode ) : getDefaultV< GetCullModeCallback >() , config.m_vertexBuffer ? std::move( *config.m_vertexBuffer ) : getDefaultV< VertexBuffer >() - , config.m_indexBuffer ? std::move( *config.m_indexBuffer ) : getDefaultV< IndexBuffer >() } + , config.m_indexBuffer ? std::move( *config.m_indexBuffer ) : getDefaultV< IndexBuffer >() + , config.m_indirectBuffer ? *config.m_indirectBuffer : getDefaultV< IndirectBuffer >() } , m_context{ context } , m_pipeline{ pass , context @@ -114,9 +115,21 @@ namespace crg m_context.vkCmdBindVertexBuffers( commandBuffer, 0u, 1u, &m_config.vertexBuffer.buffer.buffer( index ), &offset ); } - if ( m_config.indexBuffer.buffer.buffer( index ) ) + if ( auto indirectBuffer = m_config.indirectBuffer.buffer.buffer( index ) ) { - m_context.vkCmdBindIndexBuffer( commandBuffer, m_config.indexBuffer.buffer.buffer( index ), offset, m_config.getIndexType() ); + if ( auto indexBuffer = m_config.indexBuffer.buffer.buffer( index ) ) + { + m_context.vkCmdBindIndexBuffer( commandBuffer, indexBuffer, offset, m_config.getIndexType() ); + m_context.vkCmdDrawIndexedIndirect( commandBuffer, indirectBuffer, m_config.indirectBuffer.offset, 1u, m_config.indirectBuffer.stride ); + } + else + { + m_context.vkCmdDrawIndirect( commandBuffer, indirectBuffer, m_config.indirectBuffer.offset, 1u, m_config.indirectBuffer.stride ); + } + } + else if ( auto indexBuffer = m_config.indexBuffer.buffer.buffer( index ) ) + { + m_context.vkCmdBindIndexBuffer( commandBuffer, indexBuffer, offset, m_config.getIndexType() ); m_context.vkCmdDrawIndexed( commandBuffer, m_config.getPrimitiveCount(), 1u, 0u, 0u, 0u ); } else diff --git a/source/RenderGraph/RunnablePasses/RenderQuadHolder.cpp b/source/RenderGraph/RunnablePasses/RenderQuadHolder.cpp index 2b0a9f0..18e85d2 100644 --- a/source/RenderGraph/RunnablePasses/RenderQuadHolder.cpp +++ b/source/RenderGraph/RunnablePasses/RenderQuadHolder.cpp @@ -23,7 +23,8 @@ namespace crg , config.m_isEnabled , config.m_recordInto ? std::move( *config.m_recordInto ) : getDefaultV< RunnablePass::RecordCallback >() , config.m_end ? std::move( *config.m_end ) : getDefaultV< RunnablePass::RecordCallback >() - , config.m_instances ? std::move( *config.m_instances ) : 1u } + , config.m_instances ? std::move( *config.m_instances ) : 1u + , config.m_indirectBuffer ? *config.m_indirectBuffer : getDefaultV < IndirectBuffer >() } , m_context{ context } , m_graph{ graph } , m_pipeline{ pass @@ -110,7 +111,15 @@ namespace crg m_config.recordInto( context, commandBuffer, index ); VkDeviceSize offset{}; m_context.vkCmdBindVertexBuffers( commandBuffer, 0u, 1u, &m_vertexBuffer->buffer.buffer( index ), &offset ); - m_context.vkCmdDraw( commandBuffer, 3u, m_config.m_instances, 0u, 0u ); + + if ( auto indirectBuffer = m_config.indirectBuffer.buffer.buffer( index ) ) + { + m_context.vkCmdDrawIndirect( commandBuffer, indirectBuffer, m_config.indirectBuffer.offset, 1u, m_config.indirectBuffer.stride ); + } + else + { + m_context.vkCmdDraw( commandBuffer, 3u, m_config.m_instances, 0u, 0u ); + } } void RenderQuadHolder::end( RecordContext & context