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