diff options
| author | lucy96chen <47800040+lucy96chen@users.noreply.github.com> | 2022-05-26 10:54:35 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-05-26 10:54:35 -0700 |
| commit | 43e1b7cdc70b2fcac8a3e8ee72f5bc91726f4ec5 (patch) | |
| tree | 1e4701b4ab324a199b81e1f6c671f6660f1050c5 /tools/gfx/vulkan/vk-command-buffer.cpp | |
| parent | 5ff4f42c636a67724523e4fe60697cfac64908cd (diff) | |
Split render-vk.h/.cpp into a set of smaller files (#2244)
* Some preliminary work on splitting render-vk
* render-vk split, tests currently crash on null reference
* fixed circular include
Diffstat (limited to 'tools/gfx/vulkan/vk-command-buffer.cpp')
| -rw-r--r-- | tools/gfx/vulkan/vk-command-buffer.cpp | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/tools/gfx/vulkan/vk-command-buffer.cpp b/tools/gfx/vulkan/vk-command-buffer.cpp new file mode 100644 index 000000000..8e0b35750 --- /dev/null +++ b/tools/gfx/vulkan/vk-command-buffer.cpp @@ -0,0 +1,171 @@ +// vk-command-buffer.cpp +#include "vk-command-buffer.h" + +#include "vk-device.h" +#include "vk-shader-object.h" +#include "vk-util.h" + +namespace gfx +{ + +using namespace Slang; + +namespace vk +{ + +// There are a pair of cyclic references between a `TransientResourceHeap` and +// a `CommandBuffer` created from the heap. We need to break the cycle when +// the public reference count of a command buffer drops to 0. + +ICommandBuffer* CommandBufferImpl::getInterface(const Guid& guid) +{ + if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_ICommandBuffer) + return static_cast<ICommandBuffer*>(this); + return nullptr; +} + +void CommandBufferImpl::comFree() { m_transientHeap.breakStrongReference(); } + +Result CommandBufferImpl::init( + DeviceImpl* renderer, VkCommandPool pool, TransientResourceHeapImpl* transientHeap) +{ + m_renderer = renderer; + m_transientHeap = transientHeap; + m_pool = pool; + + auto& api = renderer->m_api; + VkCommandBufferAllocateInfo allocInfo = {}; + allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocInfo.commandPool = pool; + allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocInfo.commandBufferCount = 1; + SLANG_VK_RETURN_ON_FAIL( + api.vkAllocateCommandBuffers(api.m_device, &allocInfo, &m_commandBuffer)); + + beginCommandBuffer(); + return SLANG_OK; +} + +void CommandBufferImpl::beginCommandBuffer() +{ + auto& api = m_renderer->m_api; + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + nullptr, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT}; + api.vkBeginCommandBuffer(m_commandBuffer, &beginInfo); + if (m_preCommandBuffer) + { + api.vkBeginCommandBuffer(m_preCommandBuffer, &beginInfo); + } + m_isPreCommandBufferEmpty = true; +} + +Result CommandBufferImpl::createPreCommandBuffer() +{ + VkCommandBufferAllocateInfo allocInfo = {}; + allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocInfo.commandPool = m_pool; + allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocInfo.commandBufferCount = 1; + auto& api = m_renderer->m_api; + SLANG_VK_RETURN_ON_FAIL( + api.vkAllocateCommandBuffers(api.m_device, &allocInfo, &m_preCommandBuffer)); + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + nullptr, + VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT}; + api.vkBeginCommandBuffer(m_preCommandBuffer, &beginInfo); + return SLANG_OK; +} + +VkCommandBuffer CommandBufferImpl::getPreCommandBuffer() +{ + m_isPreCommandBufferEmpty = false; + if (m_preCommandBuffer) + return m_preCommandBuffer; + createPreCommandBuffer(); + return m_preCommandBuffer; +} + +void CommandBufferImpl::encodeRenderCommands( + IRenderPassLayout* renderPass, IFramebuffer* framebuffer, IRenderCommandEncoder** outEncoder) +{ + if (!m_renderCommandEncoder) + { + m_renderCommandEncoder = new RenderCommandEncoder(); + m_renderCommandEncoder->init(this); + } + m_renderCommandEncoder->beginPass(renderPass, framebuffer); + *outEncoder = m_renderCommandEncoder.Ptr(); +} + +void CommandBufferImpl::encodeComputeCommands(IComputeCommandEncoder** outEncoder) +{ + if (!m_computeCommandEncoder) + { + m_computeCommandEncoder = new ComputeCommandEncoder(); + m_computeCommandEncoder->init(this); + } + *outEncoder = m_computeCommandEncoder.Ptr(); +} + +void CommandBufferImpl::encodeResourceCommands(IResourceCommandEncoder** outEncoder) +{ + if (!m_resourceCommandEncoder) + { + m_resourceCommandEncoder = new ResourceCommandEncoder(); + m_resourceCommandEncoder->init(this); + } + *outEncoder = m_resourceCommandEncoder.Ptr(); +} + +void CommandBufferImpl::encodeRayTracingCommands(IRayTracingCommandEncoder** outEncoder) +{ + if (!m_rayTracingCommandEncoder) + { + if (m_renderer->m_api.vkCmdBuildAccelerationStructuresKHR) + { + m_rayTracingCommandEncoder = new RayTracingCommandEncoder(); + m_rayTracingCommandEncoder->init(this); + } + } + *outEncoder = m_rayTracingCommandEncoder.Ptr(); +} + +void CommandBufferImpl::close() +{ + auto& vkAPI = m_renderer->m_api; + if (!m_isPreCommandBufferEmpty) + { + // `preCmdBuffer` contains buffer transfer commands for shader object + // uniform buffers, and we need a memory barrier here to ensure the + // transfers are visible to shaders. + VkMemoryBarrier memBarrier = {VK_STRUCTURE_TYPE_MEMORY_BARRIER}; + memBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + memBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + vkAPI.vkCmdPipelineBarrier( + m_preCommandBuffer, + VK_PIPELINE_STAGE_TRANSFER_BIT, + VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, + 0, + 1, + &memBarrier, + 0, + nullptr, + 0, + nullptr); + vkAPI.vkEndCommandBuffer(m_preCommandBuffer); + } + vkAPI.vkEndCommandBuffer(m_commandBuffer); +} + +Result CommandBufferImpl::getNativeHandle(InteropHandle* outHandle) +{ + outHandle->api = InteropHandleAPI::Vulkan; + outHandle->handleValue = (uint64_t)m_commandBuffer; + return SLANG_OK; +} + +} // namespace vk +} // namespace gfx |
