# HG changeset patch # User sam # Date 1720976673 -25200 # Node ID a8864fe6fe6e4b8b139c0961cfae776c0bb32730 # Parent d4a206b5e5b02c32a0a89609560eac23312f2b9c add: descriptor sets binding n stuff diff -r d4a206b5e5b0 -r a8864fe6fe6e semicongine/rendering.nim --- a/semicongine/rendering.nim Sun Jul 14 21:30:52 2024 +0700 +++ b/semicongine/rendering.nim Mon Jul 15 00:04:33 2024 +0700 @@ -65,6 +65,8 @@ var vulkan*: VulkanGlobals +func currentFiF*(swapchain: Swapchain): int = swapchain.currentFiF + type # type aliases 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] @@ -114,8 +116,8 @@ data*: seq[T] GPUArray*[T: SupportedGPUType, TBuffer: static BufferType] = object data*: seq[T] - buffer: Buffer - offset: uint64 + buffer*: Buffer + offset*: uint64 GPUValue*[T: object|array, TBuffer: static BufferType] = object data*: T buffer: Buffer diff -r d4a206b5e5b0 -r a8864fe6fe6e semicongine/rendering/renderer.nim --- a/semicongine/rendering/renderer.nim Sun Jul 14 21:30:52 2024 +0700 +++ b/semicongine/rendering/renderer.nim Mon Jul 15 00:04:33 2024 +0700 @@ -86,14 +86,12 @@ let flags = toEnums(physicalProperties.memoryTypes[memoryTypeIndex].propertyFlags) return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT in flags -proc GetLayoutFor*(pipeline: Pipeline, dType: DescriptorSetType): VkDescriptorSetLayout = - pipeline.descriptorSetLayouts[dType] - proc InitDescriptorSet*( renderData: RenderData, layout: VkDescriptorSetLayout, descriptorSet: var DescriptorSet, ) = + # santization checks for name, value in descriptorSet.data.fieldPairs: when typeof(value) is GPUValue: @@ -185,13 +183,6 @@ pDescriptorCopies = nil, ) -converter toVkIndexType(indexType: IndexType): VkIndexType = - case indexType: - of None: VK_INDEX_TYPE_NONE_KHR - of UInt8: VK_INDEX_TYPE_UINT8_EXT - of UInt16: VK_INDEX_TYPE_UINT16 - of UInt32: VK_INDEX_TYPE_UINT32 - proc AllocateNewMemoryBlock(size: uint64, mType: uint32): MemoryBlock = result = MemoryBlock( vk: svkAllocateMemory(size, mType), @@ -536,6 +527,22 @@ assert typeof(shaderAttribute) is TMaterial, "Shader has materialdescriptor type '" & typetraits.name(get(genericParams(typeof(shaderAttribute)), 0)) & "' but provided type is " & typetraits.name(TMaterial) + +template WithBind*[A, B](commandBuffer: VkCommandBuffer, globalDescriptorSet: DescriptorSet[A, GlobalSet], materialDescriptorSet: DescriptorSet[B, MaterialSet], pipeline: Pipeline, currentFiF: int, body: untyped): untyped = + block: + let sets = [globalDescriptorSet.vk[currentFiF], materialDescriptorSet.vk[currentFiF]] + vkCmdBindDescriptorSets( + commandBuffer = commandBuffer, + pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, + layout = pipeline.layout, + firstSet = 0, + descriptorSetCount = sets.len.uint32, + pDescriptorSets = sets.ToCPointer, + dynamicOffsetCount = 0, + pDynamicOffsets = nil + ) + body + proc Render*[TShader, TGlobals, TMaterial, TMesh, TInstance]( commandBuffer: VkCommandBuffer, pipeline: Pipeline[TShader], @@ -544,33 +551,91 @@ mesh: TMesh, instances: TInstance, ) = - static: AssertCompatible(TShader, TMesh, TInstance, TGlobals, TMaterial) - #[ - if renderable.vertexBuffers.len > 0: - commandBuffer.vkCmdBindVertexBuffers( + when not defined(release): + static: AssertCompatible(TShader, TMesh, TInstance, TGlobals, TMaterial) + + var vertexBuffers: seq[VkBuffer] + var vertexBuffersOffsets: seq[uint64] + var elementCount = 0'u32 + var instanceCount = 1'u32 + + for shaderAttributeName, shaderAttribute in default(TShader).fieldPairs: + when hasCustomPragma(shaderAttribute, VertexAttribute): + for meshName, meshValue in mesh.fieldPairs: + when meshName == shaderAttributeName: + vertexBuffers.add meshValue.buffer.vk + vertexBuffersOffsets.add meshValue.offset + elementCount = meshValue.data.len.uint32 + elif hasCustomPragma(shaderAttribute, InstanceAttribute): + for instanceName, instanceValue in instances.fieldPairs: + when instanceName == shaderAttributeName: + vertexBuffers.add instanceValue.buffer.vk + vertexBuffersOffsets.add instanceValue.offset + instanceCount = instanceValue.data.len.uint32 + + if vertexBuffers.len > 0: + vkCmdBindVertexBuffers( + commandBuffer = commandBuffer, firstBinding = 0'u32, - bindingCount = uint32(renderable.vertexBuffers.len), - pBuffers = renderable.vertexBuffers.ToCPointer(), - pOffsets = renderable.bufferOffsets.ToCPointer() + bindingCount = uint32(vertexBuffers.len), + pBuffers = vertexBuffers.ToCPointer(), + pOffsets = vertexBuffersOffsets.ToCPointer() ) - if renderable.indexType != None: - commandBuffer.vkCmdBindIndexBuffer( - renderable.indexBuffer, - renderable.indexBufferOffset, - renderable.indexType, + + var indexBuffer: VkBuffer + var indexBufferOffset: uint64 + var indexType = VK_INDEX_TYPE_NONE_KHR + + for meshName, meshValue in mesh.fieldPairs: + when typeof(meshValue) is GPUArray[uint8, IndexBuffer]: + indexBuffer = meshValue.buffer.vk + indexBufferOffset = meshValue.offset + indexType = VK_INDEX_TYPE_UINT8_EXT + elementCount = meshValue.data.len.uint32 + elif typeof(meshValue) is GPUArray[uint16, IndexBuffer]: + indexBuffer = meshValue.buffer.vk + indexBufferOffset = meshValue.offset + indexType = VK_INDEX_TYPE_UINT16 + elementCount = meshValue.data.len.uint32 + elif typeof(meshValue) is GPUArray[uint32, IndexBuffer]: + indexBuffer = meshValue.buffer.vk + indexBufferOffset = meshValue.offset + indexType = VK_INDEX_TYPE_UINT32 + elementCount = meshValue.data.len.uint32 + + assert elementCount > 0 + + if indexType != VK_INDEX_TYPE_NONE_KHR: + vkCmdBindIndexBuffer( + commandBuffer, + indexBuffer, + indexBufferOffset, + indexType, ) - commandBuffer.vkCmdDrawIndexed( - indexCount = renderable.indexCount, - instanceCount = renderable.instanceCount, + vkCmdDrawIndexed( + commandBuffer = commandBuffer, + indexCount = elementCount, + instanceCount = instanceCount, firstIndex = 0, vertexOffset = 0, firstInstance = 0 ) else: - commandBuffer.vkCmdDraw( - vertexCount = renderable.vertexCount, - instanceCount = renderable.instanceCount, + vkCmdDraw( + commandBuffer = commandBuffer, + vertexCount = elementCount, + instanceCount = instanceCount, firstVertex = 0, firstInstance = 0 ) - ]# + +type EMPTY = object + +proc Render*[TShader, TGlobals, TMaterial, TMesh]( + commandBuffer: VkCommandBuffer, + pipeline: Pipeline[TShader], + globalSet: TGlobals, + materialSet: TMaterial, + mesh: TMesh, +) = + Render(commandBuffer, pipeline, globalSet, materialSet, mesh, EMPTY()) diff -r d4a206b5e5b0 -r a8864fe6fe6e semicongine/rendering/shaders.nim --- a/semicongine/rendering/shaders.nim Sun Jul 14 21:30:52 2024 +0700 +++ b/semicongine/rendering/shaders.nim Mon Jul 15 00:04:33 2024 +0700 @@ -460,6 +460,15 @@ addr(result.vk) ) +proc GetLayoutFor*(pipeline: Pipeline, dType: DescriptorSetType): VkDescriptorSetLayout = + pipeline.descriptorSetLayouts[dType] + + +template WithPipeline*(commandbuffer: VkCommandBuffer, pipeline: Pipeline, body: untyped): untyped = + block: + vkCmdBindPipeline(commandbuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.vk) + body + proc DestroyPipeline*(pipeline: Pipeline) = for descriptorSetLayout in pipeline.descriptorSetLayouts: diff -r d4a206b5e5b0 -r a8864fe6fe6e test1.nim --- a/test1.nim Sun Jul 14 21:30:52 2024 +0700 +++ b/test1.nim Mon Jul 15 00:04:33 2024 +0700 @@ -29,8 +29,8 @@ ShaderA = object # vertex input position {.VertexAttribute.}: Vec3f - objPosition {.InstanceAttribute.}: Vec3f - rotation {.InstanceAttribute.}: Vec4f + # objPosition {.InstanceAttribute.}: Vec3f + # rotation {.InstanceAttribute.}: Vec4f # intermediate test {.Pass.}: float32 test1 {.PassFlat.}: Vec3f @@ -40,14 +40,16 @@ globals: DescriptorSet[GlobalsA, GlobalSet] uniforms: DescriptorSet[UniformsA, MaterialSet] # code - vertexCode: string = "void main() {}" - fragmentCode: string = "void main() {}" - -let frameWidth = 100'u32 -let frameHeight = 100'u32 + vertexCode: string = """void main() { + gl_Position = vec4(position, 1); +}""" + fragmentCode: string = """void main() { + color = vec4(1, 0, 0, 1); +}""" var myMesh1 = MeshA( - position: GPUArray[Vec3f, VertexBuffer](data: @[NewVec3f(0, 0, ), NewVec3f(0, 0, ), NewVec3f(0, 0, )]), + position: GPUArray[Vec3f, VertexBuffer](data: @[NewVec3f(-0.5, 0.5, ), NewVec3f(0, -0.5, ), NewVec3f(0.5, 0.5, )]), + indices: GPUArray[uint16, IndexBuffer](data: @[0'u16, 1'u16, 2'u16]) ) var uniforms1 = DescriptorSet[UniformsA, MaterialSet]( data: UniformsA( @@ -76,12 +78,7 @@ ) let mainRenderpass = CreatePresentationRenderPass() -var swapchainResult = InitSwapchain(renderpass = mainRenderpass) - -assert swapchainResult.isSome() -var swapchain = swapchainResult.get() - -# shaders +var swapchain = InitSwapchain(renderpass = mainRenderpass).get() var pipeline1 = CreatePipeline[ShaderA](renderPass = mainRenderpass) var renderdata = InitRenderData() @@ -111,24 +108,25 @@ InitDescriptorSet(renderdata, pipeline1.GetLayoutFor(MaterialSet), uniforms1) -# start command buffer +# main loop var t = getMonoTime() while UpdateInputs(): WithNextFrame(swapchain, framebuffer, commandbuffer): - WithRenderPass(mainRenderpass, framebuffer, commandbuffer, swapchain.width, swapchain.height, NewVec4f(1, 0, 0, 0)): - vkCmdBindPipeline(commandbuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline1.vk) + WithRenderPass(mainRenderpass, framebuffer, commandbuffer, swapchain.width, swapchain.height, NewVec4f(0, 0, 0, 0)): + WithPipeline(commandbuffer, pipeline1): + WithBind(commandBuffer, myGlobals, uniforms1, pipeline1, swapchain.currentFiF.int): + Render( + commandbuffer = commandbuffer, + pipeline = pipeline1, + globalSet = myGlobals, + materialSet = uniforms1, + mesh = myMesh1, + # instances = instances1, + ) + echo (getMonoTime() - t).inMicroseconds.float / 1000.0 + t = getMonoTime() - Render( - commandbuffer = commandbuffer, - pipeline = pipeline1, - globalSet = myGlobals, - materialSet = uniforms1, - mesh = myMesh1, - instances = instances1, - ) - echo (getMonoTime() - t).inMicroseconds.float / 1000.0 - t = getMonoTime() - +# cleanup checkVkResult vkDeviceWaitIdle(vulkan.device) DestroyPipeline(pipeline1) vkDestroyRenderPass(vulkan.device, mainRenderpass, nil)