annotate src/zamikongine/shader.nim @ 485:b4a972bd37d5

did: change shader compilation to run during program compilation, maybe add dynamic version later
author Sam <sam@basx.dev>
date Wed, 11 Jan 2023 11:15:02 +0700
parents 73a0954beabd
children 9231df12b222
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
485
b4a972bd37d5 did: change shader compilation to run during program compilation, maybe add dynamic version later
Sam <sam@basx.dev>
parents: 483
diff changeset
1 import std/tempfiles
483
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
2 import std/strformat
480
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
3 import std/strutils
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
4 import std/tables
485
b4a972bd37d5 did: change shader compilation to run during program compilation, maybe add dynamic version later
Sam <sam@basx.dev>
parents: 483
diff changeset
5 import std/compilesettings
b4a972bd37d5 did: change shader compilation to run during program compilation, maybe add dynamic version later
Sam <sam@basx.dev>
parents: 483
diff changeset
6
480
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
7
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
8 import ./vulkan_helpers
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
9 import ./vulkan
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
10 import ./vertex
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
11
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
12 type
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
13 ShaderProgram* = object
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
14 entryPoint*: string
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
15 programType*: VkShaderStageFlagBits
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
16 shader*: VkPipelineShaderStageCreateInfo
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
17
485
b4a972bd37d5 did: change shader compilation to run during program compilation, maybe add dynamic version later
Sam <sam@basx.dev>
parents: 483
diff changeset
18 func stage2string(stage: VkShaderStageFlagBits): string {.compileTime.} =
483
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
19 case stage
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
20 of VK_SHADER_STAGE_VERTEX_BIT: "vert"
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
21 of VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: "tesc"
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
22 of VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: "tese"
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
23 of VK_SHADER_STAGE_GEOMETRY_BIT: "geom"
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
24 of VK_SHADER_STAGE_FRAGMENT_BIT: "frag"
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
25 of VK_SHADER_STAGE_ALL_GRAPHICS: ""
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
26 of VK_SHADER_STAGE_COMPUTE_BIT: "comp"
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
27 of VK_SHADER_STAGE_ALL: ""
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
28
485
b4a972bd37d5 did: change shader compilation to run during program compilation, maybe add dynamic version later
Sam <sam@basx.dev>
parents: 483
diff changeset
29 proc compileGLSLToSPIRV(stage: VkShaderStageFlagBits, shaderSource: string, entrypoint: string): seq[uint32] {.compileTime.} =
483
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
30 let stagename = stage2string(stage)
485
b4a972bd37d5 did: change shader compilation to run during program compilation, maybe add dynamic version later
Sam <sam@basx.dev>
parents: 483
diff changeset
31 let (tmpfile, tmpfilename) = createTempFile("shader", stage2string(stage))
b4a972bd37d5 did: change shader compilation to run during program compilation, maybe add dynamic version later
Sam <sam@basx.dev>
parents: 483
diff changeset
32 tmpfile.close()
b4a972bd37d5 did: change shader compilation to run during program compilation, maybe add dynamic version later
Sam <sam@basx.dev>
parents: 483
diff changeset
33 let (output, exitCode) = gorgeEx(command=fmt"{querySetting(projectPath)}/glslangValidator --entry-point {entrypoint} -V --stdin -S {stagename} -o {tmpfilename}", input=shaderSource)
483
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
34 if exitCode != 0:
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
35 raise newException(Exception, output)
485
b4a972bd37d5 did: change shader compilation to run during program compilation, maybe add dynamic version later
Sam <sam@basx.dev>
parents: 483
diff changeset
36 let shaderbinary = staticRead tmpfilename
483
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
37 var i = 0
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
38 while i < shaderbinary.len:
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
39 result.add(
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
40 (uint32(shaderbinary[i + 0]) shl 0) or
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
41 (uint32(shaderbinary[i + 1]) shl 8) or
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
42 (uint32(shaderbinary[i + 2]) shl 16) or
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
43 (uint32(shaderbinary[i + 3]) shl 24)
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
44 )
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
45 i += 4
73a0954beabd did: improve alotof_triangles example, remove glslang lib, use only binary, easier cross-compilation
Sam <sam@basx.dev>
parents: 480
diff changeset
46
485
b4a972bd37d5 did: change shader compilation to run during program compilation, maybe add dynamic version later
Sam <sam@basx.dev>
parents: 483
diff changeset
47 proc initShaderProgram*(device: VkDevice, programType: static VkShaderStageFlagBits, shader: static string, entryPoint: static string="main"): ShaderProgram =
480
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
48 result.entryPoint = entryPoint
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
49 result.programType = programType
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
50
485
b4a972bd37d5 did: change shader compilation to run during program compilation, maybe add dynamic version later
Sam <sam@basx.dev>
parents: 483
diff changeset
51 const constcode = compileGLSLToSPIRV(programType, shader, entryPoint)
b4a972bd37d5 did: change shader compilation to run during program compilation, maybe add dynamic version later
Sam <sam@basx.dev>
parents: 483
diff changeset
52 var code = constcode
480
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
53 var createInfo = VkShaderModuleCreateInfo(
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
54 sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
55 codeSize: uint(code.len * sizeof(uint32)),
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
56 pCode: if code.len > 0: addr(code[0]) else: nil,
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
57 )
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
58 var shaderModule: VkShaderModule
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
59 checkVkResult vkCreateShaderModule(device, addr(createInfo), nil, addr(shaderModule))
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
60
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
61 result.shader = VkPipelineShaderStageCreateInfo(
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
62 sType: VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
63 stage: programType,
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
64 module: shaderModule,
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
65 pName: cstring(result.entryPoint), # entry point for shader
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
66 )
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
67
485
b4a972bd37d5 did: change shader compilation to run during program compilation, maybe add dynamic version later
Sam <sam@basx.dev>
parents: 483
diff changeset
68 func generateVertexShaderCode*[T](entryPoint, positionAttrName, colorAttrName: static string): string {.compileTime.} =
480
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
69 var lines: seq[string]
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
70 lines.add "#version 450"
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
71 lines.add generateGLSLDeclarations[T]()
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
72 lines.add "layout(location = 0) out vec3 fragColor;"
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
73 lines.add "void " & entryPoint & "() {"
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
74
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
75 for name, value in T().fieldPairs:
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
76 when typeof(value) is VertexAttribute and name == positionAttrName:
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
77 lines.add " gl_Position = vec4(" & name & ", 0.0, 1.0);"
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
78 when typeof(value) is VertexAttribute and name == colorAttrName:
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
79 lines.add " fragColor = " & name & ";"
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
80 lines.add "}"
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
81 return lines.join("\n")
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
82
485
b4a972bd37d5 did: change shader compilation to run during program compilation, maybe add dynamic version later
Sam <sam@basx.dev>
parents: 483
diff changeset
83 func generateFragmentShaderCode*[T](entryPoint: static string): string {.compileTime.} =
480
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
84 var lines: seq[string]
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
85 lines.add "#version 450"
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
86 lines.add "layout(location = 0) in vec3 fragColor;"
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
87 lines.add "layout(location = 0) out vec4 outColor;"
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
88 lines.add "void " & entryPoint & "() {"
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
89 lines.add " outColor = vec4(fragColor, 1.0);"
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
90 lines.add "}"
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
91
14e5151f68d1 did: introduce scene graph, meshs and generic vertex buffers
Sam <sam@basx.dev>
parents:
diff changeset
92 return lines.join("\n")