yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
f65d756bf
master
1// vk-command-buffer.cpp 2#include "vk-command-buffer.h" 3 4#include "vk-device.h" 5#include "vk-shader-object.h" 6#include "vk-util.h" 7 8namespace gfx 9{ 10 11using namespace Slang ; 12 13namespace vk 14{ 15 16// There are a pair of cyclic references between a `TransientResourceHeap` and 17// a `CommandBuffer` created from the heap. We need to break the cycle when 18// the public reference count of a command buffer drops to 0. 19 20ICommandBuffer * CommandBufferImpl ::getInterface (const Guid & guid ) 21{ 22if (guid == GfxGUID ::IID_ISlangUnknown || guid == GfxGUID ::IID_ICommandBuffer ) 23return static_cast < ICommandBuffer *> (this ); 24return nullptr ; 25} 26 27void CommandBufferImpl ::comFree () 28{ 29m_transientHeap .breakStrongReference (); 30} 31 32Result CommandBufferImpl ::init ( 33DeviceImpl * renderer , 34VkCommandPool pool , 35TransientResourceHeapImpl * transientHeap ) 36{ 37m_renderer = renderer ; 38m_transientHeap = transientHeap ; 39m_pool = pool ; 40 41auto & api = renderer -> m_api ; 42VkCommandBufferAllocateInfo allocInfo = {}; 43allocInfo .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO ; 44allocInfo .commandPool = pool ; 45allocInfo .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY ; 46allocInfo .commandBufferCount = 1 ; 47SLANG_VK_RETURN_ON_FAIL ( 48api .vkAllocateCommandBuffers (api .m_device ,& allocInfo ,& m_commandBuffer )); 49 50beginCommandBuffer (); 51return SLANG_OK ; 52} 53 54void CommandBufferImpl ::beginCommandBuffer () 55{ 56auto & api = m_renderer -> m_api ; 57VkCommandBufferBeginInfo beginInfo = { 58VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO , 59nullptr , 60VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT }; 61api .vkBeginCommandBuffer (m_commandBuffer ,& beginInfo ); 62if (m_preCommandBuffer ) 63 { 64api .vkBeginCommandBuffer (m_preCommandBuffer ,& beginInfo ); 65 } 66m_isPreCommandBufferEmpty = true; 67} 68 69Result CommandBufferImpl ::createPreCommandBuffer () 70{ 71VkCommandBufferAllocateInfo allocInfo = {}; 72allocInfo .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO ; 73allocInfo .commandPool = m_pool ; 74allocInfo .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY ; 75allocInfo .commandBufferCount = 1 ; 76auto & api = m_renderer -> m_api ; 77SLANG_VK_RETURN_ON_FAIL ( 78api .vkAllocateCommandBuffers (api .m_device ,& allocInfo ,& m_preCommandBuffer )); 79VkCommandBufferBeginInfo beginInfo = { 80VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO , 81nullptr , 82VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT }; 83api .vkBeginCommandBuffer (m_preCommandBuffer ,& beginInfo ); 84return SLANG_OK ; 85} 86 87VkCommandBuffer CommandBufferImpl ::getPreCommandBuffer () 88{ 89m_isPreCommandBufferEmpty = false; 90if (m_preCommandBuffer ) 91return m_preCommandBuffer ; 92createPreCommandBuffer (); 93return m_preCommandBuffer ; 94} 95 96void CommandBufferImpl ::encodeRenderCommands ( 97IRenderPassLayout * renderPass , 98IFramebuffer * framebuffer , 99IRenderCommandEncoder ** outEncoder ) 100{ 101if (!m_renderCommandEncoder ) 102 { 103m_renderCommandEncoder = new RenderCommandEncoder (); 104m_renderCommandEncoder -> init (this ); 105 } 106m_renderCommandEncoder -> beginPass (renderPass ,framebuffer ); 107* outEncoder = m_renderCommandEncoder .Ptr (); 108} 109 110void CommandBufferImpl ::encodeComputeCommands (IComputeCommandEncoder ** outEncoder ) 111{ 112if (!m_computeCommandEncoder ) 113 { 114m_computeCommandEncoder = new ComputeCommandEncoder (); 115m_computeCommandEncoder -> init (this ); 116 } 117* outEncoder = m_computeCommandEncoder .Ptr (); 118} 119 120void CommandBufferImpl ::encodeResourceCommands (IResourceCommandEncoder ** outEncoder ) 121{ 122if (!m_resourceCommandEncoder ) 123 { 124m_resourceCommandEncoder = new ResourceCommandEncoder (); 125m_resourceCommandEncoder -> init (this ); 126 } 127* outEncoder = m_resourceCommandEncoder .Ptr (); 128} 129 130void CommandBufferImpl ::encodeRayTracingCommands (IRayTracingCommandEncoder ** outEncoder ) 131{ 132if (!m_rayTracingCommandEncoder ) 133 { 134if (m_renderer -> m_api .vkCmdBuildAccelerationStructuresKHR ) 135 { 136m_rayTracingCommandEncoder = new RayTracingCommandEncoder (); 137m_rayTracingCommandEncoder -> init (this ); 138 } 139 } 140* outEncoder = m_rayTracingCommandEncoder .Ptr (); 141} 142 143void CommandBufferImpl ::close () 144{ 145auto & vkAPI = m_renderer -> m_api ; 146if (!m_isPreCommandBufferEmpty ) 147 { 148// `preCmdBuffer` contains buffer transfer commands for shader object 149// uniform buffers, and we need a memory barrier here to ensure the 150// transfers are visible to shaders. 151VkMemoryBarrier memBarrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER }; 152memBarrier .srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT ; 153memBarrier .dstAccessMask = VK_ACCESS_MEMORY_READ_BIT ; 154vkAPI .vkCmdPipelineBarrier ( 155m_preCommandBuffer , 156VK_PIPELINE_STAGE_TRANSFER_BIT , 157VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT , 1580 , 1591 , 160& memBarrier , 1610 , 162nullptr , 1630 , 164nullptr ); 165vkAPI .vkEndCommandBuffer (m_preCommandBuffer ); 166 } 167vkAPI .vkEndCommandBuffer (m_commandBuffer ); 168} 169 170Result CommandBufferImpl ::getNativeHandle (InteropHandle * outHandle ) 171{ 172outHandle -> api = InteropHandleAPI ::Vulkan ; 173outHandle -> handleValue = (uint64_t )m_commandBuffer ; 174return SLANG_OK ; 175} 176 177}// namespace vk 178}// namespace gfx