Mercurial > games > semicongine
annotate src/semicongine/gpu_data.nim @ 120:2780d9aad142
add: better mesh support, indexed mesh
| author | Sam <sam@basx.dev> |
|---|---|
| date | Thu, 06 Apr 2023 00:30:56 +0700 |
| parents | 056e08dfad10 |
| children | dfaddaf96f09 |
| rev | line source |
|---|---|
|
114
056e08dfad10
yay: first triangle rendering with new engine implmentation
Sam <sam@basx.dev>
parents:
113
diff
changeset
|
1 import std/sequtils |
|
113
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
2 import std/typetraits |
| 111 | 3 import std/strformat |
| 4 import std/tables | |
| 5 | |
| 6 import ./vulkan/api | |
|
113
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
7 import ./math |
| 111 | 8 |
| 9 type | |
| 10 CountType = 1'u32 .. 4'u32 | |
| 11 DataType* = enum | |
| 12 Float32 | |
| 13 Float64 | |
| 14 Int8 | |
| 15 Int16 | |
| 16 Int32 | |
| 17 Int64 | |
| 18 UInt8 | |
| 19 UInt16 | |
| 20 UInt32 | |
| 21 UInt64 | |
| 120 | 22 MemoryLocation* = enum |
| 23 VRAM, VRAMVisible, RAM # VRAM is fastest, VRAMVisible allows updating memory directly, may be slower | |
| 111 | 24 Attribute* = object |
| 25 name*: string | |
| 26 thetype*: DataType | |
| 27 components*: CountType # how many components the vectors has (1 means scalar) | |
| 28 rows*: CountType # used to split matrices into rows of vectors | |
| 29 perInstance*: bool | |
| 120 | 30 memoryLocation*: MemoryLocation |
| 111 | 31 AttributeGroup* = object |
| 32 attributes*: seq[Attribute] | |
| 33 | |
|
114
056e08dfad10
yay: first triangle rendering with new engine implmentation
Sam <sam@basx.dev>
parents:
113
diff
changeset
|
34 func initAttributeGroup*(attrs: varargs[Attribute]): auto = |
|
056e08dfad10
yay: first triangle rendering with new engine implmentation
Sam <sam@basx.dev>
parents:
113
diff
changeset
|
35 AttributeGroup(attributes: attrs.toSeq) |
|
056e08dfad10
yay: first triangle rendering with new engine implmentation
Sam <sam@basx.dev>
parents:
113
diff
changeset
|
36 |
|
113
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
37 func vertexInputs*(group: AttributeGroup): seq[Attribute] = |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
38 for attr in group.attributes: |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
39 if attr.perInstance == false: |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
40 result.add attr |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
41 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
42 func instanceInputs*(group: AttributeGroup): seq[Attribute] = |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
43 for attr in group.attributes: |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
44 if attr.perInstance == false: |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
45 result.add attr |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
46 |
| 120 | 47 func attr*( |
| 48 name: string, | |
| 49 thetype: DataType, | |
| 50 components=CountType(1), | |
| 51 rows=CountType(1), | |
| 52 perInstance=false, | |
| 53 memoryLocation=VRAMVisible, | |
| 54 ): auto = | |
| 55 Attribute( | |
| 56 name: name, | |
| 57 thetype: thetype, | |
| 58 components: components, | |
| 59 rows: rows, | |
| 60 perInstance: perInstance, | |
| 61 memoryLocation: memoryLocation, | |
| 62 ) | |
| 111 | 63 |
| 64 func size*(thetype: DataType): uint32 = | |
| 65 case thetype: | |
| 66 of Float32: 4 | |
| 67 of Float64: 8 | |
| 68 of Int8: 1 | |
| 69 of Int16: 2 | |
| 70 of Int32: 4 | |
| 71 of Int64: 8 | |
| 72 of UInt8: 1 | |
| 73 of UInt16: 2 | |
| 74 of UInt32: 4 | |
| 75 of UInt64: 8 | |
| 76 | |
| 77 func size*(attribute: Attribute, perRow=false): uint32 = | |
| 78 if perRow: | |
| 79 attribute.thetype.size * attribute.components | |
| 80 else: | |
| 81 attribute.thetype.size * attribute.components * attribute.rows | |
| 82 | |
| 83 func size*(thetype: AttributeGroup): uint32 = | |
| 84 for attribute in thetype.attributes: | |
| 85 result += attribute.size | |
| 86 | |
|
113
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
87 func getDataType*[T: SomeNumber](value: T): DataType = |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
88 when T is float32: Float32 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
89 elif T is float64: Float64 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
90 elif T is int8: Int8 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
91 elif T is int16: Int16 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
92 elif T is int32: Int32 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
93 elif T is int64: Int64 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
94 elif T is uint8: UInt8 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
95 elif T is uint16: UInt16 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
96 elif T is uint32: UInt32 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
97 elif T is uint64: UInt64 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
98 elif T is int and sizeof(int) == sizeof(int64): Int64 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
99 elif T is int and sizeof(int) == sizeof(int32): Int32 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
100 elif T is uint and sizeof(uint) == sizeof(uint64): UInt64 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
101 elif T is uint and sizeof(uint) == sizeof(uint32): UInt32 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
102 elif T is float and sizeof(float) == sizeof(float32): Float32 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
103 elif T is float and sizeof(float) == sizeof(float64): Float64 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
104 else: |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
105 static: |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
106 raise newException(Exception, &"Unsupported data type for GPU data: {name(T)}" ) |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
107 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
108 func asAttribute*[T: SomeNumber|TMat|TVec](value: T, name: string): Attribute = |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
109 when not (T is SomeNumber): |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
110 let nonScalarDatatype = getDataType(default(get(genericParams(typeof(value)), 0))) |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
111 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
112 when T is SomeNumber: attr(name, getDataType(default(T))) |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
113 elif T is TMat22: attr(name, nonScalarDatatype, 2, 2) |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
114 elif T is TMat23: attr(name, nonScalarDatatype, 3, 2) |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
115 elif T is TMat32: attr(name, nonScalarDatatype, 3, 2) |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
116 elif T is TMat33: attr(name, nonScalarDatatype, 3, 3) |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
117 elif T is TMat34: attr(name, nonScalarDatatype, 4, 3) |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
118 elif T is TMat43: attr(name, nonScalarDatatype, 3, 4) |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
119 elif T is TMat44: attr(name, nonScalarDatatype, 4, 4) |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
120 elif T is TVec2: attr(name, nonScalarDatatype, 2) |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
121 elif T is TVec3: attr(name, nonScalarDatatype, 3) |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
122 elif T is TVec4: attr(name, nonScalarDatatype, 4) |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
123 else: {.error "Unsupported attribute type for GPU data".} |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
124 |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
125 func asAttribute*[T: SomeNumber|TMat|TVec](): Attribute = |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
126 asAttribute(default(T), name(T)) |
|
7b695fb335ed
did: first final implementation of scene-graph <-> pipeline connection, not working yet
Sam <sam@basx.dev>
parents:
112
diff
changeset
|
127 |
| 111 | 128 const TYPEMAP = { |
| 129 CountType(1): { | |
| 130 UInt8: VK_FORMAT_R8_UINT, | |
| 131 Int8: VK_FORMAT_R8_SINT, | |
| 132 UInt16: VK_FORMAT_R16_UINT, | |
| 133 Int16: VK_FORMAT_R16_SINT, | |
| 134 UInt32: VK_FORMAT_R32_UINT, | |
| 135 Int32: VK_FORMAT_R32_SINT, | |
| 136 UInt64: VK_FORMAT_R64_UINT, | |
| 137 Int64: VK_FORMAT_R64_SINT, | |
| 138 Float32: VK_FORMAT_R32_SFLOAT, | |
| 139 Float64: VK_FORMAT_R64_SFLOAT, | |
| 140 }.toTable, | |
| 141 CountType(2): { | |
| 142 UInt8: VK_FORMAT_R8G8_UINT, | |
| 143 Int8: VK_FORMAT_R8G8_SINT, | |
| 144 UInt16: VK_FORMAT_R16G16_UINT, | |
| 145 Int16: VK_FORMAT_R16G16_SINT, | |
| 146 UInt32: VK_FORMAT_R32G32_UINT, | |
| 147 Int32: VK_FORMAT_R32G32_SINT, | |
| 148 UInt64: VK_FORMAT_R64G64_UINT, | |
| 149 Int64: VK_FORMAT_R64G64_SINT, | |
| 150 Float32: VK_FORMAT_R32G32_SFLOAT, | |
| 151 Float64: VK_FORMAT_R64G64_SFLOAT, | |
| 152 }.toTable, | |
| 153 CountType(3): { | |
| 154 UInt8: VK_FORMAT_R8G8B8_UINT, | |
| 155 Int8: VK_FORMAT_R8G8B8_SINT, | |
| 156 UInt16: VK_FORMAT_R16G16B16_UINT, | |
| 157 Int16: VK_FORMAT_R16G16B16_SINT, | |
| 158 UInt32: VK_FORMAT_R32G32B32_UINT, | |
| 159 Int32: VK_FORMAT_R32G32B32_SINT, | |
| 160 UInt64: VK_FORMAT_R64G64B64_UINT, | |
| 161 Int64: VK_FORMAT_R64G64B64_SINT, | |
| 162 Float32: VK_FORMAT_R32G32B32_SFLOAT, | |
| 163 Float64: VK_FORMAT_R64G64B64_SFLOAT, | |
| 164 }.toTable, | |
| 165 CountType(4): { | |
| 166 UInt8: VK_FORMAT_R8G8B8A8_UINT, | |
| 167 Int8: VK_FORMAT_R8G8B8A8_SINT, | |
| 168 UInt16: VK_FORMAT_R16G16B16A16_UINT, | |
| 169 Int16: VK_FORMAT_R16G16B16A16_SINT, | |
| 170 UInt32: VK_FORMAT_R32G32B32A32_UINT, | |
| 171 Int32: VK_FORMAT_R32G32B32A32_SINT, | |
| 172 UInt64: VK_FORMAT_R64G64B64A64_UINT, | |
| 173 Int64: VK_FORMAT_R64G64B64A64_SINT, | |
| 174 Float32: VK_FORMAT_R32G32B32A32_SFLOAT, | |
| 175 Float64: VK_FORMAT_R64G64B64A64_SFLOAT, | |
| 176 }.toTable, | |
| 177 }.toTable | |
| 178 | |
| 179 func getVkFormat*(value: Attribute): VkFormat = | |
| 180 TYPEMAP[value.components][value.thetype] | |
| 181 | |
| 182 # from https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap15.html | |
| 183 func nLocationSlots*(attribute: Attribute): uint32 = | |
| 184 #[ | |
| 185 single location: | |
| 186 16-bit scalar and vector types, and | |
| 187 32-bit scalar and vector types, and | |
| 188 64-bit scalar and 2-component vector types. | |
| 189 two locations | |
| 190 64-bit three- and four-component vectors | |
| 191 ]# | |
| 192 case attribute.thetype: | |
| 193 of Float32: 1 | |
| 194 of Float64: (if attribute.components < 3: 1 else: 2) | |
| 195 of Int8: 1 | |
| 196 of Int16: 1 | |
| 197 of Int32: 1 | |
| 198 of Int64: (if attribute.components < 3: 1 else: 2) | |
| 199 of UInt8: 1 | |
| 200 of UInt16: 1 | |
| 201 of UInt32: 1 | |
| 202 of UInt64: (if attribute.components < 3: 1 else: 2) | |
| 203 | |
| 204 func glslType*(attribute: Attribute): string = | |
| 205 # todo: likely not correct as we would need to enable some | |
| 206 # extensions somewhere (Vulkan/GLSL compiler?) to have | |
| 207 # everything work as intended. Or maybe the GPU driver does | |
| 208 # some automagic conversion stuf.. | |
| 209 | |
| 210 # used to ensure square matrix get only one number for side instead of two, e.g. mat2 instead of mat22 | |
| 211 let matrixColumns = if attribute.components == attribute.rows: "" else: $attribute.components | |
| 212 case attribute.rows: | |
| 213 of 1: | |
| 214 case attribute.components: | |
| 215 of 1: # scalars | |
| 216 case attribute.thetype: | |
| 217 of Float32: "float" | |
| 218 of Float64: "double" | |
| 219 of Int8, Int16, Int32, Int64: "int" | |
| 220 of UInt8, UInt16, UInt32, UInt64: "uint" | |
| 221 else: # vectors | |
| 222 case attribute.thetype: | |
| 223 of Float32: &"vec{attribute.components}" | |
| 224 of Float64: &"dvec{attribute.components}" | |
| 225 of Int8, Int16, Int32, Int64: &"ivec{attribute.components}" | |
| 226 of UInt8, UInt16, UInt32, UInt64: &"uvec{attribute.components}" | |
| 227 else: | |
| 228 case attribute.components: | |
| 229 of 1: raise newException(Exception, &"Unsupported matrix-column-count: {attribute.components}") | |
| 230 else: | |
| 231 case attribute.thetype: | |
| 232 of Float32: &"mat{attribute.rows}{matrixColumns}" | |
| 233 of Float64: &"dmat{attribute.rows}{matrixColumns}" | |
| 234 else: raise newException(Exception, &"Unsupported matrix-component type: {attribute.thetype}") | |
| 235 | |
| 236 func glslInput*(group: AttributeGroup): seq[string] = | |
| 237 if group.attributes.len == 0: | |
| 238 return @[] | |
| 239 var i = 0'u32 | |
| 240 for attribute in group.attributes: | |
| 241 result.add &"layout(location = {i}) in {attribute.glslType} {attribute.name};" | |
| 242 for j in 0 ..< attribute.rows: | |
| 243 i += attribute.nLocationSlots | |
| 244 | |
| 245 func glslUniforms*(group: AttributeGroup, blockName="Uniforms", binding=0): seq[string] = | |
| 246 if group.attributes.len == 0: | |
| 247 return @[] | |
| 248 # currently only a single uniform block supported, therefore binding = 0 | |
| 249 result.add(&"layout(binding = {binding}) uniform T{blockName} {{") | |
| 250 for attribute in group.attributes: | |
| 251 result.add(&" {attribute.glslType} {attribute.name};") | |
| 252 result.add(&"}} {blockName};") | |
| 253 | |
| 254 func glslOutput*(group: AttributeGroup): seq[string] = | |
| 255 if group.attributes.len == 0: | |
| 256 return @[] | |
| 257 var i = 0'u32 | |
| 258 for attribute in group.attributes: | |
| 259 result.add &"layout(location = {i}) out {attribute.glslType} {attribute.name};" | |
| 260 i += 1 | |
| 120 | 261 |
| 262 func groupByMemoryLocation*(attributes: openArray[Attribute]): Table[MemoryLocation, seq[Attribute]] = | |
| 263 for attr in attributes: | |
| 264 if not (attr.memoryLocation in result): | |
| 265 result[attr.memoryLocation] = @[] | |
| 266 result[attr.memoryLocation].add attr |
