comparison semiconginev2/rendering/shaders.nim @ 1218:56781cc0fc7c compiletime-tests

did: renamge main package
author sam <sam@basx.dev>
date Wed, 17 Jul 2024 21:01:37 +0700
parents semicongine/rendering/shaders.nim@570ac1620fb6
children 4e465583ea32
comparison
equal deleted inserted replaced
1217:f819a874058f 1218:56781cc0fc7c
1 func GlslType[T: SupportedGPUType|Texture](value: T): string =
2 when T is float32: "float"
3 elif T is float64: "double"
4 elif T is int8 or T is int16 or T is int32 or T is int64: "int"
5 elif T is uint8 or T is uint16 or T is uint32 or T is uint64: "uint"
6 elif T is TVec2[int32]: "ivec2"
7 elif T is TVec2[int64]: "ivec2"
8 elif T is TVec3[int32]: "ivec3"
9 elif T is TVec3[int64]: "ivec3"
10 elif T is TVec4[int32]: "ivec4"
11 elif T is TVec4[int64]: "ivec4"
12 elif T is TVec2[uint32]: "uvec2"
13 elif T is TVec2[uint64]: "uvec2"
14 elif T is TVec3[uint32]: "uvec3"
15 elif T is TVec3[uint64]: "uvec3"
16 elif T is TVec4[uint32]: "uvec4"
17 elif T is TVec4[uint64]: "uvec4"
18 elif T is TVec2[float32]: "vec2"
19 elif T is TVec2[float64]: "dvec2"
20 elif T is TVec3[float32]: "vec3"
21 elif T is TVec3[float64]: "dvec3"
22 elif T is TVec4[float32]: "vec4"
23 elif T is TVec4[float64]: "dvec4"
24 elif T is TMat2[float32]: "mat2"
25 elif T is TMat2[float64]: "dmat2"
26 elif T is TMat23[float32]: "mat23"
27 elif T is TMat23[float64]: "dmat23"
28 elif T is TMat32[float32]: "mat32"
29 elif T is TMat32[float64]: "dmat32"
30 elif T is TMat3[float32]: "mat3"
31 elif T is TMat3[float64]: "dmat3"
32 elif T is TMat34[float32]: "mat34"
33 elif T is TMat34[float64]: "dmat34"
34 elif T is TMat43[float32]: "mat43"
35 elif T is TMat43[float64]: "dmat43"
36 elif T is TMat4[float32]: "mat4"
37 elif T is TMat4[float64]: "dmat4"
38 elif T is Texture: "sampler2D"
39 else: {.error: "Unsupported data type on GPU".}
40
41 func VkType[T: SupportedGPUType](value: T): VkFormat =
42 when T is float32: VK_FORMAT_R32_SFLOAT
43 elif T is float64: VK_FORMAT_R64_SFLOAT
44 elif T is int8: VK_FORMAT_R8_SINT
45 elif T is int16: VK_FORMAT_R16_SINT
46 elif T is int32: VK_FORMAT_R32_SINT
47 elif T is int64: VK_FORMAT_R64_SINT
48 elif T is uint8: VK_FORMAT_R8_UINT
49 elif T is uint16: VK_FORMAT_R16_UINT
50 elif T is uint32: VK_FORMAT_R32_UINT
51 elif T is uint64: VK_FORMAT_R64_UINT
52 elif T is TVec2[int32]: VK_FORMAT_R32G32_SINT
53 elif T is TVec2[int64]: VK_FORMAT_R64G64_SINT
54 elif T is TVec3[int32]: VK_FORMAT_R32G32B32_SINT
55 elif T is TVec3[int64]: VK_FORMAT_R64G64B64_SINT
56 elif T is TVec4[int32]: VK_FORMAT_R32G32B32A32_SINT
57 elif T is TVec4[int64]: VK_FORMAT_R64G64B64A64_SINT
58 elif T is TVec2[uint32]: VK_FORMAT_R32G32_UINT
59 elif T is TVec2[uint64]: VK_FORMAT_R64G64_UINT
60 elif T is TVec3[uint32]: VK_FORMAT_R32G32B32_UINT
61 elif T is TVec3[uint64]: VK_FORMAT_R64G64B64_UINT
62 elif T is TVec4[uint32]: VK_FORMAT_R32G32B32A32_UINT
63 elif T is TVec4[uint64]: VK_FORMAT_R64G64B64A64_UINT
64 elif T is TVec2[float32]: VK_FORMAT_R32G32_SFLOAT
65 elif T is TVec2[float64]: VK_FORMAT_R64G64_SFLOAT
66 elif T is TVec3[float32]: VK_FORMAT_R32G32B32_SFLOAT
67 elif T is TVec3[float64]: VK_FORMAT_R64G64B64_SFLOAT
68 elif T is TVec4[float32]: VK_FORMAT_R32G32B32A32_SFLOAT
69 elif T is TVec4[float64]: VK_FORMAT_R64G64B64A64_SFLOAT
70 elif T is TMat2[float32]: VK_FORMAT_R32G32_SFLOAT
71 elif T is TMat2[float64]: VK_FORMAT_R64G64_SFLOAT
72 elif T is TMat23[float32]: VK_FORMAT_R32G32B32_SFLOAT
73 elif T is TMat23[float64]: VK_FORMAT_R64G64B64_SFLOAT
74 elif T is TMat32[float32]: VK_FORMAT_R32G32_SFLOAT
75 elif T is TMat32[float64]: VK_FORMAT_R64G64_SFLOAT
76 elif T is TMat3[float32]: VK_FORMAT_R32G32B32_SFLOAT
77 elif T is TMat3[float64]: VK_FORMAT_R64G64B64_SFLOAT
78 elif T is TMat34[float32]: VK_FORMAT_R32G32B32A32_SFLOAT
79 elif T is TMat34[float64]: VK_FORMAT_R64G64B64A64_SFLOAT
80 elif T is TMat43[float32]: VK_FORMAT_R32G32B32_SFLOAT
81 elif T is TMat43[float64]: VK_FORMAT_R64G64B64_SFLOAT
82 elif T is TMat4[float32]: VK_FORMAT_R32G32B32A32_SFLOAT
83 elif T is TMat4[float64]: VK_FORMAT_R64G64B64A64_SFLOAT
84 else: {.error: "Unsupported data type on GPU".}
85
86
87 func NumberOfVertexInputAttributeDescriptors[T: SupportedGPUType|Texture](value: T): uint32 =
88 when T is TMat2[float32] or T is TMat2[float64] or T is TMat23[float32] or T is TMat23[float64]:
89 2
90 elif T is TMat32[float32] or T is TMat32[float64] or T is TMat3[float32] or T is TMat3[float64] or T is TMat34[float32] or T is TMat34[float64]:
91 3
92 elif T is TMat43[float32] or T is TMat43[float64] or T is TMat4[float32] or T is TMat4[float64]:
93 4
94 else:
95 1
96
97 func NLocationSlots[T: SupportedGPUType|Texture](value: T): uint32 =
98 #[
99 single location:
100 - any scalar
101 - any 16-bit vector
102 - any 32-bit vector
103 - any 64-bit vector that has max. 2 components
104 16-bit scalar and vector types, and
105 32-bit scalar and vector types, and
106 64-bit scalar and 2-component vector types.
107 two locations
108 64-bit three- and four-component vectors
109 ]#
110 when T is TVec3[int64] or
111 T is TVec4[int64] or
112 T is TVec3[uint64] or
113 T is TVec4[uint64] or
114 T is TVec3[float64] or
115 T is TVec4[float64] or
116 T is TMat23[float64] or
117 T is TMat3[float64] or
118 T is TMat34[float64] or
119 T is TMat43[float64] or
120 T is TMat4[float64]:
121 return 2
122 else:
123 return 1
124
125 proc generateShaderSource[TShader](shader: TShader): (string, string) {.compileTime.} =
126 const GLSL_VERSION = "450"
127 var vsInput: seq[string]
128 var vsOutput: seq[string]
129 var fsInput: seq[string]
130 var fsOutput: seq[string]
131 var uniforms: seq[string]
132 var samplers: seq[string]
133 var vsInputLocation = 0'u32
134 var passLocation = 0
135 var fsOutputLocation = 0
136
137 var sawDescriptorSets = false
138 for fieldname, value in fieldPairs(shader):
139 # vertex shader inputs
140 when hasCustomPragma(value, VertexAttribute) or hasCustomPragma(value, InstanceAttribute):
141 assert typeof(value) is SupportedGPUType
142 vsInput.add "layout(location = " & $vsInputLocation & ") in " & GlslType(value) & " " & fieldname & ";"
143 for j in 0 ..< NumberOfVertexInputAttributeDescriptors(value):
144 vsInputLocation += NLocationSlots(value)
145
146 # intermediate values, passed between shaders
147 elif hasCustomPragma(value, Pass) or hasCustomPragma(value, PassFlat):
148 let flat = if hasCustomPragma(value, PassFlat): "flat " else: ""
149 vsOutput.add "layout(location = " & $passLocation & ") " & flat & "out " & GlslType(value) & " " & fieldname & ";"
150 fsInput.add "layout(location = " & $passLocation & ") " & flat & "in " & GlslType(value) & " " & fieldname & ";"
151 passLocation.inc
152
153 # fragment shader output
154 elif hasCustomPragma(value, ShaderOutput):
155 fsOutput.add &"layout(location = " & $fsOutputLocation & ") out " & GlslType(value) & " " & fieldname & ";"
156 fsOutputLocation.inc
157
158 # descriptor sets
159 # need to consider 4 cases: uniform block, texture, uniform block array, texture array
160 elif hasCustomPragma(value, DescriptorSets):
161 assert not sawDescriptorSets, "Only one field with pragma DescriptorSets allowed per shader"
162 assert typeof(value) is tuple, "Descriptor field '" & fieldname & "' must be of type tuple"
163 assert tupleLen(typeof(value)) <= MAX_DESCRIPTORSETS, typetraits.name(TShader) & ": maximum " & $MAX_DESCRIPTORSETS & " allowed"
164 sawDescriptorSets = true
165 var descriptorSetIndex = 0
166 for descriptor in value.fields:
167
168 var descriptorBinding = 0
169
170 for descriptorName, descriptorValue in fieldPairs(descriptor):
171
172 when typeof(descriptorValue) is Texture:
173 samplers.add "layout(set=" & $descriptorSetIndex & ", binding = " & $descriptorBinding & ") uniform " & GlslType(descriptorValue) & " " & descriptorName & ";"
174 descriptorBinding.inc
175
176 elif typeof(descriptorValue) is GPUValue:
177
178 uniforms.add "layout(set=" & $descriptorSetIndex & ", binding = " & $descriptorBinding & ") uniform T" & descriptorName & " {"
179 when typeof(descriptorValue.data) is object:
180
181 for blockFieldName, blockFieldValue in descriptorValue.data.fieldPairs():
182 assert typeof(blockFieldValue) is SupportedGPUType, "uniform block field '" & blockFieldName & "' is not a SupportedGPUType"
183 uniforms.add " " & GlslType(blockFieldValue) & " " & blockFieldName & ";"
184 uniforms.add "} " & descriptorName & ";"
185
186 else:
187 {.error: "Unsupported shader descriptor field " & descriptorName & " (must be object)".}
188 descriptorBinding.inc
189
190 elif typeof(descriptorValue) is array:
191
192 when elementType(descriptorValue) is Texture:
193
194 let arrayDecl = "[" & $typeof(descriptorValue).len & "]"
195 samplers.add "layout(set=" & $descriptorSetIndex & ", binding = " & $descriptorBinding & ") uniform " & GlslType(default(elementType(descriptorValue))) & " " & descriptorName & "" & arrayDecl & ";"
196 descriptorBinding.inc
197
198 elif elementType(descriptorValue) is GPUValue:
199
200 uniforms.add "layout(set=" & $descriptorSetIndex & ", binding = " & $descriptorBinding & ") uniform T" & descriptorName & " {"
201
202 for blockFieldName, blockFieldValue in default(elementType(descriptorValue)).data.fieldPairs():
203 assert typeof(blockFieldValue) is SupportedGPUType, "uniform block field '" & blockFieldName & "' is not a SupportedGPUType"
204 uniforms.add " " & GlslType(blockFieldValue) & " " & blockFieldName & ";"
205 uniforms.add "} " & descriptorName & "[" & $descriptorValue.len & "];"
206 descriptorBinding.inc
207
208 else:
209 {.error: "Unsupported shader descriptor field " & descriptorName.}
210
211 descriptorSetIndex.inc
212 elif fieldname in ["vertexCode", "fragmentCode"]:
213 discard
214 else:
215 {.error: "Unsupported shader field '" & typetraits.name(TShader) & "." & fieldname & "' of type " & typetraits.name(typeof(value)).}
216
217 result[0] = (@[&"#version {GLSL_VERSION}", "#extension GL_EXT_scalar_block_layout : require", ""] &
218 vsInput &
219 uniforms &
220 samplers &
221 vsOutput &
222 @[shader.vertexCode]).join("\n")
223
224 result[1] = (@[&"#version {GLSL_VERSION}", "#extension GL_EXT_scalar_block_layout : require", ""] &
225 fsInput &
226 uniforms &
227 samplers &
228 fsOutput &
229 @[shader.fragmentCode]).join("\n")
230
231 proc compileGlslToSPIRV(stage: VkShaderStageFlagBits, shaderSource: string): seq[uint32] {.compileTime.} =
232 func stage2string(stage: VkShaderStageFlagBits): string {.compileTime.} =
233 case stage
234 of VK_SHADER_STAGE_VERTEX_BIT: "vert"
235 of VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: "tesc"
236 of VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: "tese"
237 of VK_SHADER_STAGE_GEOMETRY_BIT: "geom"
238 of VK_SHADER_STAGE_FRAGMENT_BIT: "frag"
239 of VK_SHADER_STAGE_COMPUTE_BIT: "comp"
240 else: ""
241
242 when defined(nimcheck): # will not run if nimcheck is running
243 return result
244
245 let
246 stagename = stage2string(stage)
247 shaderHash = hash(shaderSource)
248 shaderfile = getTempDir() / &"shader_{shaderHash}.{stagename}"
249
250 if not shaderfile.fileExists:
251 echo "shader of type ", stage
252 for i, line in enumerate(shaderSource.splitlines()):
253 echo " ", i + 1, " ", line
254 var glslExe = currentSourcePath.parentDir.parentDir.parentDir / "tools" / "glslangValidator"
255 when defined(windows):
256 glslExe = glslExe & "." & ExeExt
257 let command = &"{glslExe} --entry-point main -V --stdin -S {stagename} -o {shaderfile}"
258 echo "run: ", command
259 discard StaticExecChecked(
260 command = command,
261 input = shaderSource
262 )
263 else:
264 echo &"shaderfile {shaderfile} is up-to-date"
265
266 when defined(mingw) and defined(linux): # required for crosscompilation, path separators get messed up
267 let shaderbinary = staticRead shaderfile.replace("\\", "/")
268 else:
269 let shaderbinary = staticRead shaderfile
270
271 var i = 0
272 while i < shaderbinary.len:
273 result.add(
274 (uint32(shaderbinary[i + 0]) shl 0) or
275 (uint32(shaderbinary[i + 1]) shl 8) or
276 (uint32(shaderbinary[i + 2]) shl 16) or
277 (uint32(shaderbinary[i + 3]) shl 24)
278 )
279 i += 4
280
281
282 proc CompileShader[TShader](shader: static TShader): (VkShaderModule, VkShaderModule) =
283 const (vertexShaderSource, fragmentShaderSource) = generateShaderSource(shader)
284
285 let vertexBinary = compileGlslToSPIRV(VK_SHADER_STAGE_VERTEX_BIT, vertexShaderSource)
286 let fragmentBinary = compileGlslToSPIRV(VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShaderSource)
287
288 var createInfoVertex = VkShaderModuleCreateInfo(
289 sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
290 codeSize: csize_t(vertexBinary.len * sizeof(uint32)),
291 pCode: vertexBinary.ToCPointer,
292 )
293 checkVkResult vulkan.device.vkCreateShaderModule(addr(createInfoVertex), nil, addr(result[0]))
294 var createInfoFragment = VkShaderModuleCreateInfo(
295 sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
296 codeSize: csize_t(fragmentBinary.len * sizeof(uint32)),
297 pCode: fragmentBinary.ToCPointer,
298 )
299 checkVkResult vulkan.device.vkCreateShaderModule(addr(createInfoFragment), nil, addr(result[1]))
300
301 template ForVertexDataFields(shader: typed, fieldname, valuename, isinstancename, body: untyped): untyped =
302 for theFieldname, value in fieldPairs(shader):
303 when hasCustomPragma(value, VertexAttribute) or hasCustomPragma(value, InstanceAttribute):
304 when not typeof(value) is seq:
305 {.error: "field '" & theFieldname & "' needs to be a seq".}
306 when not typeof(value) is SupportedGPUType:
307 {.error: "field '" & theFieldname & "' is not a supported GPU type".}
308 block:
309 const `fieldname` {.inject.} = theFieldname
310 let `valuename` {.inject.} = value
311 const `isinstancename` {.inject.} = hasCustomPragma(value, InstanceAttribute)
312 body
313
314 proc GetDescriptorSetCount[TShader](): uint32 =
315 for _, value in fieldPairs(default(TShader)):
316 when hasCustomPragma(value, DescriptorSets):
317 return tupleLen(typeof(value)).uint32
318
319 proc CreateDescriptorSetLayouts[TShader](): array[MAX_DESCRIPTORSETS, VkDescriptorSetLayout] =
320 var setNumber: int
321 for _, value in fieldPairs(default(TShader)):
322 when hasCustomPragma(value, DescriptorSets):
323 for descriptorSet in value.fields:
324 var layoutbindings: seq[VkDescriptorSetLayoutBinding]
325 ForDescriptorFields(descriptorSet, fieldName, fieldValue, descriptorType, descriptorCount, descriptorBindingNumber):
326 layoutbindings.add VkDescriptorSetLayoutBinding(
327 binding: descriptorBindingNumber,
328 descriptorType: descriptorType,
329 descriptorCount: descriptorCount,
330 stageFlags: VkShaderStageFlags(VK_SHADER_STAGE_ALL_GRAPHICS),
331 pImmutableSamplers: nil,
332 )
333 var layoutCreateInfo = VkDescriptorSetLayoutCreateInfo(
334 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
335 bindingCount: layoutbindings.len.uint32,
336 pBindings: layoutbindings.ToCPointer
337 )
338 checkVkResult vkCreateDescriptorSetLayout(
339 vulkan.device,
340 addr(layoutCreateInfo),
341 nil,
342 addr(result[setNumber])
343 )
344 inc setNumber
345
346 proc CreatePipeline*[TShader](
347 renderPass: VkRenderPass,
348 topology: VkPrimitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
349 polygonMode: VkPolygonMode = VK_POLYGON_MODE_FILL,
350 cullMode: VkCullModeFlagBits = VK_CULL_MODE_BACK_BIT,
351 frontFace: VkFrontFace = VK_FRONT_FACE_CLOCKWISE,
352 descriptorPoolLimit = 1024,
353 samples = VK_SAMPLE_COUNT_1_BIT,
354 ): Pipeline[TShader] =
355 # create pipeline
356
357 const shader = default(TShader)
358 (result.vertexShaderModule, result.fragmentShaderModule) = CompileShader(shader)
359
360 var nSets = GetDescriptorSetCount[TShader]()
361 result.descriptorSetLayouts = CreateDescriptorSetLayouts[TShader]()
362 let pipelineLayoutInfo = VkPipelineLayoutCreateInfo(
363 sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
364 setLayoutCount: nSets,
365 pSetLayouts: if nSets == 0: nil else: result.descriptorSetLayouts.ToCPointer,
366 # pushConstantRangeCount: uint32(pushConstants.len),
367 # pPushConstantRanges: pushConstants.ToCPointer,
368 )
369 checkVkResult vkCreatePipelineLayout(vulkan.device, addr(pipelineLayoutInfo), nil, addr(result.layout))
370
371 let stages = [
372 VkPipelineShaderStageCreateInfo(
373 sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
374 stage: VK_SHADER_STAGE_VERTEX_BIT,
375 module: result.vertexShaderModule,
376 pName: "main",
377 ),
378 VkPipelineShaderStageCreateInfo(
379 sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
380 stage: VK_SHADER_STAGE_FRAGMENT_BIT,
381 module: result.fragmentShaderModule,
382 pName: "main",
383 ),
384 ]
385 var
386 bindings: seq[VkVertexInputBindingDescription]
387 attributes: seq[VkVertexInputAttributeDescription]
388 var inputBindingNumber = 0'u32
389 var location = 0'u32
390 ForVertexDataFields(default(TShader), fieldname, value, isInstanceAttr):
391 bindings.add VkVertexInputBindingDescription(
392 binding: inputBindingNumber,
393 stride: sizeof(value).uint32,
394 inputRate: if isInstanceAttr: VK_VERTEX_INPUT_RATE_INSTANCE else: VK_VERTEX_INPUT_RATE_VERTEX,
395 )
396 # allows to submit larger data structures like Mat44, for most other types will be 1
397 let perDescriptorSize = sizeof(value).uint32 div NumberOfVertexInputAttributeDescriptors(value)
398 for i in 0'u32 ..< NumberOfVertexInputAttributeDescriptors(value):
399 attributes.add VkVertexInputAttributeDescription(
400 binding: inputBindingNumber,
401 location: location,
402 format: VkType(value),
403 offset: i * perDescriptorSize,
404 )
405 location += NLocationSlots(value)
406 inc inputBindingNumber
407
408 let
409 vertexInputInfo = VkPipelineVertexInputStateCreateInfo(
410 sType: VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
411 vertexBindingDescriptionCount: uint32(bindings.len),
412 pVertexBindingDescriptions: bindings.ToCPointer,
413 vertexAttributeDescriptionCount: uint32(attributes.len),
414 pVertexAttributeDescriptions: attributes.ToCPointer,
415 )
416 inputAssembly = VkPipelineInputAssemblyStateCreateInfo(
417 sType: VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
418 topology: topology,
419 primitiveRestartEnable: false,
420 )
421 viewportState = VkPipelineViewportStateCreateInfo(
422 sType: VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
423 viewportCount: 1,
424 scissorCount: 1,
425 )
426 rasterizer = VkPipelineRasterizationStateCreateInfo(
427 sType: VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
428 depthClampEnable: VK_FALSE,
429 rasterizerDiscardEnable: VK_FALSE,
430 polygonMode: polygonMode,
431 lineWidth: 1.0,
432 cullMode: toBits [cullMode],
433 frontFace: frontFace,
434 depthBiasEnable: VK_FALSE,
435 depthBiasConstantFactor: 0.0,
436 depthBiasClamp: 0.0,
437 depthBiasSlopeFactor: 0.0,
438 )
439 multisampling = VkPipelineMultisampleStateCreateInfo(
440 sType: VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
441 sampleShadingEnable: VK_FALSE,
442 rasterizationSamples: samples,
443 minSampleShading: 1.0,
444 pSampleMask: nil,
445 alphaToCoverageEnable: VK_FALSE,
446 alphaToOneEnable: VK_FALSE,
447 )
448 colorBlendAttachment = VkPipelineColorBlendAttachmentState(
449 colorWriteMask: toBits [VK_COLOR_COMPONENT_R_BIT, VK_COLOR_COMPONENT_G_BIT, VK_COLOR_COMPONENT_B_BIT, VK_COLOR_COMPONENT_A_BIT],
450 blendEnable: VK_TRUE,
451 srcColorBlendFactor: VK_BLEND_FACTOR_SRC_ALPHA,
452 dstColorBlendFactor: VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
453 colorBlendOp: VK_BLEND_OP_ADD,
454 srcAlphaBlendFactor: VK_BLEND_FACTOR_ONE,
455 dstAlphaBlendFactor: VK_BLEND_FACTOR_ZERO,
456 alphaBlendOp: VK_BLEND_OP_ADD,
457 )
458 colorBlending = VkPipelineColorBlendStateCreateInfo(
459 sType: VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
460 logicOpEnable: false,
461 attachmentCount: 1,
462 pAttachments: addr(colorBlendAttachment),
463 )
464 dynamicStates = [VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR]
465 dynamicState = VkPipelineDynamicStateCreateInfo(
466 sType: VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
467 dynamicStateCount: dynamicStates.len.uint32,
468 pDynamicStates: dynamicStates.ToCPointer,
469 )
470 let createInfo = VkGraphicsPipelineCreateInfo(
471 sType: VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
472 stageCount: 2,
473 pStages: stages.ToCPointer,
474 pVertexInputState: addr(vertexInputInfo),
475 pInputAssemblyState: addr(inputAssembly),
476 pViewportState: addr(viewportState),
477 pRasterizationState: addr(rasterizer),
478 pMultisampleState: addr(multisampling),
479 pDepthStencilState: nil,
480 pColorBlendState: addr(colorBlending),
481 pDynamicState: addr(dynamicState),
482 layout: result.layout,
483 renderPass: renderPass,
484 subpass: 0,
485 basePipelineHandle: VkPipeline(0),
486 basePipelineIndex: -1,
487 )
488 checkVkResult vkCreateGraphicsPipelines(
489 vulkan.device,
490 VkPipelineCache(0),
491 1,
492 addr(createInfo),
493 nil,
494 addr(result.vk)
495 )
496
497 template WithPipeline*(commandbuffer: VkCommandBuffer, pipeline: Pipeline, body: untyped): untyped =
498 block:
499 vkCmdBindPipeline(commandbuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.vk)
500 body
501
502 proc DestroyPipeline*(pipeline: Pipeline) =
503
504 for descriptorSetLayout in pipeline.descriptorSetLayouts:
505 vkDestroyDescriptorSetLayout(vulkan.device, descriptorSetLayout, nil)
506
507 vkDestroyShaderModule(vulkan.device, pipeline.vertexShaderModule, nil)
508 vkDestroyShaderModule(vulkan.device, pipeline.fragmentShaderModule, nil)
509 vkDestroyPipelineLayout(vulkan.device, pipeline.layout, nil)
510 vkDestroyPipeline(vulkan.device, pipeline.vk, nil)