1 /// command buffer module
2 module gfx.graal.cmd;
3 
4 import gfx.core.rc;
5 import gfx.core.typecons;
6 import gfx.graal.buffer;
7 import gfx.graal.image;
8 import gfx.graal.renderpass;
9 import gfx.graal.pipeline;
10 import gfx.graal.types;
11 
12 import std.typecons : Flag, No;
13 
14 interface CommandPool : AtomicRefCounted
15 {
16     void reset();
17 
18     CommandBuffer[] allocate(size_t count);
19 
20     void free(CommandBuffer[] buffers)
21     in {
22         import std.algorithm : all;
23         assert(buffers.all!(b => b.pool is this));
24     }
25 }
26 
27 enum Access {
28     none                        = 0x00000000,
29     indirectCommandRead         = 0x00000001,
30     indexRead                   = 0x00000002,
31     vertexAttributeRead         = 0x00000004,
32     uniformRead                 = 0x00000008,
33     inputAttachmentRead         = 0x00000010,
34     shaderRead                  = 0x00000020,
35     shaderWrite                 = 0x00000040,
36     colorAttachmentRead         = 0x00000080,
37     colorAttachmentWrite        = 0x00000100,
38     depthStencilAttachmentRead  = 0x00000200,
39     depthStencilAttachmentWrite = 0x00000400,
40     transferRead                = 0x00000800,
41     transferWrite               = 0x00001000,
42     hostRead                    = 0x00002000,
43     hostWrite                   = 0x00004000,
44     memoryRead                  = 0x00008000,
45     memoryWrite                 = 0x00010000,
46 }
47 
48 enum queueFamilyIgnored = 0xffffffff;
49 
50 struct ImageMemoryBarrier {
51     Trans!Access accessMaskTrans;
52     Trans!ImageLayout layoutTrans;
53     Trans!uint queueFamIndexTrans;
54     ImageBase image;
55     ImageSubresourceRange range;
56 }
57 
58 struct BufferMemoryBarrier {
59     Trans!Access accessMaskTrans;
60     Trans!uint queueFamIndexTrans;
61     Buffer buffer;
62     size_t offset;
63     size_t size;
64 }
65 
66 enum PipelineStage {
67     topOfPipe                   = 0x00000001,
68     drawIndirect                = 0x00000002,
69     vertexInput                 = 0x00000004,
70     vertexShader                = 0x00000008,
71     tessellationControlShader   = 0x00000010,
72     tessellationEvalShader      = 0x00000020,
73     geometryShader              = 0x00000040,
74     fragmentShader              = 0x00000080,
75     earlyFragmentTests          = 0x00000100,
76     lateFragmentTests           = 0x00000200,
77     colorAttachmentOutput       = 0x00000400,
78     computeShader               = 0x00000800,
79     transfer                    = 0x00001000,
80     bottomOfPipe                = 0x00002000,
81     host                        = 0x00004000,
82     allGraphics                 = 0x00008000,
83     allCommands                 = 0x00010000,
84 }
85 
86 enum PipelineBindPoint {
87     graphics, compute
88 }
89 
90 /// Values to be given to a clear image color command
91 /// The type should be f32, unless the image format has numeric format of sInt or uInt.
92 struct ClearColorValues
93 {
94     enum Type {
95         f32, i32, u32
96     }
97     union Values {
98         float[4] f32;
99         int[4] i32;
100         uint[4] u32;
101     }
102     Type type;
103     Values values;
104 
105     this (float r, float g, float b, float a) {
106         type = Type.f32;
107         values.f32 = [ r, g, b, a ];
108     }
109 
110     this (int r, int g, int b, int a) {
111         type = Type.i32;
112         values.i32 = [ r, g, b, a ];
113     }
114 
115     this (uint r, uint g, uint b, uint a) {
116         type = Type.u32;
117         values.u32 = [ r, g, b, a ];
118     }
119 }
120 
121 struct ClearDepthStencilValues
122 {
123     float depth;
124     uint stencil;
125 }
126 
127 struct ClearValues
128 {
129     enum Type { undefined, color, depthStencil }
130     union Values {
131         ClearColorValues        color;
132         ClearDepthStencilValues depthStencil;
133     }
134     Type type;
135     Values values;
136 
137     this (ClearColorValues color) {
138         type = Type.color;
139         values.color = color;
140     }
141     this (ClearDepthStencilValues depthStencil) {
142         type = Type.depthStencil;
143         values.depthStencil = depthStencil;
144     }
145 
146     static ClearValues color(in float r, in float g, in float b, in float a) {
147         return ClearValues(ClearColorValues(r, g, b, a));
148     }
149 
150     static ClearValues color(in int r, in int g, in int b, in int a) {
151         return ClearValues(ClearColorValues(r, g, b, a));
152     }
153 
154     static ClearValues color(in uint r, in uint g, in uint b, in uint a) {
155         return ClearValues(ClearColorValues(r, g, b, a));
156     }
157 
158     static ClearValues depthStencil(in float depth, in uint stencil) {
159         return ClearValues(ClearDepthStencilValues(depth, stencil));
160     }
161 }
162 
163 struct VertexBinding {
164     Buffer buffer;
165     size_t offset;
166 }
167 
168 struct CopyRegion
169 {
170     Trans!size_t offset;
171     size_t size;
172 }
173 
174 struct ImageCopyRegion
175 {
176     Trans!ImageSubresourceRange isr;
177     Trans!(float[3]) offset;
178 }
179 
180 struct BufferImageCopy
181 {
182     ulong bufferOffset;
183     uint bufferWidth;
184     uint bufferHeight;
185     ImageSubresourceLayer imageLayers;
186     int[3] offset;
187     uint[3] extent;
188 }
189 
190 enum StencilFace
191 {
192     front = 1,
193     back = 2,
194     frontAndBack = 3,
195 }
196 
197 enum wholeSize = uint.max;
198 
199 interface CommandBuffer
200 {
201     @property CommandPool pool();
202 
203     void reset();
204 
205     void begin(Flag!"persistent" persistent=No.persistent);
206     void end();
207 
208     void pipelineBarrier(Trans!PipelineStage stageTrans,
209                          BufferMemoryBarrier[] bufMbs,
210                          ImageMemoryBarrier[] imgMbs);
211 
212     void clearColorImage(ImageBase image, ImageLayout layout,
213                          in ClearColorValues clearValues,
214                          ImageSubresourceRange[] ranges);
215 
216     void clearDepthStencilImage(ImageBase image, ImageLayout layout,
217                                 in ClearDepthStencilValues clearValues,
218                                 ImageSubresourceRange[] ranges);
219 
220     /// Fills buffer from offset to offset+size with value
221     /// Params:
222     ///     dst     = the buffer to fill.
223     ///     offset  = Byte offset from where to fill the buffer.
224     ///               Must be a multiple of 4.
225     ///     size    = Number of bytes to fill. Must be a multiple of 4 or
226     ///               wholeSize to fill until the end of the buffer.
227     ///     value   = Value to copy into the buffer, in host endianess.
228     /// Can only be used outside of a render pass.
229     void fillBuffer(Buffer dst, in size_t offset, in size_t size, uint value)
230     in {
231         assert(offset % 4 == 0);
232         assert(size == wholeSize || size % 4 == 0);
233     }
234     /// Update buffer with the data passed as argument
235     /// Params:
236     ///     dst     = the buffer to update.
237     ///     offset  = Byte offset from where to update the buffer.
238     ///               Must be a multiple of 4.
239     ///     data    = The data to copy into the buffer.
240     /// The data is duplicated into the command buffer, so it is legal to pass a slice
241     /// to local on-stack data, or to let GC collect the data right after the call.
242     /// Can only be used outside of a render pass.
243     void updateBuffer(Buffer dst, in size_t offset, in uint[] data);
244     void copyBuffer(Trans!Buffer buffers, in CopyRegion[] regions);
245     void copyBufferToImage(Buffer srcBuffer, ImageBase dstImage,
246                            in ImageLayout dstLayout, in BufferImageCopy[] regions);
247 
248     void setViewport(in uint firstViewport, in Viewport[] viewports);
249     void setScissor(in uint firstScissor, in Rect[] scissors);
250     void setDepthBounds(in float minDepth, in float maxDepth);
251     void setLineWidth(in float lineWidth);
252     void setDepthBias(in float constFactor, in float clamp, in float slopeFactor);
253     void setStencilCompareMask(in StencilFace faceMask, in uint compareMask);
254     void setStencilWriteMask(in StencilFace faceMask, in uint writeMask);
255     void setStencilReference(in StencilFace faceMask, in uint reference);
256     void setBlendConstants(in float[4] blendConstants);
257 
258     void beginRenderPass(RenderPass rp, Framebuffer fb,
259                          Rect area, ClearValues[] clearValues);
260 
261     void nextSubpass();
262 
263     void endRenderPass();
264 
265     void bindPipeline(Pipeline pipeline);
266     void bindVertexBuffers(uint firstBinding, VertexBinding[] bindings);
267     void bindIndexBuffer(Buffer indexBuf, size_t offset, IndexType type);
268 
269     void bindDescriptorSets(PipelineBindPoint bindPoint, PipelineLayout layout,
270                             uint firstSet, DescriptorSet[] sets, in size_t[] dynamicOffsets);
271 
272     void pushConstants(PipelineLayout layout, ShaderStage stages,
273                        size_t offset, size_t size, const(void)* data);
274 
275     void draw(uint vertexCount, uint instanceCount, uint firstVertex, uint firstInstance);
276     void drawIndexed(uint indexCount, uint instanceCount, uint firstVertex, int vertexOffset, uint firstInstance);
277 }