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