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