Mercurial > games > semicongine
comparison src/zamikongine/shader.nim @ 24:71bbe11d8de8
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 | b45a5d338cd0 |
| children | 8f290112718a |
comparison
equal
deleted
inserted
replaced
| 23:0ffdf1f4ecf4 | 24:71bbe11d8de8 |
|---|---|
| 1 import std/osproc | 1 import std/tempfiles |
| 2 import std/strformat | 2 import std/strformat |
| 3 import std/strutils | 3 import std/strutils |
| 4 import std/tables | 4 import std/tables |
| 5 import std/compilesettings | |
| 6 | |
| 5 | 7 |
| 6 import ./vulkan_helpers | 8 import ./vulkan_helpers |
| 7 import ./vulkan | 9 import ./vulkan |
| 8 import ./vertex | 10 import ./vertex |
| 9 | 11 |
| 11 ShaderProgram* = object | 13 ShaderProgram* = object |
| 12 entryPoint*: string | 14 entryPoint*: string |
| 13 programType*: VkShaderStageFlagBits | 15 programType*: VkShaderStageFlagBits |
| 14 shader*: VkPipelineShaderStageCreateInfo | 16 shader*: VkPipelineShaderStageCreateInfo |
| 15 | 17 |
| 16 func stage2string(stage: VkShaderStageFlagBits): string = | 18 func stage2string(stage: VkShaderStageFlagBits): string {.compileTime.} = |
| 17 case stage | 19 case stage |
| 18 of VK_SHADER_STAGE_VERTEX_BIT: "vert" | 20 of VK_SHADER_STAGE_VERTEX_BIT: "vert" |
| 19 of VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: "tesc" | 21 of VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT: "tesc" |
| 20 of VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: "tese" | 22 of VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT: "tese" |
| 21 of VK_SHADER_STAGE_GEOMETRY_BIT: "geom" | 23 of VK_SHADER_STAGE_GEOMETRY_BIT: "geom" |
| 22 of VK_SHADER_STAGE_FRAGMENT_BIT: "frag" | 24 of VK_SHADER_STAGE_FRAGMENT_BIT: "frag" |
| 23 of VK_SHADER_STAGE_ALL_GRAPHICS: "" | 25 of VK_SHADER_STAGE_ALL_GRAPHICS: "" |
| 24 of VK_SHADER_STAGE_COMPUTE_BIT: "comp" | 26 of VK_SHADER_STAGE_COMPUTE_BIT: "comp" |
| 25 of VK_SHADER_STAGE_ALL: "" | 27 of VK_SHADER_STAGE_ALL: "" |
| 26 | 28 |
| 27 proc compileGLSLToSPIRV(stage: VkShaderStageFlagBits, shaderSource: string, entrypoint: string): seq[uint32] = | 29 proc compileGLSLToSPIRV(stage: VkShaderStageFlagBits, shaderSource: string, entrypoint: string): seq[uint32] {.compileTime.} = |
| 28 let stagename = stage2string(stage) | 30 let stagename = stage2string(stage) |
| 29 let (output, exitCode) = execCmdEx(command=fmt"./glslangValidator --entry-point {entrypoint} -V --stdin -S {stagename}", input=shaderSource) | 31 let (tmpfile, tmpfilename) = createTempFile("shader", stage2string(stage)) |
| 32 tmpfile.close() | |
| 33 let (output, exitCode) = gorgeEx(command=fmt"{querySetting(projectPath)}/glslangValidator --entry-point {entrypoint} -V --stdin -S {stagename} -o {tmpfilename}", input=shaderSource) | |
| 30 if exitCode != 0: | 34 if exitCode != 0: |
| 31 raise newException(Exception, output) | 35 raise newException(Exception, output) |
| 32 let shaderbinary = readFile fmt"{stagename}.spv" | 36 let shaderbinary = staticRead tmpfilename |
| 33 var i = 0 | 37 var i = 0 |
| 34 while i < shaderbinary.len: | 38 while i < shaderbinary.len: |
| 35 result.add( | 39 result.add( |
| 36 (uint32(shaderbinary[i + 0]) shl 0) or | 40 (uint32(shaderbinary[i + 0]) shl 0) or |
| 37 (uint32(shaderbinary[i + 1]) shl 8) or | 41 (uint32(shaderbinary[i + 1]) shl 8) or |
| 38 (uint32(shaderbinary[i + 2]) shl 16) or | 42 (uint32(shaderbinary[i + 2]) shl 16) or |
| 39 (uint32(shaderbinary[i + 3]) shl 24) | 43 (uint32(shaderbinary[i + 3]) shl 24) |
| 40 ) | 44 ) |
| 41 i += 4 | 45 i += 4 |
| 42 | 46 |
| 43 proc initShaderProgram*(device: VkDevice, programType: VkShaderStageFlagBits, shader: string, entryPoint: string="main"): ShaderProgram = | 47 proc initShaderProgram*(device: VkDevice, programType: static VkShaderStageFlagBits, shader: static string, entryPoint: static string="main"): ShaderProgram = |
| 44 result.entryPoint = entryPoint | 48 result.entryPoint = entryPoint |
| 45 result.programType = programType | 49 result.programType = programType |
| 46 | 50 |
| 47 var code = compileGLSLToSPIRV(result.programType, shader, result.entryPoint) | 51 const constcode = compileGLSLToSPIRV(programType, shader, entryPoint) |
| 52 var code = constcode | |
| 48 var createInfo = VkShaderModuleCreateInfo( | 53 var createInfo = VkShaderModuleCreateInfo( |
| 49 sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, | 54 sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, |
| 50 codeSize: uint(code.len * sizeof(uint32)), | 55 codeSize: uint(code.len * sizeof(uint32)), |
| 51 pCode: if code.len > 0: addr(code[0]) else: nil, | 56 pCode: if code.len > 0: addr(code[0]) else: nil, |
| 52 ) | 57 ) |
| 58 stage: programType, | 63 stage: programType, |
| 59 module: shaderModule, | 64 module: shaderModule, |
| 60 pName: cstring(result.entryPoint), # entry point for shader | 65 pName: cstring(result.entryPoint), # entry point for shader |
| 61 ) | 66 ) |
| 62 | 67 |
| 63 func generateVertexShaderCode*[T](entryPoint, positionAttrName, colorAttrName: static string): string = | 68 func generateVertexShaderCode*[T](entryPoint, positionAttrName, colorAttrName: static string): string {.compileTime.} = |
| 64 var lines: seq[string] | 69 var lines: seq[string] |
| 65 lines.add "#version 450" | 70 lines.add "#version 450" |
| 66 lines.add generateGLSLDeclarations[T]() | 71 lines.add generateGLSLDeclarations[T]() |
| 67 lines.add "layout(location = 0) out vec3 fragColor;" | 72 lines.add "layout(location = 0) out vec3 fragColor;" |
| 68 lines.add "void " & entryPoint & "() {" | 73 lines.add "void " & entryPoint & "() {" |
| 73 when typeof(value) is VertexAttribute and name == colorAttrName: | 78 when typeof(value) is VertexAttribute and name == colorAttrName: |
| 74 lines.add " fragColor = " & name & ";" | 79 lines.add " fragColor = " & name & ";" |
| 75 lines.add "}" | 80 lines.add "}" |
| 76 return lines.join("\n") | 81 return lines.join("\n") |
| 77 | 82 |
| 78 func generateFragmentShaderCode*[T](entryPoint: static string): string = | 83 func generateFragmentShaderCode*[T](entryPoint: static string): string {.compileTime.} = |
| 79 var lines: seq[string] | 84 var lines: seq[string] |
| 80 lines.add "#version 450" | 85 lines.add "#version 450" |
| 81 lines.add "layout(location = 0) in vec3 fragColor;" | 86 lines.add "layout(location = 0) in vec3 fragColor;" |
| 82 lines.add "layout(location = 0) out vec4 outColor;" | 87 lines.add "layout(location = 0) out vec4 outColor;" |
| 83 lines.add "void " & entryPoint & "() {" | 88 lines.add "void " & entryPoint & "() {" |
