Mercurial > games > semicongine
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() |