Mercurial > games > semicongine
comparison static_utils.nim @ 1176:511c9f7cd1da compiletime-tests
sync to notebook in bedroom
| author | sam <sam@basx.dev> |
|---|---|
| date | Sat, 29 Jun 2024 21:04:04 +0700 |
| parents | fafc2f14da0b |
| children | 4ef959278451 |
comparison
equal
deleted
inserted
replaced
| 1175:a94732d98cc6 | 1176:511c9f7cd1da |
|---|---|
| 19 template Pass* {.pragma.} | 19 template Pass* {.pragma.} |
| 20 template PassFlat* {.pragma.} | 20 template PassFlat* {.pragma.} |
| 21 template ShaderOutput* {.pragma.} | 21 template ShaderOutput* {.pragma.} |
| 22 | 22 |
| 23 const INFLIGHTFRAMES = 2'u32 | 23 const INFLIGHTFRAMES = 2'u32 |
| 24 | |
| 24 type | 25 type |
| 25 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] | 26 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] |
| 26 ShaderObject*[TShader] = object | 27 ShaderObject*[TShader] = object |
| 27 vertexShader: VkShaderModule | 28 vertexShader: VkShaderModule |
| 28 fragmentShader: VkShaderModule | 29 fragmentShader: VkShaderModule |
| 123 let `fieldname` {.inject.} = theFieldname | 124 let `fieldname` {.inject.} = theFieldname |
| 124 let `valuename` {.inject.} = value | 125 let `valuename` {.inject.} = value |
| 125 let `isinstancename` {.inject.} = hasCustomPragma(value, InstanceAttribute) | 126 let `isinstancename` {.inject.} = hasCustomPragma(value, InstanceAttribute) |
| 126 body | 127 body |
| 127 | 128 |
| 128 template ForDescriptorFields*(inputData: typed, typename, countname, bindingNumber, body: untyped): untyped = | 129 template ForDescriptorFields*(inputData: typed, fieldname, typename, countname, bindingNumber, body: untyped): untyped = |
| 129 var `bindingNumber` {.inject.} = 1'u32 | 130 var `bindingNumber` {.inject.} = 1'u32 |
| 130 for theFieldname, value in fieldPairs(inputData): | 131 for theFieldname, value in fieldPairs(inputData): |
| 132 let `fieldname` {.inject.} = theFieldname | |
| 131 when typeof(value) is Texture: | 133 when typeof(value) is Texture: |
| 132 block: | 134 block: |
| 133 let `typename` {.inject.} = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER | 135 let `typename` {.inject.} = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER |
| 134 let `countname` {.inject.} = 1'u32 | 136 let `countname` {.inject.} = 1'u32 |
| 135 body | 137 body |
| 193 return 1 | 195 return 1 |
| 194 | 196 |
| 195 type | 197 type |
| 196 IndexType = enum | 198 IndexType = enum |
| 197 None, UInt8, UInt16, UInt32 | 199 None, UInt8, UInt16, UInt32 |
| 198 RenderBuffers = object | 200 |
| 199 deviceBuffers: seq[Buffer] # for fast reads | 201 IndirectGPUMemory = object |
| 200 hostVisibleBuffers: seq[Buffer] # for fast writes | 202 vk: VkDeviceMemory |
| 203 size: uint64 | |
| 204 DirectGPUMemory = object | |
| 205 vk: VkDeviceMemory | |
| 206 size: uint64 | |
| 207 data: pointer | |
| 208 GPUMemory = IndirectGPUMemory | DirectGPUMemory | |
| 209 | |
| 210 Buffer[TMemory: GPUMemory] = object | |
| 211 vk: VkBuffer | |
| 212 memory*: TMemory | |
| 213 offset: uint64 | |
| 214 size: uint64 | |
| 215 | |
| 216 GPUArray[T: SupportedGPUType, TMemory: GPUMemory] = object | |
| 217 data: seq[T] | |
| 218 buffer: Buffer[TMemory] | |
| 219 offset: uint64 | |
| 220 GPUValue[T: object|array, TMemory: GPUMemory] = object | |
| 221 data: T | |
| 222 buffer: Buffer[TMemory] | |
| 223 offset: uint64 | |
| 224 | |
| 201 Renderable[TMesh, TInstance] = object | 225 Renderable[TMesh, TInstance] = object |
| 202 vertexBuffers: seq[VkBuffer] | 226 vertexBuffers: seq[VkBuffer] |
| 203 bufferOffsets: seq[VkDeviceSize] | 227 bufferOffsets: seq[VkDeviceSize] |
| 204 instanceCount: uint32 | 228 instanceCount: uint32 |
| 205 case indexType: IndexType | 229 case indexType: IndexType |
| 207 vertexCount: uint32 | 231 vertexCount: uint32 |
| 208 else: | 232 else: |
| 209 indexBuffer: VkBuffer | 233 indexBuffer: VkBuffer |
| 210 indexCount: uint32 | 234 indexCount: uint32 |
| 211 indexBufferOffset: VkDeviceSize | 235 indexBufferOffset: VkDeviceSize |
| 236 | |
| 212 Pipeline[TShader] = object | 237 Pipeline[TShader] = object |
| 213 pipeline: VkPipeline | 238 pipeline: VkPipeline |
| 214 layout: VkPipelineLayout | 239 layout: VkPipelineLayout |
| 215 descriptorSets: array[INFLIGHTFRAMES.int, VkDescriptorSet] | 240 descriptorSetLayout: VkDescriptorSetLayout |
| 241 RenderData = object | |
| 242 descriptorPool: VkDescriptorPool | |
| 243 indirectMemory: seq[IndirectGPUMemory] | |
| 244 nextFreeIndirectMemoryOffset: seq[uint64] | |
| 245 indirectBuffers: seq[Buffer[IndirectGPUMemory]] | |
| 246 directMemory: seq[DirectGPUMemory] | |
| 247 nextFreeDirectMemoryOffset: seq[uint64] | |
| 248 directBuffers: seq[Buffer[DirectGPUMemory]] | |
| 216 | 249 |
| 217 converter toVkIndexType(indexType: IndexType): VkIndexType = | 250 converter toVkIndexType(indexType: IndexType): VkIndexType = |
| 218 case indexType: | 251 case indexType: |
| 219 of None: VK_INDEX_TYPE_NONE_KHR | 252 of None: VK_INDEX_TYPE_NONE_KHR |
| 220 of UInt8: VK_INDEX_TYPE_UINT8_EXT | 253 of UInt8: VK_INDEX_TYPE_UINT8_EXT |
| 422 shader: ShaderObject[TShader], | 455 shader: ShaderObject[TShader], |
| 423 topology: VkPrimitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, | 456 topology: VkPrimitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, |
| 424 polygonMode: VkPolygonMode = VK_POLYGON_MODE_FILL, | 457 polygonMode: VkPolygonMode = VK_POLYGON_MODE_FILL, |
| 425 cullMode: VkCullModeFlagBits = VK_CULL_MODE_BACK_BIT, | 458 cullMode: VkCullModeFlagBits = VK_CULL_MODE_BACK_BIT, |
| 426 frontFace: VkFrontFace = VK_FRONT_FACE_CLOCKWISE, | 459 frontFace: VkFrontFace = VK_FRONT_FACE_CLOCKWISE, |
| 460 descriptorPoolLimit = 1024 | |
| 427 ): Pipeline[TShader] = | 461 ): Pipeline[TShader] = |
| 428 # assumptions/limitations: | |
| 429 # - we are only using vertex and fragment shaders (2 stages) | |
| 430 # - we only support one subpass | |
| 431 # = we only support one Uniform-Block | |
| 432 | |
| 433 # create pipeline | 462 # create pipeline |
| 434 var layoutbindings: seq[VkDescriptorSetLayoutBinding] | 463 var layoutbindings: seq[VkDescriptorSetLayoutBinding] |
| 435 ForDescriptorFields(default(TShader), descriptorType, descriptorCount, descriptorBindingNumber): | 464 ForDescriptorFields(default(TShader), fieldName, descriptorType, descriptorCount, descriptorBindingNumber): |
| 436 layoutbindings.add VkDescriptorSetLayoutBinding( | 465 layoutbindings.add VkDescriptorSetLayoutBinding( |
| 437 binding: descriptorBindingNumber, | 466 binding: descriptorBindingNumber, |
| 438 descriptorType: descriptorType, | 467 descriptorType: descriptorType, |
| 439 descriptorCount: descriptorCount, | 468 descriptorCount: descriptorCount, |
| 440 stageFlags: VkShaderStageFlags(VK_SHADER_STAGE_ALL_GRAPHICS), | 469 stageFlags: VkShaderStageFlags(VK_SHADER_STAGE_ALL_GRAPHICS), |
| 443 var layoutCreateInfo = VkDescriptorSetLayoutCreateInfo( | 472 var layoutCreateInfo = VkDescriptorSetLayoutCreateInfo( |
| 444 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, | 473 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, |
| 445 bindingCount: uint32(layoutbindings.len), | 474 bindingCount: uint32(layoutbindings.len), |
| 446 pBindings: layoutbindings.ToCPointer | 475 pBindings: layoutbindings.ToCPointer |
| 447 ) | 476 ) |
| 448 var descriptorSetLayout: VkDescriptorSetLayout | 477 result.descriptorSetLayout: VkDescriptorSetLayout |
| 449 checkVkResult vkCreateDescriptorSetLayout(device, addr(layoutCreateInfo), nil, addr(descriptorSetLayout)) | 478 checkVkResult vkCreateDescriptorSetLayout(device, addr(layoutCreateInfo), nil, addr(result.descriptorSetLayout)) |
| 450 let pipelineLayoutInfo = VkPipelineLayoutCreateInfo( | 479 let pipelineLayoutInfo = VkPipelineLayoutCreateInfo( |
| 451 sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, | 480 sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, |
| 452 setLayoutCount: 1, | 481 setLayoutCount: 1, |
| 453 pSetLayouts: addr(descriptorSetLayout), | 482 pSetLayouts: addr(result.descriptorSetLayout), |
| 454 # pushConstantRangeCount: uint32(pushConstants.len), | 483 # pushConstantRangeCount: uint32(pushConstants.len), |
| 455 # pPushConstantRanges: pushConstants.ToCPointer, | 484 # pPushConstantRanges: pushConstants.ToCPointer, |
| 456 ) | 485 ) |
| 457 checkVkResult vkCreatePipelineLayout(device, addr(pipelineLayoutInfo), nil, addr(result.layout)) | 486 checkVkResult vkCreatePipelineLayout(device, addr(pipelineLayoutInfo), nil, addr(result.layout)) |
| 458 | 487 |
| 580 addr(createInfo), | 609 addr(createInfo), |
| 581 nil, | 610 nil, |
| 582 addr(result.pipeline) | 611 addr(result.pipeline) |
| 583 ) | 612 ) |
| 584 | 613 |
| 585 # create descriptors, one per frame-in-flight | 614 proc AllocateIndirectMemory(device: VkDevice, pDevice: VkPhysicalDevice, allocationSize: uint64): IndirectGPUMemory = |
| 586 let nSamplers = 0'u32 | 615 # chooses biggest memory type that has NOT VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
| 587 let nUniformBuffers = 0'u32 | 616 result.size = allocationSize |
| 588 | 617 |
| 589 if nSamplers + nUniformBuffers > 0: | 618 # find a good memory type |
| 590 var poolSizes: seq[VkDescriptorPoolSize] | 619 var physicalProperties: VkPhysicalDeviceMemoryProperties |
| 591 if nUniformBuffers > 0: | 620 vkGetPhysicalDeviceMemoryProperties(pDevice, addr physicalProperties) |
| 592 poolSizes.add VkDescriptorPoolSize(thetype: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, descriptorCount: nSamplers * INFLIGHTFRAMES) | 621 |
| 593 if nSamplers > 0: | 622 var biggestHeap: uint64 = -1 |
| 594 poolSizes.add VkDescriptorPoolSize(thetype: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: nUniformBuffers * INFLIGHTFRAMES) | 623 var memoryTypeIndex = -1 |
| 595 var poolInfo = VkDescriptorPoolCreateInfo( | 624 # try to find non-host-visible type |
| 596 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, | 625 for i in 0 ..< physicalProperties.memoryTypeCount: |
| 597 poolSizeCount: uint32(poolSizes.len), | 626 if VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT not in toEnums(physicalProperties.memoryTypes[i].propertyFlags) |
| 598 pPoolSizes: poolSizes.ToCPointer, | 627 let size = physicalProperties.memoryHeaps[physicalProperties.memoryTypes[i].heapIndex].size |
| 599 maxSets: (nUniformBuffers + nSamplers) * INFLIGHTFRAMES * 2, # good formula? no idea... | 628 if size > biggestHeap: |
| 600 ) | 629 biggest = size |
| 601 var pool: VkDescriptorPool | 630 memoryTypeIndex = i |
| 602 checkVkResult vkCreateDescriptorPool(device, addr(poolInfo), nil, addr(pool)) | 631 |
| 603 | 632 # If we did not found a device-only memory type, let's just take the biggest overall |
| 604 var layouts = newSeqWith(result.descriptorSets.len, descriptorSetLayout) | 633 if memoryTypeIndex < 0: |
| 605 var allocInfo = VkDescriptorSetAllocateInfo( | 634 for i in 0 ..< physicalProperties.memoryTypeCount: |
| 606 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, | 635 let size = physicalProperties.memoryHeaps[physicalProperties.memoryTypes[i].heapIndex].size |
| 607 descriptorPool: pool, | 636 if size > biggestHeap: |
| 608 descriptorSetCount: uint32(layouts.len), | 637 biggest = size |
| 609 pSetLayouts: layouts.ToCPointer, | 638 memoryTypeIndex = i |
| 610 ) | 639 |
| 611 checkVkResult vkAllocateDescriptorSets(device, addr(allocInfo), result.descriptorSets.ToCPointer) | 640 assert memoryTypeIndex >= 0, "Unable to find indirect memory type" |
| 641 var allocationInfo = VkMemoryAllocateInfo( | |
| 642 sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, | |
| 643 allocationSize: initialAllocationSize, | |
| 644 memoryTypeIndex: memoryTypeIndex, | |
| 645 ) | |
| 646 checkVkResult vkAllocateMemory( | |
| 647 device, | |
| 648 addr allocationInfo, | |
| 649 nil, | |
| 650 addr result.vk | |
| 651 ) | |
| 652 | |
| 653 proc AllocateDirectMemory(device: VkDevice, allocationSize: uint64): DirectGPUMemory = | |
| 654 result.size = allocationSize | |
| 655 | |
| 656 # find a good memory type | |
| 657 var physicalProperties: VkPhysicalDeviceMemoryProperties | |
| 658 vkGetPhysicalDeviceMemoryProperties(pDevice, addr physicalProperties) | |
| 659 | |
| 660 var biggestHeap: uint64 = -1 | |
| 661 var memoryTypeIndex = -1 | |
| 662 # try to find host-visible type | |
| 663 for i in 0 ..< physicalProperties.memoryTypeCount: | |
| 664 if VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in toEnums(physicalProperties.memoryTypes[i].propertyFlags) | |
| 665 let size = physicalProperties.memoryHeaps[physicalProperties.memoryTypes[i].heapIndex].size | |
| 666 if size > biggestHeap: | |
| 667 biggest = size | |
| 668 memoryTypeIndex = i | |
| 669 | |
| 670 assert memoryTypeIndex >= 0, "Unable to find direct (aka host-visible) memory type" | |
| 671 var allocationInfo = VkMemoryAllocateInfo( | |
| 672 sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, | |
| 673 allocationSize: initialAllocationSize, | |
| 674 memoryTypeIndex: memoryTypeIndex, | |
| 675 ) | |
| 676 checkVkResult vkAllocateMemory( | |
| 677 device, | |
| 678 addr allocationInfo, | |
| 679 nil, | |
| 680 addr result.vk | |
| 681 ) | |
| 682 checkVkResult result.device.vk.vkMapMemory( | |
| 683 memory = result.vk, | |
| 684 offset = 0'u64, | |
| 685 size = result.size, | |
| 686 flags = VkMemoryMapFlags(0), | |
| 687 ppData = addr(result.data) | |
| 688 ) | |
| 689 | |
| 690 proc InitRenderData(device: VkDevice, descriptorPoolLimit = 1024): RenderData = | |
| 691 # allocate descriptor pools | |
| 692 var poolSizes = [ | |
| 693 VkDescriptorPoolSize(thetype: VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, descriptorCount: descriptorPoolLimit) | |
| 694 VkDescriptorPoolSize(thetype: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: descriptorPoolLimit) | |
| 695 ] | |
| 696 var poolInfo = VkDescriptorPoolCreateInfo( | |
| 697 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, | |
| 698 poolSizeCount: poolSizes.len.uint32, | |
| 699 pPoolSizes: poolSizes.ToCPointer, | |
| 700 maxSets: descriptorPoolLimit, | |
| 701 ) | |
| 702 checkVkResult vkCreateDescriptorPool(device, addr(poolInfo), nil, addr(result.descriptorPool)) | |
| 703 | |
| 704 # allocate some memory | |
| 705 var initialAllocationSize: 1_000_000_000 # TODO: make this more dynamic or something | |
| 706 result.indirectMemory = @[AllocateIndirectMemory(device, size=initialAllocationSize)] | |
| 707 result.nextFreeIndirectMemoryOffset = @[0'u64] | |
| 708 result.directMemory = @[AllocateDirectMemory(device, size=initialAllocationSize)] | |
| 709 result.nextFreeDirectMemoryOffset = @[0'u64] | |
| 612 | 710 |
| 613 proc WriteDescriptors[TShader](device: VkDevice, pipeline: Pipeline[TShader]) = | 711 proc WriteDescriptors[TShader](device: VkDevice, pipeline: Pipeline[TShader]) = |
| 614 var descriptorSetWrites: seq[VkWriteDescriptorSet] | 712 var descriptorSetWrites: seq[VkWriteDescriptorSet] |
| 615 ForDescriptorFields(default(TShader), descriptorType, descriptorCount, descriptorBindingNumber): | 713 # map (buffer + offset + range) to descriptor |
| 714 # map (texture) to descriptor | |
| 715 ForDescriptorFields(default(TShader), fieldName, descriptorType, descriptorCount, descriptorBindingNumber): | |
| 616 for frameInFlight in 0 ..< pipeline.descriptorSets.len: | 716 for frameInFlight in 0 ..< pipeline.descriptorSets.len: |
| 617 if descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: | 717 if descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: |
| 618 # TODO | 718 # TODO |
| 619 let bufferInfo = VkDescriptorBufferInfo( | 719 let bufferInfo = VkDescriptorBufferInfo( |
| 620 buffer: VkBuffer(0), | 720 buffer: VkBuffer(0), |
| 651 vkUpdateDescriptorSets(device, uint32(descriptorSetWrites.len), descriptorSetWrites.ToCPointer, 0, nil) | 751 vkUpdateDescriptorSets(device, uint32(descriptorSetWrites.len), descriptorSetWrites.ToCPointer, 0, nil) |
| 652 | 752 |
| 653 proc CreateRenderable[TMesh, TInstance]( | 753 proc CreateRenderable[TMesh, TInstance]( |
| 654 mesh: TMesh, | 754 mesh: TMesh, |
| 655 instance: TInstance, | 755 instance: TInstance, |
| 656 buffers: RenderBuffers, | |
| 657 ): Renderable[TMesh, TInstance] = | 756 ): Renderable[TMesh, TInstance] = |
| 658 result.indexType = None | 757 result.indexType = None |
| 659 | 758 |
| 660 proc Bind[T](pipeline: Pipeline[T], commandBuffer: VkCommandBuffer, currentFrameInFlight: int) = | 759 proc Bind[T](pipeline: Pipeline[T], commandBuffer: VkCommandBuffer, currentFrameInFlight: int) = |
| 661 let a = pipeline.descriptorSets | 760 let a = pipeline.descriptorSets |
| 674 proc AssertCompatible(TShader, TMesh, TInstance, TGlobals: typedesc) = | 773 proc AssertCompatible(TShader, TMesh, TInstance, TGlobals: typedesc) = |
| 675 # assert seq-fields of TMesh|TInstance == seq-fields of TShader | 774 # assert seq-fields of TMesh|TInstance == seq-fields of TShader |
| 676 # assert normal fields of TMesh|Globals == normal fields of TShaderDescriptors | 775 # assert normal fields of TMesh|Globals == normal fields of TShaderDescriptors |
| 677 for inputName, inputValue in default(TShader).fieldPairs: | 776 for inputName, inputValue in default(TShader).fieldPairs: |
| 678 var foundField = false | 777 var foundField = false |
| 778 | |
| 779 # Vertex input data | |
| 679 when hasCustomPragma(inputValue, VertexAttribute): | 780 when hasCustomPragma(inputValue, VertexAttribute): |
| 680 assert typeof(inputValue) is SupportedGPUType | 781 assert typeof(inputValue) is SupportedGPUType |
| 681 for meshName, meshValue in default(TMesh).fieldPairs: | 782 for meshName, meshValue in default(TMesh).fieldPairs: |
| 682 when meshName == inputName: | 783 when meshName == inputName: |
| 784 assert meshValue is GPUArray, "Mesh attribute '" & meshName & "' must be of type 'GPUArray' but is of type " & tt.name(typeof(meshValue)) | |
| 683 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" | 785 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" |
| 684 assert elementType(meshValue) is typeof(inputValue), "Shader input " & tt.name(TShader) & "." & inputName & " is of type '" & tt.name(typeof(inputValue)) & "' but mesh attribute is of type '" & tt.name(elementType(meshValue)) & "'" | 786 assert elementType(meshValue.data) is typeof(inputValue), "Shader input " & tt.name(TShader) & "." & inputName & " is of type '" & tt.name(typeof(inputValue)) & "' but mesh attribute is of type '" & tt.name(elementType(meshValue.data)) & "'" |
| 685 foundField = true | 787 foundField = true |
| 686 assert foundField, "Shader input '" & tt.name(TShader) & "." & inputName & ": " & tt.name(typeof(inputValue)) & "' not found in '" & tt.name(TMesh) & "'" | 788 assert foundField, "Shader input '" & tt.name(TShader) & "." & inputName & ": " & tt.name(typeof(inputValue)) & "' not found in '" & tt.name(TMesh) & "'" |
| 789 | |
| 790 # Instance input data | |
| 687 elif hasCustomPragma(inputValue, InstanceAttribute): | 791 elif hasCustomPragma(inputValue, InstanceAttribute): |
| 688 assert typeof(inputValue) is SupportedGPUType | 792 assert typeof(inputValue) is SupportedGPUType |
| 689 for instanceName, instanceValue in default(TInstance).fieldPairs: | 793 for instanceName, instanceValue in default(TInstance).fieldPairs: |
| 690 when instanceName == inputName: | 794 when instanceName == inputName: |
| 795 assert instanceValue is GPUArray, "Instance attribute '" & instanceName & "' must be of type 'GPUArray' but is of type " & tt.name(typeof(instanceName)) | |
| 691 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" | 796 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" |
| 692 assert elementType(instanceValue) 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)) & "'" | 797 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)) & "'" |
| 693 foundField = true | 798 foundField = true |
| 694 assert foundField, "Shader input '" & tt.name(TShader) & "." & inputName & ": " & tt.name(typeof(inputValue)) & "' not found in '" & tt.name(TInstance) & "'" | 799 assert foundField, "Shader input '" & tt.name(TShader) & "." & inputName & ": " & tt.name(typeof(inputValue)) & "' not found in '" & tt.name(TInstance) & "'" |
| 695 elif typeof(inputValue) is Texture or typeof(inputValue) is object: | 800 |
| 801 # Texture | |
| 802 elif typeof(inputValue) is Texture: | |
| 696 for meshName, meshValue in default(TMesh).fieldPairs: | 803 for meshName, meshValue in default(TMesh).fieldPairs: |
| 697 when meshName == inputName: | 804 when meshName == inputName: |
| 698 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" | 805 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" |
| 699 assert typeof(meshValue) is typeof(inputValue), "Shader input " & tt.name(TShader) & "." & inputName & " is of type '" & tt.name(typeof(inputValue)) & "' but mesh attribute is of type '" & tt.name(elementType(meshValue)) & "'" | 806 assert typeof(meshValue) is typeof(inputValue), "Shader input " & tt.name(TShader) & "." & inputName & " is of type '" & tt.name(typeof(inputValue)) & "' but mesh attribute is of type '" & tt.name(elementType(meshValue)) & "'" |
| 700 foundField = true | 807 foundField = true |
| 702 when globalName == inputName: | 809 when globalName == inputName: |
| 703 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" | 810 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" |
| 704 assert typeof(globalValue) 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)) & "'" | 811 assert typeof(globalValue) 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)) & "'" |
| 705 foundField = true | 812 foundField = true |
| 706 assert foundField, "Shader input '" & tt.name(TShader) & "." & inputName & ": " & tt.name(typeof(inputValue)) & "' not found in '" & tt.name(TMesh) & "|" & tt.name(TGlobals) & "'" | 813 assert foundField, "Shader input '" & tt.name(TShader) & "." & inputName & ": " & tt.name(typeof(inputValue)) & "' not found in '" & tt.name(TMesh) & "|" & tt.name(TGlobals) & "'" |
| 814 | |
| 815 # Uniform block | |
| 816 elif typeof(inputValue) is object: | |
| 817 for meshName, meshValue in default(TMesh).fieldPairs: | |
| 818 when meshName == inputName: | |
| 819 assert meshValue is GPUValue, "Mesh attribute '" & meshName & "' must be of type 'GPUValue' but is of type " & tt.name(typeof(meshValue)) | |
| 820 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" | |
| 821 assert typeof(meshValue.data) is typeof(inputValue), "Shader input " & tt.name(TShader) & "." & inputName & " is of type '" & tt.name(typeof(inputValue)) & "' but mesh attribute is of type '" & tt.name(elementType(meshValue.data)) & "'" | |
| 822 foundField = true | |
| 823 for globalName, globalValue in default(TGlobals).fieldPairs: | |
| 824 when globalName == inputName: | |
| 825 assert globalValue is GPUValue, "global attribute '" & globalName & "' must be of type 'GPUValue' but is of type " & tt.name(typeof(globalValue)) | |
| 826 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" | |
| 827 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)) & "'" | |
| 828 foundField = true | |
| 829 assert foundField, "Shader input '" & tt.name(TShader) & "." & inputName & ": " & tt.name(typeof(inputValue)) & "' not found in '" & tt.name(TMesh) & "|" & tt.name(TGlobals) & "'" | |
| 830 | |
| 831 # array | |
| 707 elif typeof(inputValue) is array: | 832 elif typeof(inputValue) is array: |
| 708 when (elementType(inputValue) is Texture or elementType(inputValue) is object): | 833 |
| 834 # texture-array | |
| 835 when elementType(inputValue) is Texture: | |
| 709 for meshName, meshValue in default(TMesh).fieldPairs: | 836 for meshName, meshValue in default(TMesh).fieldPairs: |
| 710 when meshName == inputName: | 837 when meshName == inputName: |
| 711 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" | 838 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" |
| 712 assert typeof(meshValue) is typeof(inputValue), "Shader input " & tt.name(TShader) & "." & inputName & " is of type '" & tt.name(typeof(inputValue)) & "' but mesh attribute is of type '" & tt.name(elementType(meshValue)) & "'" | 839 assert typeof(meshValue) is typeof(inputValue), "Shader input " & tt.name(TShader) & "." & inputName & " is of type '" & tt.name(typeof(inputValue)) & "' but mesh attribute is of type '" & tt.name(elementType(meshValue)) & "'" |
| 713 foundField = true | 840 foundField = true |
| 714 for globalName, globalValue in default(TGlobals).fieldPairs: | 841 for globalName, globalValue in default(TGlobals).fieldPairs: |
| 715 when globalName == inputName: | 842 when globalName == inputName: |
| 716 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" | 843 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" |
| 717 assert typeof(globalValue) 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)) & "'" | 844 assert typeof(globalValue) 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)) & "'" |
| 845 foundField = true | |
| 846 assert foundField, "Shader input '" & tt.name(TShader) & "." & inputName & ": " & tt.name(typeof(inputValue)) & "' not found in '" & tt.name(TMesh) & "|" & tt.name(TGlobals) & "'" | |
| 847 | |
| 848 # uniform-block array | |
| 849 elif elementType(inputValue) is object: | |
| 850 for meshName, meshValue in default(TMesh).fieldPairs: | |
| 851 when meshName == inputName: | |
| 852 assert meshValue is GPUValue, "Mesh attribute '" & meshName & "' must be of type 'GPUValue' but is of type " & tt.name(typeof(meshValue)) | |
| 853 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" | |
| 854 assert typeof(meshValue.data) is typeof(inputValue), "Shader input " & tt.name(TShader) & "." & inputName & " is of type '" & tt.name(typeof(inputValue)) & "' but mesh attribute is of type '" & tt.name(elementType(meshValue.data)) & "'" | |
| 855 foundField = true | |
| 856 for globalName, globalValue in default(TGlobals).fieldPairs: | |
| 857 when globalName == inputName: | |
| 858 assert globalValue is GPUValue, "global attribute '" & globalName & "' must be of type 'GPUValue' but is of type " & tt.name(typeof(globalValue)) | |
| 859 assert foundField == false, "Shader input '" & tt.name(TShader) & "." & inputName & "' has been found more than once" | |
| 860 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)) & "'" | |
| 718 foundField = true | 861 foundField = true |
| 719 assert foundField, "Shader input '" & tt.name(TShader) & "." & inputName & ": " & tt.name(typeof(inputValue)) & "' not found in '" & tt.name(TMesh) & "|" & tt.name(TGlobals) & "'" | 862 assert foundField, "Shader input '" & tt.name(TShader) & "." & inputName & ": " & tt.name(typeof(inputValue)) & "' not found in '" & tt.name(TMesh) & "|" & tt.name(TGlobals) & "'" |
| 720 | 863 |
| 721 | 864 |
| 722 proc Render[TShader, TMesh, TInstance, TGlobals]( | 865 proc Render[TShader, TMesh, TInstance, TGlobals]( |
| 766 reflection: float32 | 909 reflection: float32 |
| 767 baseColor: Vec3f | 910 baseColor: Vec3f |
| 768 ShaderSettings = object | 911 ShaderSettings = object |
| 769 brightness: float32 | 912 brightness: float32 |
| 770 MeshA = object | 913 MeshA = object |
| 771 position: seq[Vec3f] | 914 position: GPUArray[Vec3f, IndirectGPUMemory] |
| 772 transparency: float | 915 InstanceA = object |
| 773 material: array[3, MaterialA] | 916 rotation: GPUArray[Vec4f, IndirectGPUMemory] |
| 917 objPosition: GPUArray[Vec3f, IndirectGPUMemory] | |
| 918 UniformsA = object | |
| 919 materials: GPUValue[array[3, MaterialA], IndirectGPUMemory] | |
| 774 materialTextures: array[3, Texture] | 920 materialTextures: array[3, Texture] |
| 775 InstanceA = object | 921 GlobalsA = object |
| 776 transform: seq[Mat4] | |
| 777 position: seq[Vec3f] | |
| 778 Globals = object | |
| 779 fontAtlas: Texture | 922 fontAtlas: Texture |
| 780 settings: ShaderSettings | 923 settings: GPUValue[ShaderSettings, IndirectGPUMemory] |
| 781 | 924 |
| 782 ShaderA = object | 925 ShaderA = object |
| 783 # vertex input | 926 # vertex input |
| 784 position {.VertexAttribute.}: Vec3f | 927 position {.VertexAttribute.}: Vec3f |
| 785 transform {.InstanceAttribute.}: Mat4 | 928 objPosition {.InstanceAttribute.}: Vec3f |
| 929 rotation {.InstanceAttribute.}: Vec4f | |
| 786 # intermediate | 930 # intermediate |
| 787 test {.Pass.}: float32 | 931 test {.Pass.}: float32 |
| 788 test1 {.PassFlat.}: Vec3f | 932 test1 {.PassFlat.}: Vec3f |
| 789 # output | 933 # output |
| 790 color {.ShaderOutput.}: Vec4f | 934 color {.ShaderOutput.}: Vec4f |
| 791 # uniforms | 935 # uniforms |
| 792 material: array[3, MaterialA] | 936 materials: array[3, MaterialA] |
| 793 settings: ShaderSettings | 937 settings: ShaderSettings |
| 794 # textures | 938 # textures |
| 795 fontAtlas: Texture | 939 fontAtlas: Texture |
| 796 materialTextures: array[3, Texture] | 940 materialTextures: array[3, Texture] |
| 797 # code | 941 # code |
| 804 vulkanVersion = VK_MAKE_API_VERSION(0, 1, 3, 0), | 948 vulkanVersion = VK_MAKE_API_VERSION(0, 1, 3, 0), |
| 805 instanceExtensions = @[], | 949 instanceExtensions = @[], |
| 806 layers = @["VK_LAYER_KHRONOS_validation"], | 950 layers = @["VK_LAYER_KHRONOS_validation"], |
| 807 ) | 951 ) |
| 808 | 952 |
| 809 | |
| 810 let selectedPhysicalDevice = i.GetPhysicalDevices().FilterBestGraphics() | 953 let selectedPhysicalDevice = i.GetPhysicalDevices().FilterBestGraphics() |
| 811 let dev = i.CreateDevice( | 954 let dev = i.CreateDevice( |
| 812 selectedPhysicalDevice, | 955 selectedPhysicalDevice, |
| 813 enabledExtensions = @[], | 956 enabledExtensions = @[], |
| 814 selectedPhysicalDevice.FilterForGraphicsPresentationQueues() | 957 selectedPhysicalDevice.FilterForGraphicsPresentationQueues() |
| 815 ) | 958 ) |
| 816 let frameWidth = 100'u32 | 959 let frameWidth = 100'u32 |
| 817 let frameHeight = 100'u32 | 960 let frameHeight = 100'u32 |
| 818 | 961 |
| 819 var myRenderable: Renderable[MeshA, InstanceA] | 962 var myMesh1 = MeshA( |
| 820 var myGlobals: Globals | 963 position: GPUArray[Vec3f, IndirectGPUMemory](data: @[NewVec3f(0, 0, ), NewVec3f(0, 0, ), NewVec3f(0, 0, )]), |
| 964 ) | |
| 965 var uniforms1 = UniformsA( | |
| 966 materials: GPUValue[array[3, MaterialA], IndirectGPUMemory](data: [ | |
| 967 MaterialA(reflection: 0, baseColor: NewVec3f(1, 0, 0)), | |
| 968 MaterialA(reflection: 0.1, baseColor: NewVec3f(0, 1, 0)), | |
| 969 MaterialA(reflection: 0.5, baseColor: NewVec3f(0, 0, 1)), | |
| 970 ]), | |
| 971 materialTextures: [ | |
| 972 Texture(isGrayscale: false, colorImage: Image[RGBAPixel](width: 1, height: 1, imagedata: @[[255'u8, 0'u8, 0'u8, 255'u8]])), | |
| 973 Texture(isGrayscale: false, colorImage: Image[RGBAPixel](width: 1, height: 1, imagedata: @[[0'u8, 255'u8, 0'u8, 255'u8]])), | |
| 974 Texture(isGrayscale: false, colorImage: Image[RGBAPixel](width: 1, height: 1, imagedata: @[[0'u8, 0'u8, 255'u8, 255'u8]])), | |
| 975 ] | |
| 976 ) | |
| 977 var instances1 = InstanceA( | |
| 978 rotation: GPUArray[Vec4f, IndirectGPUMemory](data: @[NewVec4f(1, 0, 0, 0.1), NewVec4f(0, 1, 0, 0.1)]), | |
| 979 objPosition: GPUArray[Vec3f, IndirectGPUMemory](data: @[NewVec3f(0, 0, 0), NewVec3f(1, 1, 1)]), | |
| 980 ) | |
| 981 var myGlobals: GlobalsA | |
| 821 | 982 |
| 822 # setup for rendering (TODO: swapchain & framebuffers) | 983 # setup for rendering (TODO: swapchain & framebuffers) |
| 823 | 984 |
| 824 # renderpass | 985 # renderpass |
| 825 let renderpass = dev.vk.CreateRenderPass(dev.physicalDevice.GetSurfaceFormats().FilterSurfaceFormat().format) | 986 let renderpass = dev.vk.CreateRenderPass(dev.physicalDevice.GetSurfaceFormats().FilterSurfaceFormat().format) |
| 827 # shaders | 988 # shaders |
| 828 const shader = ShaderA() | 989 const shader = ShaderA() |
| 829 let shaderObject = dev.vk.CompileShader(shader) | 990 let shaderObject = dev.vk.CompileShader(shader) |
| 830 var pipeline1 = CreatePipeline(dev.vk, renderPass = renderpass, shaderObject) | 991 var pipeline1 = CreatePipeline(dev.vk, renderPass = renderpass, shaderObject) |
| 831 | 992 |
| 993 var renderdata = InitRenderData(dev.vk) | |
| 994 | |
| 995 # create descriptor sets | |
| 996 var descriptorSets: array[INFLIGHTFRAMES.int, VkDescriptorSet] | |
| 997 var layouts = newSeqWith(descriptorSets.len, pipeline.descriptorSetLayout) | |
| 998 var allocInfo = VkDescriptorSetAllocateInfo( | |
| 999 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, | |
| 1000 descriptorPool: pool, | |
| 1001 descriptorSetCount: uint32(layouts.len), | |
| 1002 pSetLayouts: layouts.ToCPointer, | |
| 1003 ) | |
| 1004 checkVkResult vkAllocateDescriptorSets(device, addr(allocInfo), descriptorSets.ToCPointer) | |
| 1005 | |
| 1006 | |
| 1007 #[ | |
| 832 # TODO: probably here: allocate renderables, uniform buffers & textures | 1008 # TODO: probably here: allocate renderables, uniform buffers & textures |
| 1009 let meshBuffers: seq[(bool, uint64)] = GetBufferSizes[MeshA](item = myMesh1) | |
| 1010 let instanceBuffers: seq[(bool, uint64)] = GetBufferSizes[InstanceA](item = instances1) | |
| 1011 let globalBuffers: seq[(bool, uint64)] = GetBufferSizes[Globals](item = myGlobals) | |
| 1012 var myRenderable = CreateRenderable() | |
| 1013 UploadTextures[MeshA]() | |
| 1014 UploadTextures[Globals]() | |
| 1015 ]# | |
| 1016 var myRenderable: Renderable[MeshA, InstanceA] | |
| 833 | 1017 |
| 834 # descriptors | 1018 # descriptors |
| 835 WriteDescriptors(dev.vk, pipeline1) | 1019 WriteDescriptors(dev.vk, pipeline1) |
| 836 | 1020 |
| 837 # command buffer | 1021 # command buffer |
