comparison static_utils.nim @ 1175:a94732d98cc6 compiletime-tests

merge
author sam <sam@basx.dev>
date Sat, 29 Jun 2024 11:13:35 +0700
parents fafc2f14da0b
children 511c9f7cd1da
comparison
equal deleted inserted replaced
1174:26e367076c15 1175:a94732d98cc6
123 let `fieldname` {.inject.} = theFieldname 123 let `fieldname` {.inject.} = theFieldname
124 let `valuename` {.inject.} = value 124 let `valuename` {.inject.} = value
125 let `isinstancename` {.inject.} = hasCustomPragma(value, InstanceAttribute) 125 let `isinstancename` {.inject.} = hasCustomPragma(value, InstanceAttribute)
126 body 126 body
127 127
128 template ForDescriptorFields*(inputData: typed, typename, countname, body: untyped): untyped = 128 template ForDescriptorFields*(inputData: typed, typename, countname, bindingNumber, body: untyped): untyped =
129 var `bindingNumber` {.inject.} = 1'u32
129 for theFieldname, value in fieldPairs(inputData): 130 for theFieldname, value in fieldPairs(inputData):
130 when typeof(value) is Texture: 131 when typeof(value) is Texture:
131 block: 132 block:
132 let `typename` {.inject.} = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER 133 let `typename` {.inject.} = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
133 let `countname` {.inject.} = 1'u32 134 let `countname` {.inject.} = 1'u32
134 body 135 body
136 `bindingNumber`.inc
135 elif typeof(value) is object: 137 elif typeof(value) is object:
136 block: 138 block:
137 let `typename` {.inject.} = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER 139 let `typename` {.inject.} = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
138 let `countname` {.inject.} = 1'u32 140 let `countname` {.inject.} = 1'u32
139 body 141 body
142 `bindingNumber`.inc
140 elif typeof(value) is array: 143 elif typeof(value) is array:
141 when elementType(value) is Texture: 144 when elementType(value) is Texture:
142 block: 145 block:
143 let `typename` {.inject.} = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER 146 let `typename` {.inject.} = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
144 let `countname` {.inject.} = uint32(typeof(value).len) 147 let `countname` {.inject.} = uint32(typeof(value).len)
145 body 148 body
149 `bindingNumber`.inc
146 elif elementType(value) is object: 150 elif elementType(value) is object:
147 block: 151 block:
148 let `typename` {.inject.} = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER 152 let `typename` {.inject.} = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
149 let `countname` {.inject.} = uint32(typeof(value).len) 153 let `countname` {.inject.} = uint32(typeof(value).len)
150 body 154 body
155 `bindingNumber`.inc
151 156
152 func NumberOfVertexInputAttributeDescriptors[T: SupportedGPUType|Texture](value: T): uint32 = 157 func NumberOfVertexInputAttributeDescriptors[T: SupportedGPUType|Texture](value: T): uint32 =
153 when T is TMat2[float32] or T is TMat2[float64] or T is TMat23[float32] or T is TMat23[float64]: 158 when T is TMat2[float32] or T is TMat2[float64] or T is TMat23[float32] or T is TMat23[float64]:
154 2 159 2
155 elif T is TMat32[float32] or T is TMat32[float64] or T is TMat3[float32] or T is TMat3[float64] or T is TMat34[float32] or T is TMat34[float64]: 160 elif T is TMat32[float32] or T is TMat32[float64] or T is TMat3[float32] or T is TMat3[float64] or T is TMat34[float32] or T is TMat34[float64]:
205 indexCount: uint32 210 indexCount: uint32
206 indexBufferOffset: VkDeviceSize 211 indexBufferOffset: VkDeviceSize
207 Pipeline[TShader] = object 212 Pipeline[TShader] = object
208 pipeline: VkPipeline 213 pipeline: VkPipeline
209 layout: VkPipelineLayout 214 layout: VkPipelineLayout
210 descriptorSets: array[INFLIGHTFRAMES, VkDescriptorSet] 215 descriptorSets: array[INFLIGHTFRAMES.int, VkDescriptorSet]
211 216
212 converter toVkIndexType(indexType: IndexType): VkIndexType = 217 converter toVkIndexType(indexType: IndexType): VkIndexType =
213 case indexType: 218 case indexType:
214 of None: VK_INDEX_TYPE_NONE_KHR 219 of None: VK_INDEX_TYPE_NONE_KHR
215 of UInt8: VK_INDEX_TYPE_UINT8_EXT 220 of UInt8: VK_INDEX_TYPE_UINT8_EXT
389 uniforms & 394 uniforms &
390 samplers & 395 samplers &
391 fsOutput & 396 fsOutput &
392 @[shader.fragmentCode]).join("\n") 397 @[shader.fragmentCode]).join("\n")
393 398
394 # proc CompileShader[TShader](shader: static TShader): (seq[uint32], seq[uint32]) {.compileTime.}=
395 proc CompileShader[TShader](device: VkDevice, shader: static TShader): ShaderObject[TShader] = 399 proc CompileShader[TShader](device: VkDevice, shader: static TShader): ShaderObject[TShader] =
396 const (vertexShaderSource, fragmentShaderSource) = generateShaderSource(shader) 400 const (vertexShaderSource, fragmentShaderSource) = generateShaderSource(shader)
397 401
398 let vertexBinary = compileGlslToSPIRV(VK_SHADER_STAGE_VERTEX_BIT, vertexShaderSource) 402 let vertexBinary = compileGlslToSPIRV(VK_SHADER_STAGE_VERTEX_BIT, vertexShaderSource)
399 let fragmentBinary = compileGlslToSPIRV(VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShaderSource) 403 let fragmentBinary = compileGlslToSPIRV(VK_SHADER_STAGE_FRAGMENT_BIT, fragmentShaderSource)
426 # - we only support one subpass 430 # - we only support one subpass
427 # = we only support one Uniform-Block 431 # = we only support one Uniform-Block
428 432
429 # create pipeline 433 # create pipeline
430 var layoutbindings: seq[VkDescriptorSetLayoutBinding] 434 var layoutbindings: seq[VkDescriptorSetLayoutBinding]
431 var descriptorBindingNumber = 0'u32 435 ForDescriptorFields(default(TShader), descriptorType, descriptorCount, descriptorBindingNumber):
432 ForDescriptorFields(default(TShader), descriptorType, descriptorCount):
433 layoutbindings.add VkDescriptorSetLayoutBinding( 436 layoutbindings.add VkDescriptorSetLayoutBinding(
434 binding: descriptorBindingNumber, 437 binding: descriptorBindingNumber,
435 descriptorType: descriptorType, 438 descriptorType: descriptorType,
436 descriptorCount: descriptorCount, 439 descriptorCount: descriptorCount,
437 stageFlags: VkShaderStageFlags(VK_SHADER_STAGE_ALL_GRAPHICS), 440 stageFlags: VkShaderStageFlags(VK_SHADER_STAGE_ALL_GRAPHICS),
438 pImmutableSamplers: nil, 441 pImmutableSamplers: nil,
439 ) 442 )
440 inc descriptorBindingNumber
441 var layoutCreateInfo = VkDescriptorSetLayoutCreateInfo( 443 var layoutCreateInfo = VkDescriptorSetLayoutCreateInfo(
442 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, 444 sType: VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
443 bindingCount: uint32(layoutbindings.len), 445 bindingCount: uint32(layoutbindings.len),
444 pBindings: layoutbindings.ToCPointer 446 pBindings: layoutbindings.ToCPointer
445 ) 447 )
606 descriptorSetCount: uint32(layouts.len), 608 descriptorSetCount: uint32(layouts.len),
607 pSetLayouts: layouts.ToCPointer, 609 pSetLayouts: layouts.ToCPointer,
608 ) 610 )
609 checkVkResult vkAllocateDescriptorSets(device, addr(allocInfo), result.descriptorSets.ToCPointer) 611 checkVkResult vkAllocateDescriptorSets(device, addr(allocInfo), result.descriptorSets.ToCPointer)
610 612
611 # write descriptor sets 613 proc WriteDescriptors[TShader](device: VkDevice, pipeline: Pipeline[TShader]) =
612 # TODO
613 #[
614 var descriptorSetWrites: seq[VkWriteDescriptorSet] 614 var descriptorSetWrites: seq[VkWriteDescriptorSet]
615 for XY in descriptors?: 615 ForDescriptorFields(default(TShader), descriptorType, descriptorCount, descriptorBindingNumber):
616 616 for frameInFlight in 0 ..< pipeline.descriptorSets.len:
617 bufferInfos.add VkDescriptorBufferInfo( 617 if descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
618 buffer: descriptor.buffer.vk, 618 # TODO
619 offset: descriptor.offset, 619 let bufferInfo = VkDescriptorBufferInfo(
620 range: descriptor.size, 620 buffer: VkBuffer(0),
621 ) 621 offset: 0,
622 descriptorSetWrites.add VkWriteDescriptorSet( 622 range: 1,
623 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, 623 )
624 dstSet: descriptorSet.vk, 624 descriptorSetWrites.add VkWriteDescriptorSet(
625 dstBinding: i, 625 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
626 dstArrayElement: 0, 626 dstSet: pipeline.descriptorSets[frameInFlight],
627 descriptorType: descriptor.vkType, 627 dstBinding: descriptorBindingNumber,
628 descriptorCount: uint32(descriptor.count), 628 dstArrayElement: uint32(0),
629 pBufferInfo: addr bufferInfos[^1], 629 descriptorType: descriptorType,
630 ) 630 descriptorCount: descriptorCount,
631 vkUpdateDescriptorSets(device, uint32(descriptorSetWrites.len), descriptorSetWrites.ToCPointer, 0, nil) 631 pImageInfo: nil,
632 ]# 632 pBufferInfo: addr(bufferInfo),
633 633 )
634 elif descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
635 # TODO
636 let imageInfo = VkDescriptorImageInfo(
637 sampler: VkSampler(0),
638 imageView: VkImageView(0),
639 imageLayout: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
640 )
641 descriptorSetWrites.add VkWriteDescriptorSet(
642 sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
643 dstSet: pipeline.descriptorSets[frameInFlight],
644 dstBinding: descriptorBindingNumber,
645 dstArrayElement: uint32(0),
646 descriptorType: descriptorType,
647 descriptorCount: descriptorCount,
648 pImageInfo: addr(imageInfo),
649 pBufferInfo: nil,
650 )
651 vkUpdateDescriptorSets(device, uint32(descriptorSetWrites.len), descriptorSetWrites.ToCPointer, 0, nil)
634 652
635 proc CreateRenderable[TMesh, TInstance]( 653 proc CreateRenderable[TMesh, TInstance](
636 mesh: TMesh, 654 mesh: TMesh,
637 instance: TInstance, 655 instance: TInstance,
638 buffers: RenderBuffers, 656 buffers: RenderBuffers,
639 ): Renderable[TMesh, TInstance] = 657 ): Renderable[TMesh, TInstance] =
640 result.indexType = None 658 result.indexType = None
641 659
642 proc Bind[T](pipeline: Pipeline[T], commandBuffer: VkCommandBuffer, currentFrameInFlight: int) = 660 proc Bind[T](pipeline: Pipeline[T], commandBuffer: VkCommandBuffer, currentFrameInFlight: int) =
643 let a = pipeline.descriptorSets 661 let a = pipeline.descriptorSets
644 echo a[^currentFrameInFlight]
645 commandBuffer.vkCmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline) 662 commandBuffer.vkCmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline)
646 if a[currentFrameInFlight] != VkDescriptorSet(0): 663 if a[currentFrameInFlight] != VkDescriptorSet(0):
647 commandBuffer.vkCmdBindDescriptorSets( 664 commandBuffer.vkCmdBindDescriptorSets(
648 VK_PIPELINE_BIND_POINT_GRAPHICS, 665 VK_PIPELINE_BIND_POINT_GRAPHICS,
649 pipeline.layout, 666 pipeline.layout,
706 pipeline: Pipeline[TShader], 723 pipeline: Pipeline[TShader],
707 renderable: Renderable[TMesh, TInstance], 724 renderable: Renderable[TMesh, TInstance],
708 globals: TGlobals, 725 globals: TGlobals,
709 commandBuffer: VkCommandBuffer, 726 commandBuffer: VkCommandBuffer,
710 ) = 727 ) =
711 {.error: "Need to write descriptor sets".}
712 static: AssertCompatible(TShader, TMesh, TInstance, TGlobals) 728 static: AssertCompatible(TShader, TMesh, TInstance, TGlobals)
713 if renderable.vertexBuffers.len > 0: 729 if renderable.vertexBuffers.len > 0:
714 commandBuffer.vkCmdBindVertexBuffers( 730 commandBuffer.vkCmdBindVertexBuffers(
715 firstBinding = 0'u32, 731 firstBinding = 0'u32,
716 bindingCount = uint32(renderable.vertexBuffers.len), 732 bindingCount = uint32(renderable.vertexBuffers.len),
741 when isMainModule: 757 when isMainModule:
742 import semicongine/platform/window 758 import semicongine/platform/window
743 import semicongine/vulkan/instance 759 import semicongine/vulkan/instance
744 import semicongine/vulkan/device 760 import semicongine/vulkan/device
745 import semicongine/vulkan/physicaldevice 761 import semicongine/vulkan/physicaldevice
746 # import semicongine/vulkan/renderpass
747 import semicongine/vulkan/commandbuffer
748 import std/options 762 import std/options
749 763
750 type 764 type
751 MaterialA = object 765 MaterialA = object
752 reflection: float32 766 reflection: float32
792 layers = @["VK_LAYER_KHRONOS_validation"], 806 layers = @["VK_LAYER_KHRONOS_validation"],
793 ) 807 )
794 808
795 809
796 let selectedPhysicalDevice = i.GetPhysicalDevices().FilterBestGraphics() 810 let selectedPhysicalDevice = i.GetPhysicalDevices().FilterBestGraphics()
797 let d = i.CreateDevice( 811 let dev = i.CreateDevice(
798 selectedPhysicalDevice, 812 selectedPhysicalDevice,
799 enabledExtensions = @[], 813 enabledExtensions = @[],
800 selectedPhysicalDevice.FilterForGraphicsPresentationQueues() 814 selectedPhysicalDevice.FilterForGraphicsPresentationQueues()
801 ) 815 )
802 816 let frameWidth = 100'u32
803 var r: Renderable[MeshA, InstanceA] 817 let frameHeight = 100'u32
804 var g: Globals 818
805 819 var myRenderable: Renderable[MeshA, InstanceA]
820 var myGlobals: Globals
821
822 # setup for rendering (TODO: swapchain & framebuffers)
823
824 # renderpass
825 let renderpass = dev.vk.CreateRenderPass(dev.physicalDevice.GetSurfaceFormats().FilterSurfaceFormat().format)
826
827 # shaders
806 const shader = ShaderA() 828 const shader = ShaderA()
807 let shaderObject = d.vk.CompileShader(shader) 829 let shaderObject = dev.vk.CompileShader(shader)
808 let rp = d.vk.CreateRenderPass(d.physicalDevice.GetSurfaceFormats().FilterSurfaceFormat().format) 830 var pipeline1 = CreatePipeline(dev.vk, renderPass = renderpass, shaderObject)
809 var p = CreatePipeline(d.vk, renderPass = rp, shaderObject) 831
810 832 # TODO: probably here: allocate renderables, uniform buffers & textures
811 let commandBufferPool = d.CreateCommandBufferPool(d.FirstGraphicsQueue().get().family, INFLIGHTFRAMES.int) 833
812 let cmd = commandBufferPool.buffers[0] 834 # descriptors
813 835 WriteDescriptors(dev.vk, pipeline1)
814 checkVkResult cmd.vkResetCommandBuffer(VkCommandBufferResetFlags(0)) 836
815 let beginInfo = VkCommandBufferBeginInfo( 837 # command buffer
816 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, 838 var
817 flags: VkCommandBufferUsageFlags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT), 839 commandBufferPool: VkCommandPool
840 cmdBuffers: array[INFLIGHTFRAMES.int, VkCommandBuffer]
841 createInfo = VkCommandPoolCreateInfo(
842 sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
843 flags: toBits [VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT],
844 queueFamilyIndex: dev.FirstGraphicsQueue().get().family.index,
845 )
846 checkVkResult vkCreateCommandPool(dev.vk, addr createInfo, nil, addr commandBufferPool)
847 var allocInfo = VkCommandBufferAllocateInfo(
848 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
849 commandPool: commandBufferPool,
850 level: VK_COMMAND_BUFFER_LEVEL_PRIMARY,
851 commandBufferCount: INFLIGHTFRAMES,
818 ) 852 )
819 checkVkResult cmd.vkBeginCommandBuffer(addr(beginInfo)) 853 checkVkResult vkAllocateCommandBuffers(dev.vk, addr allocInfo, cmdBuffers.ToCPointer)
820 Bind(p, cmd, currentFrameInFlight = 0) 854
821 Render(p, r, g, cmd) 855 # start command buffer
822 856 block:
823 checkVkResult cmd.vkEndCommandBuffer() 857 let
858 currentFramebuffer = VkFramebuffer(0) # TODO
859 currentFrameInFlight = 1
860 cmd = cmdBuffers[currentFrameInFlight]
861 beginInfo = VkCommandBufferBeginInfo(
862 sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
863 flags: VkCommandBufferUsageFlags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT),
864 )
865 checkVkResult cmd.vkResetCommandBuffer(VkCommandBufferResetFlags(0))
866 checkVkResult cmd.vkBeginCommandBuffer(addr(beginInfo))
867
868 # start renderpass
869 block:
870 var
871 clearColors = [VkClearValue(color: VkClearColorValue(float32: [0, 0, 0, 0]))]
872 renderPassInfo = VkRenderPassBeginInfo(
873 sType: VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
874 renderPass: renderpass,
875 framebuffer: currentFramebuffer,
876 renderArea: VkRect2D(
877 offset: VkOffset2D(x: 0, y: 0),
878 extent: VkExtent2D(width: frameWidth, height: frameHeight),
879 ),
880 clearValueCount: uint32(clearColors.len),
881 pClearValues: clearColors.ToCPointer(),
882 )
883 viewport = VkViewport(
884 x: 0.0,
885 y: 0.0,
886 width: frameWidth.float32,
887 height: frameHeight.float32,
888 minDepth: 0.0,
889 maxDepth: 1.0,
890 )
891 scissor = VkRect2D(
892 offset: VkOffset2D(x: 0, y: 0),
893 extent: VkExtent2D(width: frameWidth, height: frameHeight)
894 )
895 vkCmdBeginRenderPass(cmd, addr(renderPassInfo), VK_SUBPASS_CONTENTS_INLINE)
896
897 # setup viewport
898 vkCmdSetViewport(cmd, firstViewport = 0, viewportCount = 1, addr(viewport))
899 vkCmdSetScissor(cmd, firstScissor = 0, scissorCount = 1, addr(scissor))
900
901 # bind pipeline, will be loop
902 block:
903 Bind(pipeline1, cmd, currentFrameInFlight = currentFrameInFlight)
904
905 # render object, will be loop
906 block:
907 Render(pipeline1, myRenderable, myGlobals, cmd)
908
909 vkCmdEndRenderPass(cmd)
910 checkVkResult cmd.vkEndCommandBuffer()