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