1 module sbylib.wrapper.vulkan.commandbuffer;
2 
3 import std;
4 import erupted;
5 import sbylib.wrapper.vulkan.buffer;
6 import sbylib.wrapper.vulkan.commandpool;
7 import sbylib.wrapper.vulkan.descriptorset;
8 import sbylib.wrapper.vulkan.device;
9 import sbylib.wrapper.vulkan.enums;
10 import sbylib.wrapper.vulkan.framebuffer;
11 import sbylib.wrapper.vulkan.image;
12 import sbylib.wrapper.vulkan.renderpass;
13 import sbylib.wrapper.vulkan.pipeline;
14 import sbylib.wrapper.vulkan.pipelinelayout;
15 import sbylib.wrapper.vulkan.util;
16 
17 class CommandBuffer {
18     static struct AllocateInfo {
19         @vkProp() {
20             CommandPool commandPool;
21             immutable CommandBufferLevel level;
22             immutable uint commandBufferCount;
23         }
24 
25         mixin VkTo!(VkCommandBufferAllocateInfo);
26     }
27 
28     static struct BeginInfo {
29         @vkProp() {
30             immutable BitFlags!Flags flags;
31         }
32 
33         @vkProp("pInheritanceInfo") {
34             InheritanceInfo inheritanceInfo;
35         }
36 
37         enum Flags {
38             OneTimeSubmit = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
39             RenderPassContinue = VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,
40             SimultaneousUse = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT,
41         }
42 
43         mixin VkTo!(VkCommandBufferBeginInfo);
44     }
45 
46     static struct InheritanceInfo {
47         @vkProp() {
48             RenderPass renderPass;
49             immutable uint subpass;
50             Framebuffer framebuffer;
51             immutable bool occlusionQueryEnable;
52             immutable VkQueryControlFlags queryFlags;
53             immutable VkQueryPipelineStatisticFlags pipelineStatistics;
54         }
55 
56         mixin VkTo!(VkCommandBufferInheritanceInfo);
57     }
58 
59     static struct RenderPassBeginInfo {
60         @vkProp() {
61             RenderPass renderPass;
62             Framebuffer framebuffer;
63             VkRect2D renderArea;
64         }
65 
66         @vkProp("pClearValues", "clearValueCount") {
67             const VkClearValue[] clearValues;
68         }
69 
70         mixin VkTo!(VkRenderPassBeginInfo);
71     }
72 
73     private Device device;
74     private CommandPool commandPool;
75     private VkCommandBuffer commandBuffer;
76 
77     mixin ImplNameSetter!(device, commandBuffer, DebugReportObjectType.CommandBuffer);
78 
79     private this(Device device, CommandPool commandPool, VkCommandBuffer commandBuffer) {
80         import std.exception : enforce;
81 
82         this.device = device;
83         this.commandPool = commandPool;
84         this.commandBuffer = commandBuffer;
85     }
86 
87     ~this() {
88         vkFreeCommandBuffers(device.device, commandPool.commandPool, 1, &commandBuffer);
89     }
90 
91     mixin VkTo!(VkCommandBuffer);
92 
93     static CommandBuffer[] allocate(Device device, AllocateInfo _info) {
94         VkCommandBuffer[] commandBuffers = new VkCommandBuffer[_info.commandBufferCount];
95 
96         auto info = _info.vkTo();
97 
98         enforceVK(vkAllocateCommandBuffers(device.device, &info, commandBuffers.ptr));
99 
100         return commandBuffers.map!(cb => new CommandBuffer(device, _info.commandPool, cb)).array;
101     }
102 
103     void begin(BeginInfo _info) {
104         auto info = _info.vkTo();
105         vkBeginCommandBuffer(commandBuffer, &info);
106     }
107 
108     void end() {
109         enforceVK(vkEndCommandBuffer(commandBuffer));
110     }
111 
112     void cmdPipelineBarrier(PipelineStage srcStageMask,
113             PipelineStage dstStageMask, VkDependencyFlags dependencyFlags,
114             VkMemoryBarrier[] memoryBarriers, VkBufferMemoryBarrier[] bufferMemoryBarriers,
115             VkImageMemoryBarrier[] imageMemoryBarriers) {
116 
117         vkCmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask,
118                 dependencyFlags, cast(uint) memoryBarriers.length,
119                 memoryBarriers.ptr, cast(uint) bufferMemoryBarriers.length, bufferMemoryBarriers.ptr,
120                 cast(uint) imageMemoryBarriers.length, imageMemoryBarriers.ptr);
121     }
122 
123     void cmdBeginRenderPass(RenderPassBeginInfo _info, SubpassContents subpassContents) {
124         auto info = _info.vkTo();
125         vkCmdBeginRenderPass(commandBuffer, &info, subpassContents);
126     }
127 
128     void cmdEndRenderPass() {
129         vkCmdEndRenderPass(commandBuffer);
130     }
131 
132     void cmdBindPipeline(PipelineBindPoint pipelineBindPoint, Pipeline pipeline) {
133         vkCmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline.pipeline);
134     }
135 
136     void cmdSetViewport(uint N)(uint firstViewport, const VkViewport[N] viewports) {
137         vkCmdSetViewport(commandBuffer, firstViewport, N, viewports.ptr);
138     }
139 
140     void cmdSetScissor(uint N)(uint firstScissor, const VkRect2D[N] scissors) {
141         vkCmdSetScissor(commandBuffer, firstScissor, N, scissors.ptr);
142     }
143 
144     void cmdBindVertexBuffers(uint N)(uint firstBinding, Buffer[N] _buffers,
145             const VkDeviceSize[N] offsets) {
146         VkBuffer[N] buffers;
147         static foreach (i; 0 .. N)
148             buffers[i] = _buffers[i].buffer;
149 
150         vkCmdBindVertexBuffers(commandBuffer, firstBinding, N, buffers.ptr, offsets.ptr);
151     }
152 
153     void cmdBindIndexBuffer(Buffer buffer,VkDeviceSize offset, IndexType indexType) {
154         vkCmdBindIndexBuffer(commandBuffer, buffer.buffer, offset, indexType);
155     }
156 
157     void cmdBindDescriptorSets(uint N, uint M)(PipelineBindPoint pipelineBindPoint, PipelineLayout layout,
158             uint firstSet, const DescriptorSet[N] _descriptorSets, const uint[M] dynamicOffsets) {
159         VkDescriptorSet[N] descriptorSets;
160         static foreach (i; 0..N)
161             descriptorSets[i] = cast(VkDescriptorSet)_descriptorSets[i].vkTo();
162 
163         vkCmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout.pipelineLayout, firstSet,
164                 cast(uint) descriptorSets.length, descriptorSets.ptr,
165                 cast(uint) dynamicOffsets.length, dynamicOffsets.ptr);
166     }
167 
168     void cmdBindDescriptorSets(uint N)(PipelineBindPoint pipelineBindPoint, PipelineLayout layout,
169             uint firstSet, const DescriptorSet[N] _descriptorSets) {
170         uint[0] dummy;
171         cmdBindDescriptorSets(pipelineBindPoint, layout, firstSet, _descriptorSets, dummy);
172     }
173 
174     void cmdDraw(uint vertexCount, uint instanceCount, uint firstVertex, uint firstInstance) {
175         vkCmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
176     }
177 
178     void cmdDrawIndexed(uint indexCount, uint instanceCount, uint firstIndex, int vertexOffset, uint firstInstance) {
179         vkCmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
180     }
181 
182     void cmdDispatch(uint groupCountX, uint groupCountY, uint groupCountZ) {
183         vkCmdDispatch(commandBuffer, groupCountX, groupCountY, groupCountZ);
184     }
185 
186     void cmdCopyBuffer(Buffer src, Buffer dst, const VkBufferCopy[] regions) {
187         vkCmdCopyBuffer(commandBuffer, src.buffer, dst.buffer, cast(uint)regions.length, regions.ptr);
188     }
189 
190     void cmdCopyImage(Image src, ImageLayout srcImageLayout, Image dst, ImageLayout dstImageLayout, const VkImageCopy[] regions) {
191         vkCmdCopyImage(commandBuffer, src.image, srcImageLayout, dst.image, dstImageLayout, cast(uint)regions.length, regions.ptr);
192     }
193 
194     void cmdCopyBufferToImage(uint N)(Buffer src, Image dst, ImageLayout layout, const VkBufferImageCopy[N] regions) {
195         vkCmdCopyBufferToImage(commandBuffer, src.buffer, dst.image, layout, N, regions.ptr);
196     }
197 
198     void cmdBlitImage(uint N)(Image srcImage, ImageLayout srcImageLayout, Image dstImage, ImageLayout dstImageLayout, VkImageBlit[N] regions, SamplerFilter filter) {
199         vkCmdBlitImage(commandBuffer, srcImage.image, srcImageLayout, dstImage.image, dstImageLayout, N, regions.ptr, filter);
200     }
201 
202     void cmdClearAttachments(uint N, uint M)(const VkClearAttachment[N] attachments, const VkClearRect[M] rects) {
203         vkCmdClearAttachments(commandBuffer, N, attachments.ptr, M, rects.ptr);
204     }
205 
206     void cmdExecuteCommands(uint N)(CommandBuffer[N] _commandBuffers) {
207         VkCommandBuffer[N] commandBuffers;
208         static foreach (i; 0..N) {
209             commandBuffers[i] = _commandBuffers[i].vkTo();
210         }
211         vkCmdExecuteCommands(commandBuffer, N, commandBuffers.ptr);
212     }
213 
214     void cmdExecuteCommands(CommandBuffer[] _commandBuffers) {
215         VkCommandBuffer[256] commandBuffers;
216         foreach (i; 0.._commandBuffers.length) {
217             commandBuffers[i] = _commandBuffers[i].vkTo();
218         }
219         vkCmdExecuteCommands(commandBuffer, cast(uint)_commandBuffers.length, commandBuffers.ptr);
220     }
221 
222     // utilities, not just a wrapper
223 
224     void begin(BeginInfo.Flags[] flags...) {
225         BitFlags!(BeginInfo.Flags) infoFlags;
226         foreach (flag; flags) infoFlags |= flag;
227         begin(BeginInfo(infoFlags));
228     }
229 }