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 |