comparison src/zamikongine/shader.nim @ 28:b1b05d4efb52

big refactoring, part1
author Sam <sam@basx.dev>
date Sat, 14 Jan 2023 14:08:00 +0700
parents 8f290112718a
children 9edca5dc4e93
comparison
equal deleted inserted replaced
27:8cb2d96ac28e 28:b1b05d4efb52
5 5
6 6
7 import ./vulkan_helpers 7 import ./vulkan_helpers
8 import ./vulkan 8 import ./vulkan
9 import ./vertex 9 import ./vertex
10 import ./math/vector
10 11
11 type 12 type
12 ShaderProgram* = object 13 AllowedUniformType = SomeNumber|Vec
14 UniformSlot *[T:AllowedUniformType] = object
15 ShaderProgram*[Uniforms] = object
13 entryPoint*: string 16 entryPoint*: string
14 programType*: VkShaderStageFlagBits 17 programType*: VkShaderStageFlagBits
15 shader*: VkPipelineShaderStageCreateInfo 18 shader*: VkPipelineShaderStageCreateInfo
19 uniforms*: Uniforms
16 20
17 func stage2string(stage: VkShaderStageFlagBits): string {.compileTime.} = 21 func stage2string(stage: VkShaderStageFlagBits): string {.compileTime.} =
18 case stage 22 case stage
19 of VK_SHADER_STAGE_VERTEX_BIT: "vert" 23 of VK_SHADER_STAGE_VERTEX_BIT: "vert"
20 of VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: "tesc" 24 of VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: "tesc"
24 of VK_SHADER_STAGE_ALL_GRAPHICS: "" 28 of VK_SHADER_STAGE_ALL_GRAPHICS: ""
25 of VK_SHADER_STAGE_COMPUTE_BIT: "comp" 29 of VK_SHADER_STAGE_COMPUTE_BIT: "comp"
26 of VK_SHADER_STAGE_ALL: "" 30 of VK_SHADER_STAGE_ALL: ""
27 31
28 proc compileGLSLToSPIRV(stage: VkShaderStageFlagBits, shaderSource: string, entrypoint: string): seq[uint32] {.compileTime.} = 32 proc compileGLSLToSPIRV(stage: VkShaderStageFlagBits, shaderSource: string, entrypoint: string): seq[uint32] {.compileTime.} =
29 # TODO: compiles only on linux for now (because we don't have compile-time functionality in std/tempfile)
30 let stagename = stage2string(stage) 33 let stagename = stage2string(stage)
31 34
35 # TODO: compiles only on linux for now (because we don't have compile-time functionality in std/tempfile)
36 if not defined(linux):
37 raise newException(Exception, "Compilation is currently only supported on linux (need mktemp command), sorry!")
32 let (tmpfile, exitCode) = gorgeEx(command=fmt"mktemp --tmpdir shader_XXXXXXX.{stagename}") 38 let (tmpfile, exitCode) = gorgeEx(command=fmt"mktemp --tmpdir shader_XXXXXXX.{stagename}")
33 if exitCode != 0: 39 if exitCode != 0:
34 raise newException(Exception, tmpfile) 40 raise newException(Exception, tmpfile)
35 41
36 let (output, exitCode_glsl) = gorgeEx(command=fmt"{querySetting(projectPath)}/glslangValidator --entry-point {entrypoint} -V --stdin -S {stagename} -o {tmpfile}", input=shaderSource) 42 let (output, exitCode_glsl) = gorgeEx(command=fmt"{querySetting(projectPath)}/glslangValidator --entry-point {entrypoint} -V --stdin -S {stagename} -o {tmpfile}", input=shaderSource)
50 (uint32(shaderbinary[i + 2]) shl 16) or 56 (uint32(shaderbinary[i + 2]) shl 16) or
51 (uint32(shaderbinary[i + 3]) shl 24) 57 (uint32(shaderbinary[i + 3]) shl 24)
52 ) 58 )
53 i += 4 59 i += 4
54 60
55 proc initShaderProgram*(device: VkDevice, programType: static VkShaderStageFlagBits, shader: static string, entryPoint: static string="main"): ShaderProgram = 61 proc initShaderProgram*[T](device: VkDevice, programType: static VkShaderStageFlagBits, shader: static string, entryPoint: static string="main"): ShaderProgram[T] =
56 result.entryPoint = entryPoint 62 result.entryPoint = entryPoint
57 result.programType = programType 63 result.programType = programType
58 64
59 const constcode = compileGLSLToSPIRV(programType, shader, entryPoint) 65 const constcode = compileGLSLToSPIRV(programType, shader, entryPoint)
60 var code = constcode 66 var code = constcode
71 stage: programType, 77 stage: programType,
72 module: shaderModule, 78 module: shaderModule,
73 pName: cstring(result.entryPoint), # entry point for shader 79 pName: cstring(result.entryPoint), # entry point for shader
74 ) 80 )
75 81
76 func generateVertexShaderCode*[T](entryPoint, positionAttrName, colorAttrName: static string): string {.compileTime.} = 82 func generateVertexShaderCode*[VertexType](entryPoint, positionAttrName, colorAttrName: static string): string {.compileTime.} =
77 var lines: seq[string] 83 var lines: seq[string]
78 lines.add "#version 450" 84 lines.add "#version 450"
79 lines.add generateGLSLDeclarations[T]() 85 # lines.add "layout(binding = 0) uniform UniformBufferObject { float dt; } ubo;"
86 lines.add generateGLSLDeclarations[VertexType]()
80 lines.add "layout(location = 0) out vec3 fragColor;" 87 lines.add "layout(location = 0) out vec3 fragColor;"
81 lines.add "void " & entryPoint & "() {" 88 lines.add "void " & entryPoint & "() {"
82 89
83 for name, value in T().fieldPairs: 90 for name, value in VertexType().fieldPairs:
84 when typeof(value) is VertexAttribute and name == positionAttrName: 91 when typeof(value) is VertexAttribute and name == positionAttrName:
85 lines.add " gl_Position = vec4(" & name & ", 0.0, 1.0);" 92 # lines.add " vec2 tmp = " & name & " * ubo.dt;"
93 lines.add " vec2 tmp = " & name & ";"
94 lines.add " gl_Position = vec4(tmp, 0.0, 1.0);"
86 when typeof(value) is VertexAttribute and name == colorAttrName: 95 when typeof(value) is VertexAttribute and name == colorAttrName:
87 lines.add " fragColor = " & name & ";" 96 lines.add " fragColor = " & name & ";"
88 lines.add "}" 97 lines.add "}"
89 return lines.join("\n") 98 return lines.join("\n")
90 99
91 func generateFragmentShaderCode*[T](entryPoint: static string): string {.compileTime.} = 100 func generateFragmentShaderCode*[VertexType](entryPoint: static string): string {.compileTime.} =
92 var lines: seq[string] 101 var lines: seq[string]
93 lines.add "#version 450" 102 lines.add "#version 450"
94 lines.add "layout(location = 0) in vec3 fragColor;" 103 lines.add "layout(location = 0) in vec3 fragColor;"
95 lines.add "layout(location = 0) out vec4 outColor;" 104 lines.add "layout(location = 0) out vec4 outColor;"
96 lines.add "void " & entryPoint & "() {" 105 lines.add "void " & entryPoint & "() {"