summaryrefslogtreecommitdiffstats
path: root/tools/gfx/vulkan/render-vk.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gfx/vulkan/render-vk.cpp')
-rw-r--r--tools/gfx/vulkan/render-vk.cpp261
1 files changed, 167 insertions, 94 deletions
diff --git a/tools/gfx/vulkan/render-vk.cpp b/tools/gfx/vulkan/render-vk.cpp
index d4396429b..96a0d1047 100644
--- a/tools/gfx/vulkan/render-vk.cpp
+++ b/tools/gfx/vulkan/render-vk.cpp
@@ -50,7 +50,10 @@ public:
};
// Renderer implementation
Result initVulkanInstanceAndDevice(bool useValidationLayer);
- virtual SLANG_NO_THROW SlangResult SLANG_MCALL initialize(const Desc& desc) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL initialize(const Desc& desc) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL createTransientResourceHeap(
+ const ITransientResourceHeap::Desc& desc,
+ ITransientResourceHeap** outHeap) override;
virtual SLANG_NO_THROW Result SLANG_MCALL
createCommandQueue(const ICommandQueue::Desc& desc, ICommandQueue** outQueue) override;
virtual SLANG_NO_THROW Result SLANG_MCALL createSwapchain(
@@ -795,7 +798,6 @@ public:
auto descriptorSetIndex =
findOrAddDescriptorSet(typeLayout->getDescriptorSetSpaceOffset(s));
auto& descriptorSetInfo = m_descriptorSetBuildInfos[descriptorSetIndex];
-
for (SlangInt r = 0; r < descriptorRangeCount; ++r)
{
auto slangBindingType =
@@ -812,7 +814,6 @@ public:
}
auto vkDescriptorType = _mapDescriptorType(slangBindingType);
-
VkDescriptorSetLayoutBinding vkBindingRangeDesc = {};
vkBindingRangeDesc.binding =
(uint32_t)typeLayout->getDescriptorSetDescriptorRangeIndexOffset(s, r);
@@ -829,14 +830,6 @@ public:
}
descriptorSetInfo.vkBindings.add(vkBindingRangeDesc);
}
- VkDescriptorSetLayoutCreateInfo createInfo = {};
- createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
- createInfo.pBindings = descriptorSetInfo.vkBindings.getBuffer();
- createInfo.bindingCount = (uint32_t)descriptorSetInfo.vkBindings.getCount();
- VkDescriptorSetLayout vkDescSetLayout;
- SLANG_RETURN_ON_FAIL(m_renderer->m_api.vkCreateDescriptorSetLayout(
- m_renderer->m_api.m_device, &createInfo, nullptr, &vkDescSetLayout));
- descriptorSetInfo.descriptorSetLayout = vkDescSetLayout;
}
return SLANG_OK;
}
@@ -1019,6 +1012,19 @@ public:
m_combinedTextureSamplerCount = builder->m_combinedTextureSamplerCount;
m_subObjectCount = builder->m_subObjectCount;
m_subObjectRanges = builder->m_subObjectRanges;
+
+ // Create VkDescriptorSetLayout for all descriptor sets.
+ for (auto& descriptorSetInfo : m_descriptorSetInfos)
+ {
+ VkDescriptorSetLayoutCreateInfo createInfo = {};
+ createInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ createInfo.pBindings = descriptorSetInfo.vkBindings.getBuffer();
+ createInfo.bindingCount = (uint32_t)descriptorSetInfo.vkBindings.getCount();
+ VkDescriptorSetLayout vkDescSetLayout;
+ SLANG_RETURN_ON_FAIL(renderer->m_api.vkCreateDescriptorSetLayout(
+ renderer->m_api.m_device, &createInfo, nullptr, &vkDescSetLayout));
+ descriptorSetInfo.descriptorSetLayout = vkDescSetLayout;
+ }
return SLANG_OK;
}
@@ -1145,7 +1151,8 @@ public:
auto slangEntryPointLayout = entryPointLayout->getSlangLayout();
_addDescriptorSets(
- slangEntryPointLayout->getTypeLayout(), slangEntryPointLayout->getVarLayout());
+ _unwrapParameterGroups(slangEntryPointLayout->getTypeLayout()),
+ slangEntryPointLayout->getVarLayout());
m_entryPoints.add(info);
}
@@ -1210,7 +1217,7 @@ public:
m_program = builder->m_program;
m_programLayout = builder->m_programLayout;
- m_entryPoints = builder->m_entryPoints;
+ m_entryPoints = _Move(builder->m_entryPoints);
m_renderer = renderer;
if (m_program->getSpecializationParamCount() != 0)
@@ -2709,8 +2716,10 @@ public:
VkCommandBuffer m_commandBuffer;
VkCommandBuffer m_preCommandBuffer = VK_NULL_HANDLE;
VkCommandPool m_pool;
+ VkFence m_fence;
VKDevice* m_renderer;
DescriptorSetAllocator* m_transientDescSetAllocator;
+ bool m_isPreCommandBufferEmpty = true;
// Command buffers are deallocated by its command pool,
// so no need to free individually.
~CommandBufferImpl() = default;
@@ -2718,11 +2727,13 @@ public:
Result init(
VKDevice* renderer,
VkCommandPool pool,
+ VkFence fence,
DescriptorSetAllocator* transientDescSetAllocator)
{
m_renderer = renderer;
m_transientDescSetAllocator = transientDescSetAllocator;
m_pool = pool;
+ m_fence = fence;
auto& api = renderer->m_api;
VkCommandBufferAllocateInfo allocInfo = {};
@@ -2733,12 +2744,23 @@ public:
SLANG_VK_RETURN_ON_FAIL(
api.vkAllocateCommandBuffers(api.m_device, &allocInfo, &m_commandBuffer));
+ beginCommandBuffer();
+ return SLANG_OK;
+ }
+
+ void 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);
- return SLANG_OK;
+ if (m_preCommandBuffer)
+ {
+ api.vkBeginCommandBuffer(m_preCommandBuffer, &beginInfo);
+ }
+ m_isPreCommandBufferEmpty = true;
}
Result createPreCommandBuffer()
@@ -2761,6 +2783,7 @@ public:
VkCommandBuffer getPreCommandBuffer()
{
+ m_isPreCommandBufferEmpty = false;
if (m_preCommandBuffer)
return m_preCommandBuffer;
createPreCommandBuffer();
@@ -3191,7 +3214,7 @@ public:
virtual SLANG_NO_THROW void SLANG_MCALL close() override
{
auto& vkAPI = m_renderer->m_api;
- if (m_preCommandBuffer != VK_NULL_HANDLE)
+ if (!m_isPreCommandBufferEmpty)
{
// `preCmdBuffer` contains buffer transfer commands for shader object
// uniform buffers, and we need a memory barrier here to ensure the
@@ -3231,56 +3254,34 @@ public:
public:
Desc m_desc;
- uint32_t m_poolIndex;
RefPtr<VKDevice> m_renderer;
VkQueue m_queue;
uint32_t m_queueFamilyIndex;
VkSemaphore m_pendingWaitSemaphore = VK_NULL_HANDLE;
List<VkCommandBuffer> m_submitCommandBuffers;
- static const int kCommandPoolCount = 8;
- VkCommandPool m_commandPools[kCommandPoolCount];
- DescriptorSetAllocator m_descSetAllocators[kCommandPoolCount];
- VkFence m_fences[kCommandPoolCount];
- VkSemaphore m_semaphores[kCommandPoolCount];
+ static const int kSemaphoreCount = 2;
+ uint32_t m_currentSemaphoreIndex;
+ VkSemaphore m_semaphores[kSemaphoreCount];
~CommandQueueImpl()
{
m_renderer->m_api.vkQueueWaitIdle(m_queue);
m_renderer->m_queueAllocCount--;
- for (int i = 0; i < kCommandPoolCount; i++)
+ for (int i = 0; i < kSemaphoreCount; i++)
{
- m_renderer->m_api.vkDestroyCommandPool(
- m_renderer->m_api.m_device, m_commandPools[i], nullptr);
- m_renderer->m_api.vkDestroyFence(m_renderer->m_api.m_device, m_fences[i], nullptr);
m_renderer->m_api.vkDestroySemaphore(
m_renderer->m_api.m_device, m_semaphores[i], nullptr);
- m_descSetAllocators[i].close();
}
}
void init(VKDevice* renderer, VkQueue queue, uint32_t queueFamilyIndex)
{
m_renderer = renderer;
- m_poolIndex = 0;
+ m_currentSemaphoreIndex = 0;
m_queue = queue;
m_queueFamilyIndex = queueFamilyIndex;
- for (int i = 0; i < kCommandPoolCount; i++)
+ for (int i = 0; i < kSemaphoreCount; i++)
{
- m_descSetAllocators[i].m_api = &m_renderer->m_api;
-
- VkCommandPoolCreateInfo poolCreateInfo = {};
- poolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
- poolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
- poolCreateInfo.queueFamilyIndex = queueFamilyIndex;
- m_renderer->m_api.vkCreateCommandPool(
- m_renderer->m_api.m_device, &poolCreateInfo, nullptr, &m_commandPools[i]);
-
- VkFenceCreateInfo fenceCreateInfo = {};
- fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
- fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
- m_renderer->m_api.vkCreateFence(
- m_renderer->m_api.m_device, &fenceCreateInfo, nullptr, &m_fences[i]);
-
VkSemaphoreCreateInfo semaphoreCreateInfo = {};
semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
semaphoreCreateInfo.flags = 0;
@@ -3289,24 +3290,6 @@ public:
}
}
- // Swaps to and resets the next command pool.
- // Wait if command lists in the next pool are still in flight.
- Result swapPools()
- {
- auto& vkAPI = m_renderer->m_api;
- m_poolIndex++;
- m_poolIndex = m_poolIndex % kCommandPoolCount;
-
- if (vkAPI.vkWaitForFences(vkAPI.m_device, 1, &m_fences[m_poolIndex], 1, UINT64_MAX) !=
- VK_SUCCESS)
- {
- return SLANG_FAIL;
- }
- vkAPI.vkResetCommandPool(vkAPI.m_device, m_commandPools[m_poolIndex], 0);
- m_descSetAllocators[m_poolIndex].reset();
- return SLANG_OK;
- }
-
virtual SLANG_NO_THROW void SLANG_MCALL wait() override
{
auto& vkAPI = m_renderer->m_api;
@@ -3318,33 +3301,26 @@ public:
return m_desc;
}
- virtual SLANG_NO_THROW Result SLANG_MCALL
- createCommandBuffer(ICommandBuffer** result) override
- {
- RefPtr<CommandBufferImpl> commandBuffer = new CommandBufferImpl();
- SLANG_RETURN_ON_FAIL(commandBuffer->init(
- m_renderer, m_commandPools[m_poolIndex], &m_descSetAllocators[m_poolIndex]));
- *result = commandBuffer.detach();
- return SLANG_OK;
- }
-
virtual SLANG_NO_THROW void SLANG_MCALL
executeCommandBuffers(
uint32_t count,
ICommandBuffer* const* commandBuffers) override
{
+ if (count == 0)
+ return;
+
auto& vkAPI = m_renderer->m_api;
m_submitCommandBuffers.clear();
for (uint32_t i = 0; i < count; i++)
{
auto cmdBufImpl = static_cast<CommandBufferImpl*>(commandBuffers[i]);
- if (cmdBufImpl->m_preCommandBuffer != VK_NULL_HANDLE)
+ if (!cmdBufImpl->m_isPreCommandBufferEmpty)
m_submitCommandBuffers.add(cmdBufImpl->m_preCommandBuffer);
auto vkCmdBuf = cmdBufImpl->m_commandBuffer;
m_submitCommandBuffers.add(vkCmdBuf);
}
VkSemaphore waitSemaphore = m_pendingWaitSemaphore;
- VkSemaphore signalSemaphore = m_semaphores[m_poolIndex];
+ VkSemaphore signalSemaphore = m_semaphores[m_currentSemaphoreIndex];
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkPipelineStageFlags stageFlag = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
@@ -3358,11 +3334,50 @@ public:
}
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &signalSemaphore;
- vkAPI.vkResetFences(vkAPI.m_device, 1, &m_fences[m_poolIndex]);
- vkAPI.vkQueueSubmit(m_queue, 1, &submitInfo, m_fences[m_poolIndex]);
+
+ auto fence = static_cast<CommandBufferImpl*>(commandBuffers[0])->m_fence;
+ vkAPI.vkResetFences(vkAPI.m_device, 1, &fence);
+ vkAPI.vkQueueSubmit(m_queue, 1, &submitInfo, fence);
m_pendingWaitSemaphore = signalSemaphore;
- swapPools();
+
+ m_currentSemaphoreIndex++;
+ m_currentSemaphoreIndex = m_currentSemaphoreIndex % kSemaphoreCount;
+ }
+ };
+
+ class TransientResourceHeapImpl
+ : public ITransientResourceHeap
+ , public RefObject
+ {
+ public:
+ SLANG_REF_OBJECT_IUNKNOWN_ALL
+ ITransientResourceHeap* getInterface(const Slang::Guid& guid)
+ {
+ if (guid == GfxGUID::IID_ISlangUnknown || guid == GfxGUID::IID_ITransientResourceHeap)
+ return static_cast<ITransientResourceHeap*>(this);
+ return nullptr;
+ }
+
+ public:
+ VkCommandPool m_commandPool;
+ DescriptorSetAllocator m_descSetAllocator;
+ VkFence m_fence;
+ List<RefPtr<CommandBufferImpl>> m_commandBufferPool;
+ uint32_t m_commandBufferAllocId = 0;
+ RefPtr<BufferResourceImpl> m_constantBuffer;
+ RefPtr<VKDevice> m_device;
+
+ Result init(const ITransientResourceHeap::Desc& desc, VKDevice* device);
+ ~TransientResourceHeapImpl()
+ {
+ m_device->m_api.vkDestroyCommandPool(m_device->m_api.m_device, m_commandPool, nullptr);
+ m_device->m_api.vkDestroyFence(m_device->m_api.m_device, m_fence, nullptr);
+ m_descSetAllocator.close();
}
+ public:
+ virtual SLANG_NO_THROW Result SLANG_MCALL
+ createCommandBuffer(ICommandBuffer** outCommandBuffer) override;
+ virtual SLANG_NO_THROW Result SLANG_MCALL synchronizeAndReset() override;
};
class SwapchainImpl
@@ -3742,6 +3757,15 @@ public:
void _transitionImageLayout(VkImage image, VkFormat format, const TextureResource::Desc& desc, VkImageLayout oldLayout, VkImageLayout newLayout);
+ uint32_t getQueueFamilyIndex(ICommandQueue::QueueType queueType)
+ {
+ switch (queueType)
+ {
+ case ICommandQueue::QueueType::Graphics:
+ default:
+ return m_queueFamilyIndex;
+ }
+ }
public:
// VKDevice members.
@@ -4282,6 +4306,71 @@ void VKDevice::waitForGpu()
m_deviceQueue.flushAndWait();
}
+Result VKDevice::TransientResourceHeapImpl::init(
+ const ITransientResourceHeap::Desc& desc,
+ VKDevice* device)
+{
+ m_device = device;
+ m_descSetAllocator.m_api = &device->m_api;
+
+ VkCommandPoolCreateInfo poolCreateInfo = {};
+ poolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ poolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+ poolCreateInfo.queueFamilyIndex =
+ device->getQueueFamilyIndex(ICommandQueue::QueueType::Graphics);
+ device->m_api.vkCreateCommandPool(
+ device->m_api.m_device, &poolCreateInfo, nullptr, &m_commandPool);
+
+ VkFenceCreateInfo fenceCreateInfo = {};
+ fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
+ device->m_api.vkCreateFence(device->m_api.m_device, &fenceCreateInfo, nullptr, &m_fence);
+ return SLANG_OK;
+}
+
+Result VKDevice::TransientResourceHeapImpl::createCommandBuffer(ICommandBuffer** outCmdBuffer)
+{
+ if (m_commandBufferAllocId < (uint32_t)m_commandBufferPool.getCount())
+ {
+ auto result = m_commandBufferPool[m_commandBufferAllocId];
+ result->beginCommandBuffer();
+ m_commandBufferAllocId++;
+ *outCmdBuffer = result.detach();
+ return SLANG_OK;
+ }
+
+ RefPtr<CommandBufferImpl> commandBuffer = new CommandBufferImpl();
+ SLANG_RETURN_ON_FAIL(commandBuffer->init(
+ m_device, m_commandPool, m_fence, &m_descSetAllocator));
+ m_commandBufferPool.add(commandBuffer);
+ m_commandBufferAllocId++;
+ *outCmdBuffer = commandBuffer.detach();
+ return SLANG_OK;
+}
+
+Result VKDevice::TransientResourceHeapImpl::synchronizeAndReset()
+{
+ m_commandBufferAllocId = 0;
+ auto& api = m_device->m_api;
+ if (api.vkWaitForFences(api.m_device, 1, &m_fence, 1, UINT64_MAX) != VK_SUCCESS)
+ {
+ return SLANG_FAIL;
+ }
+ api.vkResetCommandPool(api.m_device, m_commandPool, 0);
+ m_descSetAllocator.reset();
+ return SLANG_OK;
+}
+
+Result VKDevice::createTransientResourceHeap(
+ const ITransientResourceHeap::Desc& desc,
+ ITransientResourceHeap** outHeap)
+{
+ RefPtr<TransientResourceHeapImpl> result = new TransientResourceHeapImpl();
+ SLANG_RETURN_ON_FAIL(result->init(desc, this));
+ *outHeap = result.detach();
+ return SLANG_OK;
+}
+
Result VKDevice::createCommandQueue(const ICommandQueue::Desc& desc, ICommandQueue** outQueue)
{
// Only support one queue for now.
@@ -4430,23 +4519,6 @@ static VkBufferUsageFlagBits _calcBufferUsageFlags(int bindFlags)
return VkBufferUsageFlagBits(dstFlags);
}
-static VkBufferUsageFlags _calcBufferUsageFlags(int bindFlags, int cpuAccessFlags, const void* initData)
-{
- VkBufferUsageFlags usage = _calcBufferUsageFlags(bindFlags);
-
- if (cpuAccessFlags & IResource::AccessFlag::Read)
- {
- // If it can be read from, set this
- usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
- }
- if ((cpuAccessFlags & IResource::AccessFlag::Write) || initData)
- {
- usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
- }
-
- return usage;
-}
-
static VkImageUsageFlagBits _calcImageUsageFlags(IResource::BindFlag::Enum bind)
{
typedef IResource::BindFlag BindFlag;
@@ -4890,7 +4962,8 @@ Result VKDevice::createBufferResource(IResource::Usage initialUsage, const IBuff
VkMemoryPropertyFlags reqMemoryProperties = 0;
- VkBufferUsageFlags usage = _calcBufferUsageFlags(desc.bindFlags, desc.cpuAccessFlags, initData);
+ VkBufferUsageFlags usage = _calcBufferUsageFlags(desc.bindFlags) |
+ VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
switch (initialUsage)
{