Mercurial > games > semicongine
comparison static_utils.nim @ 1181:6b66e6c837bc compiletime-tests
sync to notebook in bedroom
author | sam <sam@basx.dev> |
---|---|
date | Tue, 02 Jul 2024 17:50:14 +0700 |
parents | d554f8185815 |
children | e9a212e9cdf7 |
comparison
equal
deleted
inserted
replaced
1180:d554f8185815 | 1181:6b66e6c837bc |
---|---|
19 template PassFlat {.pragma.} | 19 template PassFlat {.pragma.} |
20 template ShaderOutput {.pragma.} | 20 template ShaderOutput {.pragma.} |
21 template VertexIndices {.pragma.} | 21 template VertexIndices {.pragma.} |
22 template DescriptorSet {.pragma.} | 22 template DescriptorSet {.pragma.} |
23 | 23 |
24 const INFLIGHTFRAMES = 2'u32 | |
25 const MAX_DESCRIPTORSETS = 2 | |
26 const MEMORY_ALIGNMENT = 65536'u64 # Align buffers inside memory along this alignment | |
27 const BUFFER_ALIGNMENT = 64'u64 # align offsets inside buffers along this alignment | |
28 | |
29 # some globals that will (likely?) never change during the life time of the engine | 24 # some globals that will (likely?) never change during the life time of the engine |
30 type | 25 type |
26 DescriptorSetType = enum | |
27 GlobalSet | |
28 MaterialSet | |
31 VulkanGlobals = object | 29 VulkanGlobals = object |
32 instance: VkInstance | 30 instance: VkInstance |
33 device: VkDevice | 31 device: VkDevice |
34 physicalDevice: VkPhysicalDevice | 32 physicalDevice: VkPhysicalDevice |
35 queueFamilyIndex: uint32 | 33 queueFamilyIndex: uint32 |
36 queue: VkQueue | 34 queue: VkQueue |
35 | |
36 const INFLIGHTFRAMES = 2'u32 | |
37 const MAX_DESCRIPTORSETS = tt.enumLen(DescriptorSetType) | |
38 const MEMORY_ALIGNMENT = 65536'u64 # Align buffers inside memory along this alignment | |
39 const BUFFER_ALIGNMENT = 64'u64 # align offsets inside buffers along this alignment | |
40 | |
37 var vulkan: VulkanGlobals | 41 var vulkan: VulkanGlobals |
38 | 42 |
39 type | 43 type |
40 SupportedGPUType = float32 | float64 | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | TVec2[int32] | TVec2[int64] | TVec3[int32] | TVec3[int64] | TVec4[int32] | TVec4[int64] | TVec2[uint32] | TVec2[uint64] | TVec3[uint32] | TVec3[uint64] | TVec4[uint32] | TVec4[uint64] | TVec2[float32] | TVec2[float64] | TVec3[float32] | TVec3[float64] | TVec4[float32] | TVec4[float64] | TMat2[float32] | TMat2[float64] | TMat23[float32] | TMat23[float64] | TMat32[float32] | TMat32[float64] | TMat3[float32] | TMat3[float64] | TMat34[float32] | TMat34[float64] | TMat43[float32] | TMat43[float64] | TMat4[float32] | TMat4[float64] | 44 SupportedGPUType = float32 | float64 | int8 | int16 | int32 | int64 | uint8 | uint16 | uint32 | uint64 | TVec2[int32] | TVec2[int64] | TVec3[int32] | TVec3[int64] | TVec4[int32] | TVec4[int64] | TVec2[uint32] | TVec2[uint64] | TVec3[uint32] | TVec3[uint64] | TVec4[uint32] | TVec4[uint64] | TVec2[float32] | TVec2[float64] | TVec3[float32] | TVec3[float64] | TVec4[float32] | TVec4[float64] | TMat2[float32] | TMat2[float64] | TMat23[float32] | TMat23[float64] | TMat32[float32] | TMat32[float64] | TMat3[float32] | TMat3[float64] | TMat34[float32] | TMat34[float64] | TMat43[float32] | TMat43[float64] | TMat4[float32] | TMat4[float64] |
41 ShaderObject[TShader] = object | 45 ShaderObject[TShader] = object |
146 let `valuename` {.inject.} = value | 150 let `valuename` {.inject.} = value |
147 const `isinstancename` {.inject.} = hasCustomPragma(value, InstanceAttribute) | 151 const `isinstancename` {.inject.} = hasCustomPragma(value, InstanceAttribute) |
148 body | 152 body |
149 | 153 |
150 template ForDescriptorSets(shader: typed, setNumber, descriptorSet, body: untyped): untyped = | 154 template ForDescriptorSets(shader: typed, setNumber, descriptorSet, body: untyped): untyped = |
151 var n = 0 | 155 var n = DescriptorSetType.low |
152 for theFieldname, value in fieldPairs(shader): | 156 for theFieldname, value in fieldPairs(shader): |
153 when value.hasCustomPragma(DescriptorSet): | 157 when value.hasCustomPragma(DescriptorSet): |
154 block: | 158 block: |
155 let `setNumber` {.inject.} = n | 159 let `setNumber` {.inject.} = n |
156 let `descriptorSet` {.inject.} = value | 160 let `descriptorSet` {.inject.} = value |
157 body | 161 body |
158 n.inc | 162 if n < DescriptorSetType.high: |
163 n.inc | |
159 | 164 |
160 template ForDescriptorFields(shader: typed, fieldname, typename, countname, bindingNumber, body: untyped): untyped = | 165 template ForDescriptorFields(shader: typed, fieldname, typename, countname, bindingNumber, body: untyped): untyped = |
161 var `bindingNumber` {.inject.} = 1'u32 | 166 var `bindingNumber` {.inject.} = 1'u32 |
162 for theFieldname, value in fieldPairs(shader): | 167 for theFieldname, value in fieldPairs(shader): |
163 when typeof(value) is Texture: | 168 when typeof(value) is Texture: |
464 proc UpdateAllGPUBuffers[T](value: T) = | 469 proc UpdateAllGPUBuffers[T](value: T) = |
465 for name, fieldvalue in value.fieldPairs(): | 470 for name, fieldvalue in value.fieldPairs(): |
466 when typeof(fieldvalue) is GPUData: | 471 when typeof(fieldvalue) is GPUData: |
467 UpdateGPUBuffer(fieldvalue) | 472 UpdateGPUBuffer(fieldvalue) |
468 | 473 |
469 proc AssertCompatible(TShader, TDescriptorSet: typedesc, DescriptorSetIndex: static int) = | 474 proc AssertCompatible(TShader, TDescriptorSet: typedesc, descriptorSetType: static DescriptorSetType) = |
470 ForDescriptorSets(default(TShader), setNumber, descriptorSet): | 475 ForDescriptorSets(default(TShader), setNumber, descriptorSet): |
471 if setNumber == DescriptorSetIndex: | 476 if setNumber == descriptorSetType: |
472 assert typeof(descriptorSet) is TDescriptorSet | 477 assert typeof(descriptorSet) is TDescriptorSet |
473 | 478 |
474 proc CreateDescriptorSet[T, TShader]( | 479 proc CreateDescriptorSet[T, TShader]( |
475 renderData: RenderData, | 480 renderData: RenderData, |
476 pipeline: Pipeline[TShader], | 481 pipeline: Pipeline[TShader], |
477 value: T, | 482 value: T, |
478 setNumber: static int | 483 descriptorSetType: static DescriptorSetType |
479 ): array[INFLIGHTFRAMES.int, VkDescriptorSet] = | 484 ): array[INFLIGHTFRAMES.int, VkDescriptorSet] = |
480 | 485 |
481 static: AssertCompatible(TShader, T, setNumber) | 486 static: AssertCompatible(TShader, T, descriptorSetType) |
482 | 487 |
483 var layouts = newSeqWith(result.len, pipeline.descriptorSetLayouts[setNumber]) | 488 var layouts = newSeqWith(result.len, pipeline.descriptorSetLayouts[descriptorSetType.int]) |
484 var allocInfo = VkDescriptorSetAllocateInfo( | 489 var allocInfo = VkDescriptorSetAllocateInfo( |
485 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, | 490 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, |
486 descriptorPool: renderData.descriptorPool, | 491 descriptorPool: renderData.descriptorPool, |
487 descriptorSetCount: uint32(layouts.len), | 492 descriptorSetCount: uint32(layouts.len), |
488 pSetLayouts: layouts.ToCPointer, | 493 pSetLayouts: layouts.ToCPointer, |
733 ) | 738 ) |
734 checkVkResult vkCreateDescriptorSetLayout( | 739 checkVkResult vkCreateDescriptorSetLayout( |
735 vulkan.device, | 740 vulkan.device, |
736 addr(layoutCreateInfo), | 741 addr(layoutCreateInfo), |
737 nil, | 742 nil, |
738 addr(result.descriptorSetLayouts[setNumber]) | 743 addr(result.descriptorSetLayouts[setNumber.int]) |
739 ) | 744 ) |
740 let pipelineLayoutInfo = VkPipelineLayoutCreateInfo( | 745 let pipelineLayoutInfo = VkPipelineLayoutCreateInfo( |
741 sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, | 746 sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, |
742 setLayoutCount: result.descriptorSetLayouts.len.uint32, | 747 setLayoutCount: result.descriptorSetLayouts.len.uint32, |
743 pSetLayouts: result.descriptorSetLayouts.ToCPointer, | 748 pSetLayouts: result.descriptorSetLayouts.ToCPointer, |
1042 maxSets: descriptorPoolLimit, | 1047 maxSets: descriptorPoolLimit, |
1043 ) | 1048 ) |
1044 checkVkResult vkCreateDescriptorPool(vulkan.device, addr(poolInfo), nil, addr(result.descriptorPool)) | 1049 checkVkResult vkCreateDescriptorPool(vulkan.device, addr(poolInfo), nil, addr(result.descriptorPool)) |
1045 | 1050 |
1046 # allocate some memory | 1051 # allocate some memory |
1047 var initialAllocationSize = 1_000_000_000'u64 # TODO: make this more dynamic or something | 1052 var initialAllocationSize = 1_000_000_000'u64 # TODO: make this more dynamic or something? |
1048 result.indirectMemory = @[(memory: AllocateIndirectMemory(size = initialAllocationSize), usedOffset: 0'u64)] | 1053 result.indirectMemory = @[(memory: AllocateIndirectMemory(size = initialAllocationSize), usedOffset: 0'u64)] |
1049 result.directMemory = @[(memory: AllocateDirectMemory(size = initialAllocationSize), usedOffset: 0'u64)] | 1054 result.directMemory = @[(memory: AllocateDirectMemory(size = initialAllocationSize), usedOffset: 0'u64)] |
1050 | 1055 |
1051 proc FlushDirectMemory(renderData: RenderData) = | 1056 proc FlushDirectMemory(renderData: RenderData) = |
1052 var flushRegions = newSeqOfCap[VkMappedMemoryRange](renderData.directMemory.len) | 1057 var flushRegions = newSeqOfCap[VkMappedMemoryRange](renderData.directMemory.len) |
1213 nil, | 1218 nil, |
1214 ) | 1219 ) |
1215 ]# | 1220 ]# |
1216 | 1221 |
1217 proc AssertCompatible(TShader, TMesh, TInstance, TUniforms, TGlobals: typedesc) = | 1222 proc AssertCompatible(TShader, TMesh, TInstance, TUniforms, TGlobals: typedesc) = |
1218 # TODO: overhaul this | 1223 var descriptorSetCount = 0 |
1224 | |
1219 for inputName, inputValue in default(TShader).fieldPairs: | 1225 for inputName, inputValue in default(TShader).fieldPairs: |
1220 var foundField = false | 1226 var foundField = false |
1221 | 1227 |
1222 # Vertex input data | 1228 # Vertex input data |
1223 when hasCustomPragma(inputValue, VertexAttribute): | 1229 when hasCustomPragma(inputValue, VertexAttribute): |
1239 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" | 1245 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" |
1240 assert elementType(instanceValue.data) is typeof(inputValue), "Shader input " & tt.name(TShader) & "." & inputName & " is of type '" & tt.name(typeof(inputValue)) & "' but instance attribute is of type '" & tt.name(elementType(instanceValue.data)) & "'" | 1246 assert elementType(instanceValue.data) is typeof(inputValue), "Shader input " & tt.name(TShader) & "." & inputName & " is of type '" & tt.name(typeof(inputValue)) & "' but instance attribute is of type '" & tt.name(elementType(instanceValue.data)) & "'" |
1241 foundField = true | 1247 foundField = true |
1242 assert foundField, "Shader input '" & tt.name(TShader) & "." & inputName & ": " & tt.name(typeof(inputValue)) & "' not found in '" & tt.name(TInstance) & "'" | 1248 assert foundField, "Shader input '" & tt.name(TShader) & "." & inputName & ": " & tt.name(typeof(inputValue)) & "' not found in '" & tt.name(TInstance) & "'" |
1243 | 1249 |
1250 | |
1251 elif hasCustomPragma(inputValue, DescriptorSet): | |
1252 assert descriptorSetCount < MAX_DESCRIPTORSETS, &"{tt.name(TShader)}: maximum {MAX_DESCRIPTORSETS} allowed" | |
1253 descriptorSetCount.inc | |
1254 echo "DescriptorSet: ", inputName | |
1255 | |
1256 for descriptorName, descriptorValue in inputValue.fieldPairs(): | |
1257 when typeof(descriptorValue) is Texture: | |
1258 echo " Texture: ", descriptorName | |
1259 elif typeof(descriptorValue) is GPUValue: | |
1260 echo " Uniform block: ", descriptorName | |
1261 | |
1262 #[ | |
1244 # Texture | 1263 # Texture |
1245 elif typeof(inputValue) is Texture: | 1264 elif typeof(inputValue) is Texture: |
1246 for uniformName, uniformValue in default(TUniforms).fieldPairs: | 1265 for uniformName, uniformValue in default(TUniforms).fieldPairs: |
1247 when uniformName == inputName: | 1266 when uniformName == inputName: |
1248 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" | 1267 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" |
1301 assert globalValue is GPUValue, "global attribute '" & globalName & "' must be of type 'GPUValue' but is of type " & tt.name(typeof(globalValue)) | 1320 assert globalValue is GPUValue, "global attribute '" & globalName & "' must be of type 'GPUValue' but is of type " & tt.name(typeof(globalValue)) |
1302 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" | 1321 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" |
1303 assert typeof(globalValue.data) is typeof(inputValue), "Shader input " & tt.name(TShader) & "." & inputName & " is of type '" & tt.name(typeof(inputValue)) & "' but global attribute is of type '" & tt.name(typeof(globalValue.data)) & "'" | 1322 assert typeof(globalValue.data) is typeof(inputValue), "Shader input " & tt.name(TShader) & "." & inputName & " is of type '" & tt.name(typeof(inputValue)) & "' but global attribute is of type '" & tt.name(typeof(globalValue.data)) & "'" |
1304 foundField = true | 1323 foundField = true |
1305 assert foundField, "Shader input '" & tt.name(TShader) & "." & inputName & ": " & tt.name(typeof(inputValue)) & "' not found in '" & tt.name(TMesh) & "|" & tt.name(TGlobals) & "'" | 1324 assert foundField, "Shader input '" & tt.name(TShader) & "." & inputName & ": " & tt.name(typeof(inputValue)) & "' not found in '" & tt.name(TMesh) & "|" & tt.name(TGlobals) & "'" |
1325 ]# | |
1326 | |
1327 | |
1328 | |
1329 | |
1306 | 1330 |
1307 | 1331 |
1308 proc Render[TShader, TUniforms, TGlobals, TMesh, TInstance]( | 1332 proc Render[TShader, TUniforms, TGlobals, TMesh, TInstance]( |
1309 commandBuffer: VkCommandBuffer, | 1333 commandBuffer: VkCommandBuffer, |
1310 pipeline: Pipeline[TShader], | 1334 pipeline: Pipeline[TShader], |
1311 uniforms: TUniforms, | 1335 uniforms: TUniforms, |
1312 globals: TGlobals, | 1336 globals: TGlobals, |
1313 mesh: TMesh, | 1337 mesh: TMesh, |
1314 instances: TInstance, | 1338 instances: TInstance, |
1315 ) = | 1339 ) = |
1316 discard | 1340 static: AssertCompatible(TShader, TMesh, TInstance, TUniforms, TGlobals) |
1317 # static: AssertCompatible(TShader, TMesh, TInstance, TUniforms, TGlobals) | |
1318 #[ | 1341 #[ |
1319 if renderable.vertexBuffers.len > 0: | 1342 if renderable.vertexBuffers.len > 0: |
1320 commandBuffer.vkCmdBindVertexBuffers( | 1343 commandBuffer.vkCmdBindVertexBuffers( |
1321 firstBinding = 0'u32, | 1344 firstBinding = 0'u32, |
1322 bindingCount = uint32(renderable.vertexBuffers.len), | 1345 bindingCount = uint32(renderable.vertexBuffers.len), |
1517 UpdateAllGPUBuffers(instances1) | 1540 UpdateAllGPUBuffers(instances1) |
1518 UpdateAllGPUBuffers(uniforms1) | 1541 UpdateAllGPUBuffers(uniforms1) |
1519 UpdateAllGPUBuffers(myGlobals) | 1542 UpdateAllGPUBuffers(myGlobals) |
1520 renderdata.FlushDirectMemory() | 1543 renderdata.FlushDirectMemory() |
1521 | 1544 |
1522 var s1 = CreateDescriptorSet(renderdata, pipeline1, myGlobals, 0) | |
1523 var s2 = CreateDescriptorSet(renderdata, pipeline1, uniforms1, 1) | |
1524 | 1545 |
1525 # descriptors | 1546 # descriptors |
1547 # TODO: I think we can write and assign descriptors directly after creation | |
1548 var s1 = CreateDescriptorSet(renderdata, pipeline1, myGlobals, GlobalSet) | |
1549 var s2 = CreateDescriptorSet(renderdata, pipeline1, uniforms1, MaterialSet) | |
1526 # WriteDescriptors[ShaderA, UniformsA, GlobalsA](renderdata, uniforms1, myGlobals) | 1550 # WriteDescriptors[ShaderA, UniformsA, GlobalsA](renderdata, uniforms1, myGlobals) |
1527 | |
1528 # create descriptor sets | |
1529 #[ | |
1530 var descriptorSets: array[INFLIGHTFRAMES.int, VkDescriptorSet] | |
1531 var layouts = newSeqWith(descriptorSets.len, pipeline.descriptorSetLayouts) | |
1532 var allocInfo = VkDescriptorSetAllocateInfo( | |
1533 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, | |
1534 descriptorPool: pool, | |
1535 descriptorSetCount: uint32(layouts.len), | |
1536 pSetLayouts: layouts.ToCPointer, | |
1537 ) | |
1538 checkVkResult vkAllocateDescriptorSets(device, addr(allocInfo), descriptorSets.ToCPointer) | |
1539 ]# | |
1540 | 1551 |
1541 | 1552 |
1542 | 1553 |
1543 # command buffer | 1554 # command buffer |
1544 var | 1555 var |