diff --git a/include/RenderGraph/Attachment.hpp b/include/RenderGraph/Attachment.hpp index 78f6163..a0780b4 100644 --- a/include/RenderGraph/Attachment.hpp +++ b/include/RenderGraph/Attachment.hpp @@ -238,6 +238,7 @@ namespace crg Uniform = 0x01 << 0, Storage = 0x01 << 1, View = 0x01 << 2, + Clearable = 0x01 << 4, UniformView = Uniform | View, StorageView = Storage | View, }; @@ -274,6 +275,11 @@ namespace crg return hasFlag( Flag::View ); } + bool isClearable()const + { + return hasFlag( Flag::Clearable ); + } + bool isUniformView()const { return isUniform() && isView(); @@ -402,6 +408,13 @@ namespace crg return isBuffer() && buffer.isStorage(); } + bool isClearableBuffer()const + { + return isBuffer() + && isOutput() + && buffer.isClearable(); + } + bool isStorageBufferView()const { return isBuffer() && buffer.isStorageView(); diff --git a/include/RenderGraph/FramePass.hpp b/include/RenderGraph/FramePass.hpp index 04b0bb1..ae0e1a8 100644 --- a/include/RenderGraph/FramePass.hpp +++ b/include/RenderGraph/FramePass.hpp @@ -110,6 +110,14 @@ namespace crg , VkDeviceSize range ); /** *\brief + * Creates a storage buffer attachment that will be cleared a the beginning of the pass. + */ + CRG_API void addClearableOutputStorageBuffer( Buffer buffer + , uint32_t binding + , VkDeviceSize offset + , VkDeviceSize range ); + /** + *\brief * Creates a storage buffer attachment. */ CRG_API void addInOutStorageBuffer( Buffer buffer diff --git a/source/RenderGraph/FramePass.cpp b/source/RenderGraph/FramePass.cpp index 2f60309..3ccfab6 100644 --- a/source/RenderGraph/FramePass.cpp +++ b/source/RenderGraph/FramePass.cpp @@ -322,6 +322,23 @@ namespace crg , range } ); } + void FramePass::addClearableOutputStorageBuffer( Buffer buffer + , uint32_t binding + , VkDeviceSize offset + , VkDeviceSize range ) + { + auto attachName = fpass::adjustName( *this, buffer.name ) + "OSB"; + buffers.push_back( Attachment{ Attachment::FlagKind( Attachment::Flag::Output ) + , *this + , binding + , std::move( attachName ) + , ( BufferAttachment::FlagKind( BufferAttachment::Flag::Storage ) + | BufferAttachment::FlagKind( BufferAttachment::Flag::Clearable ) ) + , buffer + , offset + , range } ); + } + void FramePass::addInOutStorageBuffer( Buffer buffer , uint32_t binding , VkDeviceSize offset diff --git a/source/RenderGraph/RunnablePass.cpp b/source/RenderGraph/RunnablePass.cpp index a0a244c..7feae29 100644 --- a/source/RenderGraph/RunnablePass.cpp +++ b/source/RenderGraph/RunnablePass.cpp @@ -17,6 +17,17 @@ See LICENSE file in root folder. namespace crg { + namespace details + { + static constexpr VkDeviceSize getAlignedSize( VkDeviceSize size, VkDeviceSize align ) + { + auto rem = size % align; + return ( rem + ? size + ( align - rem ) + : size ); + } + } + //********************************************************************************************* void convert( SemaphoreWaitArray const & toWait @@ -429,6 +440,24 @@ namespace crg auto buffer = attach.buffer; auto currentState = context.getAccessState( buffer.buffer.buffer , buffer.range ); + + if ( attach.isClearableBuffer() ) + { + context.memoryBarrier( commandBuffer + , buffer.buffer.buffer + , buffer.range + , currentState.access + , currentState.pipelineStage + , { VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT } ); + m_context.vkCmdFillBuffer( commandBuffer + , buffer.buffer.buffer + , buffer.range.offset == 0u ? 0u : details::getAlignedSize( buffer.range.offset, 4u ) + , buffer.range.size == VK_WHOLE_SIZE ? VK_WHOLE_SIZE : details::getAlignedSize( buffer.range.size, 4u ) + , 0u ); + currentState.access = VK_ACCESS_TRANSFER_WRITE_BIT; + currentState.pipelineStage = VK_PIPELINE_STAGE_TRANSFER_BIT; + } + context.memoryBarrier( commandBuffer , buffer.buffer.buffer , buffer.range