Use additional semaphore to synchronize compute and graphics (Refs #257)

This commit is contained in:
saschawillems 2016-12-10 13:37:58 +01:00
parent a376f2d695
commit f5d774d5cf

View file

@ -108,6 +108,7 @@ public:
VkCommandPool commandPool; // Use a separate command pool (queue family may differ from the one used for graphics) VkCommandPool commandPool; // Use a separate command pool (queue family may differ from the one used for graphics)
VkCommandBuffer commandBuffer; // Command buffer storing the dispatch commands and barriers VkCommandBuffer commandBuffer; // Command buffer storing the dispatch commands and barriers
VkFence fence; // Synchronization fence to avoid rewriting compute CB if still in use VkFence fence; // Synchronization fence to avoid rewriting compute CB if still in use
VkSemaphore semaphore; // Used as a wait semaphore for graphics submission
VkDescriptorSetLayout descriptorSetLayout; // Compute shader binding layout VkDescriptorSetLayout descriptorSetLayout; // Compute shader binding layout
VkDescriptorSet descriptorSet; // Compute shader bindings VkDescriptorSet descriptorSet; // Compute shader bindings
VkPipelineLayout pipelineLayout; // Layout of the compute pipeline VkPipelineLayout pipelineLayout; // Layout of the compute pipeline
@ -751,6 +752,9 @@ public:
VkFenceCreateInfo fenceCreateInfo = vkTools::initializers::fenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT); VkFenceCreateInfo fenceCreateInfo = vkTools::initializers::fenceCreateInfo(VK_FENCE_CREATE_SIGNALED_BIT);
VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &compute.fence)); VK_CHECK_RESULT(vkCreateFence(device, &fenceCreateInfo, nullptr, &compute.fence));
VkSemaphoreCreateInfo semaphoreCreateInfo = vkTools::initializers::semaphoreCreateInfo();
VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &compute.semaphore));
// Build a single command buffer containing the compute dispatch commands // Build a single command buffer containing the compute dispatch commands
buildComputeCommandBuffer(); buildComputeCommandBuffer();
} }
@ -776,24 +780,43 @@ public:
{ {
VulkanExampleBase::prepareFrame(); VulkanExampleBase::prepareFrame();
// Command buffer to be sumitted to the queue // Submit compute shader for frustum culling
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
// Submit to queue // Wait for fence to ensure that compute buffer writes have finished
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VulkanExampleBase::submitFrame();
// Submit compute commands
vkWaitForFences(device, 1, &compute.fence, VK_TRUE, UINT64_MAX); vkWaitForFences(device, 1, &compute.fence, VK_TRUE, UINT64_MAX);
vkResetFences(device, 1, &compute.fence); vkResetFences(device, 1, &compute.fence);
VkSubmitInfo computeSubmitInfo = vkTools::initializers::submitInfo(); VkSubmitInfo computeSubmitInfo = vkTools::initializers::submitInfo();
computeSubmitInfo.commandBufferCount = 1; computeSubmitInfo.commandBufferCount = 1;
computeSubmitInfo.pCommandBuffers = &compute.commandBuffer; computeSubmitInfo.pCommandBuffers = &compute.commandBuffer;
computeSubmitInfo.signalSemaphoreCount = 1;
computeSubmitInfo.pSignalSemaphores = &compute.semaphore;
VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, compute.fence)); VK_CHECK_RESULT(vkQueueSubmit(compute.queue, 1, &computeSubmitInfo, VK_NULL_HANDLE));
// Submit graphics command buffer
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
// Wait on present and compute semaphores
std::vector<VkPipelineStageFlags> stageFlags = {
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
};
std::vector<VkSemaphore> waitSemaphores = {
semaphores.presentComplete, // Wait for presentation to finished
compute.semaphore // Wait for compute to finish
};
submitInfo.pWaitSemaphores = waitSemaphores.data();
submitInfo.waitSemaphoreCount = static_cast<uint32_t>(waitSemaphores.size());
submitInfo.pWaitDstStageMask = stageFlags.data();
// Submit to queue
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, compute.fence));
VulkanExampleBase::submitFrame();
// Get draw count from compute // Get draw count from compute
memcpy(&indirectStats, indirectDrawCountBuffer.mapped, sizeof(indirectStats)); memcpy(&indirectStats, indirectDrawCountBuffer.mapped, sizeof(indirectStats));