1 /// Vulkan queue module 2 module gfx.vulkan.queue; 3 4 package: 5 6 import gfx.bindings.vulkan; 7 8 import gfx.core.rc; 9 import gfx.graal.queue; 10 import gfx.vulkan.conv; 11 import gfx.vulkan.device; 12 import gfx.vulkan.error; 13 import gfx.vulkan.sync; 14 import gfx.vulkan.wsi; 15 16 final class VulkanQueue : Queue 17 { 18 this (VkQueue vkObj, VulkanDevice dev) { 19 _vkObj = vkObj; 20 _dev = dev; // weak reference, no retain 21 _vk = dev.vk; 22 } 23 24 @property VkQueue vkObj() { 25 return _vkObj; 26 } 27 28 @property VkDeviceCmds vk() { 29 return _vk; 30 } 31 32 @property Device device() 33 { 34 auto dev = lockObj(_dev); 35 if (!dev) return null; 36 return giveAwayObj(dev); 37 } 38 39 void waitIdle() { 40 vk.QueueWaitIdle(_vkObj); 41 } 42 43 void submit(Submission[] submissions, Fence fence) 44 { 45 import std.algorithm : map; 46 import std.array : array; 47 48 auto vkSubmitInfos = submissions.map!((ref Submission s) 49 { 50 auto vkWaitSems = new VkSemaphore[s.stageWaits.length]; 51 auto vkWaitDstStage = new VkPipelineStageFlags[s.stageWaits.length]; 52 53 foreach (i, sw; s.stageWaits) { 54 vkWaitSems[i] = enforce( 55 cast(VulkanSemaphore)sw.sem, 56 "Did not pass a valid vulkan wait semaphore to VulkanQueue.submit()" 57 ).vkObj; 58 vkWaitDstStage[i] = pipelineStageToVk(sw.stages); 59 } 60 61 auto vkSigSems = s.sigSems.map!( 62 s => enforce( 63 cast(VulkanSemaphore)s, 64 "Did not pass a valid vulkan signal semaphore to VulkanQueue.submit()" 65 ).vkObj 66 ).array; 67 auto vkCmdBufs = s.cmdBufs.map!( 68 b => enforce( 69 cast(VulkanCommandBuffer)b, 70 "Did not pass a vulkan command buffer" 71 ).vkObj 72 ).array; 73 74 75 VkSubmitInfo si; 76 si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 77 si.waitSemaphoreCount = cast(uint)vkWaitSems.length; 78 si.pWaitSemaphores = vkWaitSems.ptr; 79 si.pWaitDstStageMask = vkWaitDstStage.ptr; 80 si.commandBufferCount = cast(uint)vkCmdBufs.length; 81 si.pCommandBuffers = vkCmdBufs.ptr; 82 si.signalSemaphoreCount = cast(uint)vkSigSems.length; 83 si.pSignalSemaphores = vkSigSems.ptr; 84 85 return si; 86 }).array; 87 88 VkFence vkFence; 89 if (fence) { 90 vkFence = enforce(cast(VulkanFence)fence, "Did not pass a Vulkan fence").vkObj; 91 } 92 93 vulkanEnforce( 94 vk.QueueSubmit(vkObj, cast(uint)vkSubmitInfos.length, vkSubmitInfos.ptr, vkFence), 95 "Could not submit vulkan queue" 96 ); 97 } 98 99 void present(Semaphore[] waitSems, PresentRequest[] prs) { 100 import std.algorithm : map; 101 import std.array : array; 102 103 auto vkSems = waitSems.map!( 104 s => enforce( 105 cast(VulkanSemaphore)s, 106 "Did not pass a valid vulkan wait semaphore to VulkanQueue.present()" 107 ).vkObj 108 ).array; 109 110 auto vkScs = new VkSwapchainKHR[prs.length]; 111 auto vkImgs = new uint[prs.length]; 112 foreach (i, pr; prs) { 113 vkScs[i] = enforce( 114 cast(VulkanSwapchain)pr.swapChain, 115 "Did not pass a vukan swap chain").vkObj; 116 vkImgs[i] = pr.imageIndex; 117 } 118 119 VkPresentInfoKHR qpi; 120 qpi.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; 121 qpi.waitSemaphoreCount = cast(uint)waitSems.length; 122 qpi.pWaitSemaphores = &vkSems[0]; 123 qpi.swapchainCount = cast(uint)prs.length; 124 qpi.pSwapchains = &vkScs[0]; 125 qpi.pImageIndices = &vkImgs[0]; 126 127 vulkanEnforce( 128 vk.QueuePresentKHR(vkObj, &qpi), "Could not present vulkan swapchain" 129 ); 130 } 131 132 private VkQueue _vkObj; 133 private VulkanDevice _dev; // device is kept as weak reference 134 private VkDeviceCmds _vk; 135 }