1 module gfx.graal.pipeline;
2 
3 import gfx.core.rc;
4 import gfx.core.typecons;
5 import gfx.graal.buffer;
6 import gfx.graal.format;
7 import gfx.graal.image;
8 import gfx.graal.renderpass;
9 import gfx.graal.types;
10 
11 import std.typecons : Flag;
12 
13 interface ShaderModule : AtomicRefCounted
14 {
15     import gfx.graal.device : Device;
16 
17     /// Get the parent device
18     @property Device device();
19 
20     @property string entryPoint();
21 }
22 
23 interface PipelineLayout : AtomicRefCounted
24 {
25     import gfx.graal.device : Device;
26 
27     /// Get the parent device
28     @property Device device();
29 }
30 
31 interface Pipeline : AtomicRefCounted
32 {
33     import gfx.graal.device : Device;
34 
35     /// Get the parent device
36     @property Device device();
37 }
38 
39 interface DescriptorSetLayout : AtomicRefCounted
40 {
41     import gfx.graal.device : Device;
42 
43     /// Get the parent device
44     @property Device device();
45 }
46 
47 interface DescriptorPool : AtomicRefCounted
48 {
49     import gfx.graal.device : Device;
50 
51     /// Get the parent device
52     @property Device device();
53 
54     /// Allocate a descriptor set per descriptor layout passed as argument
55     DescriptorSet[] allocate(DescriptorSetLayout[] layouts);
56 
57     /// Reset this pool.
58     /// All descriptors allocated with this pool are invalid after this call
59     void reset();
60 }
61 
62 interface DescriptorSet
63 {
64     @property DescriptorPool pool();
65 }
66 
67 struct PipelineInfo {
68     GraphicsShaderSet shaders;
69     VertexInputBinding[] inputBindings;
70     VertexInputAttrib[] inputAttribs;
71     InputAssembly assembly;
72     Rasterizer rasterizer;
73     /// Viewport configuration of the pipeline.
74     /// For dynamic viewport, leave this array empty
75     ViewportConfig[] viewports;
76 
77     // TODO: tesselation, multisample
78 
79     DepthInfo depthInfo;
80     StencilInfo stencilInfo;
81     ColorBlendInfo blendInfo;
82 
83     DynamicState[] dynamicStates;
84 
85     PipelineLayout layout;
86 
87     RenderPass renderPass;
88     uint subpassIndex;
89 }
90 
91 enum ShaderStage {
92     vertex                  = 0x01,
93     tessellationControl     = 0x02,
94     tessellationEvaluation  = 0x04,
95     geometry                = 0x08,
96     fragment                = 0x10,
97     compute                 = 0x20,
98 
99     allGraphics             = 0x1f,
100     all                     = allGraphics | compute,
101 }
102 
103 struct GraphicsShaderSet {
104     ShaderModule vertex;
105     ShaderModule tessControl;
106     ShaderModule tessEval;
107     ShaderModule geometry;
108     ShaderModule fragment;
109 }
110 
111 
112 /// Describes the binding of a buffer to the pipeline
113 struct VertexInputBinding {
114     uint binding;
115     size_t stride;
116     Flag!"instanced" instanced;
117 }
118 
119 /// Describes a vertex attribute
120 struct VertexInputAttrib {
121     uint location;
122     uint binding;
123     Format format;
124     size_t offset;
125 }
126 
127 
128 enum Primitive {
129     pointList, lineList, lineStrip,
130     triangleList, triangleStrip, triangleFan,
131     lineListAdjacency, lineStripAdjacency,
132     triangleListAdjacency, triangleStripAdjacency,
133     patchList,
134 }
135 
136 struct InputAssembly {
137     Primitive primitive;
138     Flag!"primitiveRestart" primitiveRestart;
139 }
140 
141 enum FrontFace {
142     ccw, cw,
143 }
144 
145 enum Cull {
146     none            = 0x00,
147     front           = 0x01,
148     back            = 0x02,
149     frontAndBack    = front | back,
150 }
151 
152 enum PolygonMode {
153     fill, line, point,
154 }
155 
156 /// Defines how a polygon can be offset (mainly to avoid shadow artifacts).
157 /// Given m as maximum depth slope of the triangle and r as implementation defined
158 /// minimal resolvable difference, the offset of the triangle is defined as follow:
159 /// o = m * slopeFactor + r * constantFactor
160 /// If clamp == 0f, o is used directly as effective offset.
161 /// If clamp > 0f, the effective offset is min(o, clamp)
162 /// If clamp < 0f, the effective offset is max(o, clamp)
163 struct DepthBias
164 {
165     /// Factor multiplied by the minimal resolvable difference of the depth buffer
166     float constantFactor;
167     /// Clamps the effective offset to a particular value
168     float clamp;
169     /// Factor multiplied by the maximum depth slope of the polygon.
170     float slopeFactor;
171 }
172 
173 struct Rasterizer {
174     PolygonMode mode;
175     Cull cull;
176     FrontFace front;
177     Flag!"depthClamp" depthClamp;
178     Option!DepthBias depthBias;
179     float lineWidth=1f;
180 }
181 
182 struct ViewportConfig {
183     Viewport viewport;
184     Rect scissors;
185 }
186 
187 enum CompareOp
188 {
189     never, less, equal, lessOrEqual, greater, notEqual, greaterOrEqual, always,
190 }
191 
192 enum StencilOp
193 {
194     keep,
195     zero,
196     replace,
197     incrementAndClamp,
198     decrementAndClamp,
199     invert,
200     incrementAndWrap,
201     decrementAndWrap,
202 }
203 
204 struct DepthInfo
205 {
206     Flag!"enabled" enabled;
207     Flag!"write" write;
208     CompareOp compareOp;
209     Flag!"boundsTest" boundsTest;
210     float minBounds;
211     float maxBounds;
212 
213     @property static DepthInfo none() {
214         return DepthInfo.init;
215     }
216 }
217 
218 struct StencilOpState
219 {
220     StencilOp failOp;
221     StencilOp passOp;
222     StencilOp depthFailOp;
223     CompareOp compareOp;
224     uint compareMask;
225     uint writeMask;
226     uint refMask;
227 }
228 
229 struct StencilInfo
230 {
231     Flag!"enabled" enabled;
232     StencilOpState front;
233     StencilOpState back;
234 
235     @property static StencilInfo none() {
236         return StencilInfo.init;
237     }
238 }
239 
240 
241 enum BlendFactor
242 {
243     zero = 0,
244     one = 1,
245     srcColor = 2,
246     oneMinusSrcColor = 3,
247     dstColor = 4,
248     oneMinusDstColor = 5,
249     srcAlpha = 6,
250     oneMinusSrcAlpha = 7,
251     dstAlpha = 8,
252     oneMinusDstAlpha = 9,
253     constantColor = 10,
254     oneMinusConstantColor = 11,
255     constantAlpha = 12,
256     oneMinusConstantAlpha = 13,
257     srcAlphaSaturate = 14,
258     src1Color = 15,
259     oneMinusSrc1Color = 16,
260     src1Alpha = 17,
261     oneMinusSrc1Alpha = 18,
262 }
263 
264 enum BlendOp {
265     add,
266     subtract,
267     reverseSubtract,
268     min,
269     max,
270 }
271 
272 struct BlendState {
273     Trans!BlendFactor factor;
274     BlendOp op;
275 }
276 
277 enum ColorMask {
278     r = 0x01,
279     g = 0x02,
280     b = 0x04,
281     a = 0x08,
282 
283     none    = 0x00,
284     all     = r | g | b | a,
285     rg      = r | g,
286     rb      = r | b,
287     ra      = r | a,
288     gb      = g | b,
289     ga      = g | a,
290     ba      = b | a,
291     rgb     = r | g | b,
292     rga     = r | g | a,
293     rba     = r | b | a,
294     gba     = g | b | a,
295     rgba    = r | g | b | a,
296 }
297 
298 struct ColorBlendAttachment {
299     Flag!"enabled" enabled;
300     BlendState colorBlend;
301     BlendState alphaBlend;
302     ColorMask colorMask;
303 
304     static ColorBlendAttachment solid(in ColorMask mask=ColorMask.all) {
305         import std.typecons : No;
306         return ColorBlendAttachment(
307             No.enabled, BlendState.init, BlendState.init, mask
308         );
309     }
310 
311     static ColorBlendAttachment blend(in BlendState blendState,
312                                       in ColorMask mask=ColorMask.all) {
313         import std.typecons : Yes;
314         return ColorBlendAttachment(
315             Yes.enabled, blendState, blendState, mask
316         );
317     }
318 
319     static ColorBlendAttachment blend(in BlendState color, in BlendState alpha,
320                                       in ColorMask mask=ColorMask.all) {
321         import std.typecons : Yes;
322         return ColorBlendAttachment(
323             Yes.enabled, color, alpha, mask
324         );
325     }
326 }
327 
328 enum LogicOp {
329     clear,
330     and,
331     andReverse,
332     copy,
333     andInverted,
334     noop,
335     xor,
336     or,
337     nor,
338     equivalent,
339     invert,
340     orReverse,
341     copyInverted,
342     orInverted,
343     nand,
344     set,
345 }
346 
347 struct ColorBlendInfo
348 {
349     Option!LogicOp logicOp;
350     ColorBlendAttachment[] attachments;
351     float[4] blendConstants = [ 0f, 0f, 0f, 0f ];
352 }
353 
354 enum DynamicState {
355     viewport,
356     scissor,
357     lineWidth,
358     depthBias,
359     blendConstants,
360     depthBounds,
361     stencilCmpMask,
362     stencilWriteMask,
363     stencilRef,
364 }
365 
366 enum DescriptorType {
367     sampler,
368     combinedImageSampler,
369     sampledImage,
370     storageImage,
371     uniformTexelBuffer,
372     storageTexelBuffer,
373     uniformBuffer,
374     storageBuffer,
375     uniformBufferDynamic,
376     storageBufferDynamic,
377     inputAttachment,
378 }
379 
380 struct PipelineLayoutBinding {
381     uint binding;
382     DescriptorType descriptorType;
383     uint descriptorCount;
384     ShaderStage stages;
385 }
386 
387 struct PushConstantRange {
388     ShaderStage stages;
389     uint offset;
390     uint size;
391 }
392 
393 struct DescriptorPoolSize {
394     DescriptorType type;
395     uint count;
396 }
397 
398 struct WriteDescriptorSet {
399     DescriptorSet dstSet;
400     uint dstBinding;
401     uint dstArrayElem;
402     DescriptorWrites writes;
403 }
404 
405 struct CopyDescritporSet {
406     Trans!DescriptorSet set;
407     Trans!uint          binding;
408     Trans!uint          arrayElem;
409 }
410 
411 abstract class DescriptorWrites
412 {
413     this(DescriptorType type, size_t count) {
414         _type = type;
415         _count = count;
416     }
417     final @property DescriptorType type() const {
418         return _type;
419     }
420     final @property size_t count() const {
421         return _count;
422     }
423     private DescriptorType _type;
424     private size_t _count;
425 }
426 
427 class TDescWritesBase(Desc) : DescriptorWrites
428 {
429     this(Desc[] descs, DescriptorType type) {
430         super(type, descs.length);
431         _descs = descs;
432     }
433     final @property Desc[] descs() {
434         return _descs;
435     }
436     private Desc[] _descs;
437 }
438 
439 final class TDescWrites(Desc, DescriptorType ctType) : TDescWritesBase!Desc
440 {
441     this(Desc[] descs) {
442         super(descs, ctType);
443     }
444 }
445 
446 struct CombinedImageSampler {
447     Sampler sampler;
448     ImageView view;
449     ImageLayout layout;
450 }
451 
452 struct ImageViewLayout {
453     ImageView view;
454     ImageLayout layout;
455 }
456 
457 struct BufferRange {
458     Buffer buffer;
459     size_t offset;
460     size_t range;
461 }
462 
463 alias SamplerDescWrites = TDescWrites!(Sampler, DescriptorType.sampler);
464 alias CombinedImageSamplerDescWrites = TDescWrites!(CombinedImageSampler, DescriptorType.combinedImageSampler);
465 alias SampledImageDescWrites = TDescWrites!(ImageViewLayout, DescriptorType.sampledImage);
466 alias StorageImageDescWrites = TDescWrites!(ImageViewLayout, DescriptorType.storageImage);
467 alias InputAttachmentDescWrites = TDescWrites!(ImageViewLayout, DescriptorType.inputAttachment);
468 alias UniformBufferDescWrites = TDescWrites!(BufferRange, DescriptorType.uniformBuffer);
469 alias StorageBufferDescWrites = TDescWrites!(BufferRange, DescriptorType.storageBuffer);
470 alias UniformBufferDynamicDescWrites = TDescWrites!(BufferRange, DescriptorType.uniformBufferDynamic);
471 alias StorageBufferDynamicDescWrites = TDescWrites!(BufferRange, DescriptorType.storageBufferDynamic);
472 alias UniformTexelBufferDescWrites = TDescWrites!(BufferView, DescriptorType.uniformTexelBuffer);
473 alias StorageTexelBufferDescWrites = TDescWrites!(BufferView, DescriptorType.storageTexelBuffer);