summaryrefslogtreecommitdiffstats
path: root/tools/gfx/vulkan/vk-device-queue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gfx/vulkan/vk-device-queue.cpp')
-rw-r--r--tools/gfx/vulkan/vk-device-queue.cpp199
1 files changed, 199 insertions, 0 deletions
diff --git a/tools/gfx/vulkan/vk-device-queue.cpp b/tools/gfx/vulkan/vk-device-queue.cpp
new file mode 100644
index 000000000..10a3d0e3b
--- /dev/null
+++ b/tools/gfx/vulkan/vk-device-queue.cpp
@@ -0,0 +1,199 @@
+// vk-device-queue.cpp
+#include "vk-device-queue.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+namespace gfx {
+using namespace Slang;
+
+VulkanDeviceQueue::~VulkanDeviceQueue()
+{
+ for (int i = 0; i < int(EventType::CountOf); ++i)
+ {
+ m_api->vkDestroySemaphore(m_api->m_device, m_semaphores[i], nullptr);
+ }
+
+ for (int i = 0; i < m_numCommandBuffers; i++)
+ {
+ m_api->vkFreeCommandBuffers(m_api->m_device, m_commandPool, 1, &m_commandBuffers[i]);
+ m_api->vkDestroyFence(m_api->m_device, m_fences[i].fence, nullptr);
+ }
+ m_api->vkDestroyCommandPool(m_api->m_device, m_commandPool, nullptr);
+}
+
+SlangResult VulkanDeviceQueue::init(const VulkanApi& api, VkQueue queue, int queueIndex)
+{
+ assert(m_api == nullptr);
+ m_api = &api;
+
+ for (int i = 0; i < int(EventType::CountOf); ++i)
+ {
+ m_semaphores[i] = VK_NULL_HANDLE;
+ m_currentSemaphores[i] = VK_NULL_HANDLE;
+ }
+
+ m_numCommandBuffers = kMaxCommandBuffers;
+ m_queueIndex = queueIndex;
+
+ m_queue = queue;
+
+ VkCommandPoolCreateInfo poolCreateInfo = {};
+ poolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ poolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
+
+ poolCreateInfo.queueFamilyIndex = queueIndex;
+
+ api.vkCreateCommandPool(api.m_device, &poolCreateInfo, nullptr, &m_commandPool);
+
+ VkCommandBufferAllocateInfo commandInfo = {};
+ commandInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
+ commandInfo.commandPool = m_commandPool;
+ commandInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
+ commandInfo.commandBufferCount = 1;
+
+ VkFenceCreateInfo fenceCreateInfo = {};
+ fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
+ fenceCreateInfo.flags = 0; // VK_FENCE_CREATE_SIGNALED_BIT;
+
+ for (int i = 0; i < m_numCommandBuffers; i++)
+ {
+ Fence& fence = m_fences[i];
+
+ api.vkAllocateCommandBuffers(api.m_device, &commandInfo, &m_commandBuffers[i]);
+
+ api.vkCreateFence(api.m_device, &fenceCreateInfo, nullptr, &fence.fence);
+ fence.active = false;
+ fence.value = 0;
+ }
+
+ VkSemaphoreCreateInfo semaphoreCreateInfo = {};
+ semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+
+ for (int i = 0; i < int(EventType::CountOf); ++i)
+ {
+ api.vkCreateSemaphore(api.m_device, &semaphoreCreateInfo, nullptr, &m_semaphores[i]);
+ }
+
+ // Second step of flush to prime command buffer
+ flushStepB();
+
+ return SLANG_OK;
+}
+
+void VulkanDeviceQueue::flushStepA()
+{
+ m_api->vkEndCommandBuffer(m_commandBuffer);
+
+ VkPipelineStageFlags stageFlags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
+
+ VkSubmitInfo submitInfo = {};
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+
+ // Wait semaphores
+ if (isCurrent(EventType::BeginFrame))
+ {
+ submitInfo.waitSemaphoreCount = 1;
+ submitInfo.pWaitSemaphores = &m_currentSemaphores[int(EventType::BeginFrame)];
+ }
+
+ submitInfo.pWaitDstStageMask = &stageFlags;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &m_commandBuffer;
+
+ // Signal semaphores
+ if (isCurrent(EventType::EndFrame))
+ {
+ submitInfo.signalSemaphoreCount = 1;
+ submitInfo.pSignalSemaphores = &m_currentSemaphores[int(EventType::EndFrame)];
+ }
+
+ Fence& fence = m_fences[m_commandBufferIndex];
+
+ m_api->vkQueueSubmit(m_queue, 1, &submitInfo, fence.fence);
+
+ // mark signaled fence value
+ fence.value = m_nextFenceValue;
+ fence.active = true;
+
+ // increment fence value
+ m_nextFenceValue++;
+
+ // No longer waiting on this semaphore
+ makeCompleted(EventType::BeginFrame);
+}
+
+void VulkanDeviceQueue::_updateFenceAtIndex( int fenceIndex, bool blocking)
+{
+ Fence& fence = m_fences[fenceIndex];
+
+ if (fence.active)
+ {
+ uint64_t timeout = blocking ? ~uint64_t(0) : 0;
+
+ if (VK_SUCCESS == m_api->vkWaitForFences(m_api->m_device, 1, &fence.fence, VK_TRUE, timeout))
+ {
+ m_api->vkResetFences(m_api->m_device, 1, &fence.fence);
+
+ fence.active = false;
+
+ if (fence.value > m_lastFenceCompleted)
+ {
+ m_lastFenceCompleted = fence.value;
+ }
+ }
+ }
+}
+
+void VulkanDeviceQueue::flushStepB()
+{
+ m_commandBufferIndex = (m_commandBufferIndex + 1) % m_numCommandBuffers;
+ m_commandBuffer = m_commandBuffers[m_commandBufferIndex];
+
+ // non-blocking update of fence values
+ for (int i = 0; i < m_numCommandBuffers; ++i)
+ {
+ _updateFenceAtIndex(i, false);
+ }
+
+ // blocking update of fence values
+ _updateFenceAtIndex(m_commandBufferIndex, true);
+
+ m_api->vkResetCommandBuffer(m_commandBuffer, 0);
+
+ //m_api.vkResetCommandPool(m_api->m_device, m_commandPool, 0);
+
+ VkCommandBufferBeginInfo beginInfo = {};
+ beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
+ beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
+
+ m_api->vkBeginCommandBuffer(m_commandBuffer, &beginInfo);
+}
+
+void VulkanDeviceQueue::flush()
+{
+ flushStepA();
+ flushStepB();
+}
+
+void VulkanDeviceQueue::flushAndWait()
+{
+ flush();
+ waitForIdle();
+}
+
+VkSemaphore VulkanDeviceQueue::makeCurrent(EventType eventType)
+{
+ assert(!isCurrent(eventType));
+ VkSemaphore semaphore = m_semaphores[int(eventType)];
+ m_currentSemaphores[int(eventType)] = semaphore;
+ return semaphore;
+}
+
+void VulkanDeviceQueue::makeCompleted(EventType eventType)
+{
+ m_currentSemaphores[int(eventType)] = VK_NULL_HANDLE;
+}
+
+} // renderer_test