Mercurial > games > semicongine
annotate src/vertex.nim @ 478:871ee602bf95
add: vertex basics, some refactoring
| author | Sam <sam@basx.dev> |
|---|---|
| date | Sun, 01 Jan 2023 01:00:50 +0700 |
| parents | d4750f2e0760 |
| children |
| rev | line source |
|---|---|
| 478 | 1 import std/macros |
| 2 import std/strutils | |
| 3 import std/strformat | |
| 4 import std/typetraits | |
| 5 | |
| 6 import ./math/vector | |
| 7 import ./vulkan | |
| 8 | |
|
474
d4750f2e0760
add: vector/matrix modules, tests, nim config script
Sam <sam@basx.dev>
parents:
diff
changeset
|
9 type |
| 478 | 10 VertexAttributeType = SomeNumber|Vec |
| 11 VertexAttribute*[T:VertexAttributeType] = object | |
| 12 | |
| 13 | |
| 14 # from https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap15.html | |
| 15 func nLocationSlots[T: VertexAttributeType](): int = | |
| 16 when (T is Vec3[float64] or T is Vec3[uint64] or T is Vec4[float64] or T is Vec4[float64]): | |
| 17 2 | |
| 18 else: | |
| 19 1 | |
| 20 | |
| 21 # numbers | |
| 22 func getVkFormat[T: VertexAttributeType](): VkFormat = | |
| 23 when T is uint8: VK_FORMAT_R8_UINT | |
| 24 elif T is int8: VK_FORMAT_R8_SINT | |
| 25 elif T is uint16: VK_FORMAT_R16_UINT | |
| 26 elif T is int16: VK_FORMAT_R16_SINT | |
| 27 elif T is uint32: VK_FORMAT_R32_UINT | |
| 28 elif T is int32: VK_FORMAT_R32_SINT | |
| 29 elif T is uint64: VK_FORMAT_R64_UINT | |
| 30 elif T is int64: VK_FORMAT_R64_SINT | |
| 31 elif T is float32: VK_FORMAT_R32_SFLOAT | |
| 32 elif T is float64: VK_FORMAT_R64_SFLOAT | |
| 33 elif T is Vec2[uint8]: VK_FORMAT_R8G8_UINT | |
| 34 elif T is Vec2[int8]: VK_FORMAT_R8G8_SINT | |
| 35 elif T is Vec2[uint16]: VK_FORMAT_R16G16_UINT | |
| 36 elif T is Vec2[int16]: VK_FORMAT_R16G16_SINT | |
| 37 elif T is Vec2[uint32]: VK_FORMAT_R32G32_UINT | |
| 38 elif T is Vec2[int32]: VK_FORMAT_R32G32_SINT | |
| 39 elif T is Vec2[uint64]: VK_FORMAT_R64G64_UINT | |
| 40 elif T is Vec2[int64]: VK_FORMAT_R64G64_SINT | |
| 41 elif T is Vec2[float32]: VK_FORMAT_R32G32_SFLOAT | |
| 42 elif T is Vec2[float64]: VK_FORMAT_R64G64_SFLOAT | |
| 43 elif T is Vec3[uint8]: VK_FORMAT_R8G8B8_UINT | |
| 44 elif T is Vec3[int8]: VK_FORMAT_R8G8B8_SINT | |
| 45 elif T is Vec3[uint16]: VK_FORMAT_R16G16B16_UINT | |
| 46 elif T is Vec3[int16]: VK_FORMAT_R16G16B16_SINT | |
| 47 elif T is Vec3[uint32]: VK_FORMAT_R32G32B32_UINT | |
| 48 elif T is Vec3[int32]: VK_FORMAT_R32G32B32_SINT | |
| 49 elif T is Vec3[uint64]: VK_FORMAT_R64G64B64_UINT | |
| 50 elif T is Vec3[int64]: VK_FORMAT_R64G64B64_SINT | |
| 51 elif T is Vec3[float32]: VK_FORMAT_R32G32B32_SFLOAT | |
| 52 elif T is Vec3[float64]: VK_FORMAT_R64G64B64_SFLOAT | |
| 53 elif T is Vec4[uint8]: VK_FORMAT_R8G8B8A8_UINT | |
| 54 elif T is Vec4[int8]: VK_FORMAT_R8G8B8A8_SINT | |
| 55 elif T is Vec4[uint16]: VK_FORMAT_R16G16B16A16_UINT | |
| 56 elif T is Vec4[int16]: VK_FORMAT_R16G16B16A16_SINT | |
| 57 elif T is Vec4[uint32]: VK_FORMAT_R32G32B32A32_UINT | |
| 58 elif T is Vec4[int32]: VK_FORMAT_R32G32B32A32_SINT | |
| 59 elif T is Vec4[uint64]: VK_FORMAT_R64G64B64A64_UINT | |
| 60 elif T is Vec4[int64]: VK_FORMAT_R64G64B64A64_SINT | |
| 61 elif T is Vec4[float32]: VK_FORMAT_R32G32B32A32_SFLOAT | |
| 62 elif T is Vec4[float64]: VK_FORMAT_R64G64B64A64_SFLOAT | |
| 63 | |
| 64 func getGLSLType[T: VertexAttributeType](): string = | |
| 65 # todo: likely not correct as we would need to enable some | |
| 66 # extensions somewhere (Vulkan/GLSL compiler?) to have | |
| 67 # everything work as intended. Or maybe the GPU driver does | |
| 68 # some automagic conversion stuf.. | |
| 69 when T is uint8: "uint" | |
| 70 elif T is int8: "int" | |
| 71 elif T is uint16: "uint" | |
| 72 elif T is int16: "int" | |
| 73 elif T is uint32: "uint" | |
| 74 elif T is int32: "int" | |
| 75 elif T is uint64: "uint" | |
| 76 elif T is int64: "int" | |
| 77 elif T is float32: "float" | |
| 78 elif T is float64: "double" | |
| 79 | |
| 80 elif T is Vec2[uint8]: "uvec2" | |
| 81 elif T is Vec2[int8]: "ivec2" | |
| 82 elif T is Vec2[uint16]: "uvec2" | |
| 83 elif T is Vec2[int16]: "ivec2" | |
| 84 elif T is Vec2[uint32]: "uvec2" | |
| 85 elif T is Vec2[int32]: "ivec2" | |
| 86 elif T is Vec2[uint64]: "uvec2" | |
| 87 elif T is Vec2[int64]: "ivec2" | |
| 88 elif T is Vec2[float32]: "vec2" | |
| 89 elif T is Vec2[float64]: "dvec2" | |
|
474
d4750f2e0760
add: vector/matrix modules, tests, nim config script
Sam <sam@basx.dev>
parents:
diff
changeset
|
90 |
| 478 | 91 elif T is Vec3[uint8]: "uvec3" |
| 92 elif T is Vec3[int8]: "ivec3" | |
| 93 elif T is Vec3[uint16]: "uvec3" | |
| 94 elif T is Vec3[int16]: "ivec3" | |
| 95 elif T is Vec3[uint32]: "uvec3" | |
| 96 elif T is Vec3[int32]: "ivec3" | |
| 97 elif T is Vec3[uint64]: "uvec3" | |
| 98 elif T is Vec3[int64]: "ivec3" | |
| 99 elif T is Vec3[float32]: "vec3" | |
| 100 elif T is Vec3[float64]: "dvec3" | |
| 101 | |
| 102 elif T is Vec4[uint8]: "uvec4" | |
| 103 elif T is Vec4[int8]: "ivec4" | |
| 104 elif T is Vec4[uint16]: "uvec4" | |
| 105 elif T is Vec4[int16]: "ivec4" | |
| 106 elif T is Vec4[uint32]: "uvec4" | |
| 107 elif T is Vec4[int32]: "ivec4" | |
| 108 elif T is Vec4[uint64]: "uvec4" | |
| 109 elif T is Vec4[int64]: "ivec4" | |
| 110 elif T is Vec4[float32]: "vec4" | |
| 111 elif T is Vec4[float64]: "dvec4" | |
| 112 | |
| 113 template rawAttributeType(v: VertexAttribute): auto = get(genericParams(typeof(v)), 0) | |
| 114 | |
| 115 func generateGLSL[T](): string = | |
| 116 var stmtList: seq[string] | |
| 117 var i = 0 | |
| 118 for name, value in T().fieldPairs: | |
| 119 when typeof(value) is VertexAttribute: | |
| 120 let glsltype = getGLSLType[rawAttributeType(value)]() | |
| 121 let n = name | |
| 122 stmtList.add(&"layout(location = {i}) in {glsltype} {n};") | |
| 123 i += nLocationSlots[rawAttributeType(value)]() | |
| 124 | |
| 125 return stmtList.join("\n") | |
|
474
d4750f2e0760
add: vector/matrix modules, tests, nim config script
Sam <sam@basx.dev>
parents:
diff
changeset
|
126 |
| 478 | 127 func generateInputVertexBinding*[T](bindingoffset: int = 0, locationoffset: int = 0): seq[VkVertexInputBindingDescription] = |
| 128 # packed attribute data, not interleaved (aks "struct of arrays") | |
| 129 var binding = bindingoffset | |
| 130 for name, value in T().fieldPairs: | |
| 131 when typeof(value) is VertexAttribute: | |
| 132 result.add( | |
| 133 VkVertexInputBindingDescription( | |
| 134 binding: uint32(binding), | |
| 135 stride: uint32(sizeof(rawAttributeType(value))), | |
| 136 inputRate: VK_VERTEX_INPUT_RATE_VERTEX, # VK_VERTEX_INPUT_RATE_INSTANCE for instances | |
| 137 ) | |
| 138 ) | |
| 139 binding += 1 | |
| 140 | |
| 141 func generateInputAttributeBinding*[T](bindingoffset: int = 0, locationoffset: int = 0): seq[VkVertexInputAttributeDescription] = | |
| 142 # packed attribute data, not interleaved (aks "struct of arrays") | |
| 143 var location = 0 | |
| 144 var binding = bindingoffset | |
| 145 for name, value in T().fieldPairs: | |
| 146 when typeof(value) is VertexAttribute: | |
| 147 result.add( | |
| 148 VkVertexInputAttributeDescription( | |
| 149 binding: uint32(binding), | |
| 150 location: uint32(location), | |
| 151 format: getVkFormat[rawAttributeType(value)](), | |
| 152 offset: 0, | |
| 153 ) | |
| 154 ) | |
| 155 location += nLocationSlots[rawAttributeType(value)]() | |
| 156 binding += 1 | |
| 157 | |
| 158 func getBindingDescription(binding: int): auto = | |
| 159 VkVertexInputBindingDescription( | |
| 160 binding: uint32(binding), | |
| 161 stride: 0, # either sizeof of vertex (array of structs) or of attribute (struct of arrays) | |
| 162 inputRate: VK_VERTEX_INPUT_RATE_VERTEX, # VK_VERTEX_INPUT_RATE_INSTANCE for instances | |
| 163 ) | |
| 164 | |
| 165 func getAttributeDescriptions(binding: int): auto = | |
| 166 [ | |
| 167 VkVertexInputAttributeDescription( | |
| 168 binding: 0'u32, | |
| 169 location: 0, | |
| 170 format: VK_FORMAT_R32G32_SFLOAT, | |
| 171 offset: 0, | |
| 172 ), | |
| 173 VkVertexInputAttributeDescription( | |
| 174 binding: 0'u32, | |
| 175 location: 1, | |
| 176 format: VK_FORMAT_R32G32B32_SFLOAT, | |
| 177 offset: uint32(sizeof(Vec2)), # use offsetOf? | |
| 178 ), | |
| 179 ] |
