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);