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 }