# HG changeset patch # User Sam # Date 1680455184 -25200 # Node ID 056e08dfad107059a13ddff9c03362ffdeb2d132 # Parent 7b695fb335edf1e31a4a3a0a121df95876b4c66f yay: first triangle rendering with new engine implmentation diff -r 7b695fb335ed -r 056e08dfad10 src/semicongine/gpu_data.nim --- a/src/semicongine/gpu_data.nim Sun Apr 02 01:22:09 2023 +0700 +++ b/src/semicongine/gpu_data.nim Mon Apr 03 00:06:24 2023 +0700 @@ -1,3 +1,4 @@ +import std/sequtils import std/typetraits import std/strformat import std/tables @@ -28,6 +29,9 @@ AttributeGroup* = object attributes*: seq[Attribute] +func initAttributeGroup*(attrs: varargs[Attribute]): auto = + AttributeGroup(attributes: attrs.toSeq) + func vertexInputs*(group: AttributeGroup): seq[Attribute] = for attr in group.attributes: if attr.perInstance == false: diff -r 7b695fb335ed -r 056e08dfad10 src/semicongine/mesh.nim --- a/src/semicongine/mesh.nim Sun Apr 02 01:22:09 2023 +0700 +++ b/src/semicongine/mesh.nim Mon Apr 03 00:06:24 2023 +0700 @@ -41,29 +41,35 @@ method `$`*(mesh: Mesh): string = &"Mesh ({mesh.vertexCount})" -func newMesh*(vertices: openArray[Vec3f]): auto = - let meshdata = {asAttribute(default(Vec3f), "position"): MeshData(thetype: Position, position: vertices.toSeq)}.toTable - Mesh(vertexCount: uint32(vertices.len), data: meshdata, indexType: None) +func initMesh*(positions: openArray[Vec3f], colors: openArray[Vec3f]=[]): Mesh = + assert colors.len == 0 or colors.len == positions.len + result = new Mesh + result.vertexCount = uint32(positions.len) + result.indexType = None + result.data[asAttribute(default(Vec3f), "position")] = MeshData(thetype: Position, position: positions.toSeq) + if colors.len > 0: + result.data[asAttribute(default(Vec3f), "color")] = MeshData(thetype: Color, color: colors.toSeq) -func newMesh*(vertices: openArray[Vec3f], indices: openArray[array[3, uint32|int32]]): auto = - let meshdata = {asAttribute(default(Vec3f), "position"): MeshData(thetype: Position, position: vertices.toSeq)}.toTable - if uint16(vertices.len) < high(uint16): + +func initMesh*(positions: openArray[Vec3f], indices: openArray[array[3, uint32|int32]]): auto = + let meshdata = {asAttribute(default(Vec3f), "position"): MeshData(thetype: Position, position: positions.toSeq)}.toTable + if uint16(positions.len) < high(uint16): var smallIndices = newSeq[array[3, uint16]](indices.len) for i, tri in enumerate(indices): smallIndices[i] = [uint16(tri[0]), uint16(tri[1]), uint16(tri[3])] - Mesh(vertexCount: uint32(vertices.len), data: meshdata, indexType: Small, smallIndices: smallIndices) + Mesh(vertexCount: uint32(positions.len), data: meshdata, indexType: Small, smallIndices: smallIndices) else: var bigIndices = newSeq[array[3, uint32]](indices.len) for i, tri in enumerate(indices): bigIndices[i] = [uint32(tri[0]), uint32(tri[1]), uint32(tri[3])] - Mesh(vertexCount: uint32(vertices.len), data: meshdata, indexType: Big, bigIndices: bigIndices) + Mesh(vertexCount: uint32(positions.len), data: meshdata, indexType: Big, bigIndices: bigIndices) -func newMesh*(vertices: openArray[Vec3f], indices: openArray[array[3, uint16|int16]]): auto = - let meshdata = {asAttribute(default(Vec3f), "position"): MeshData(thetype: Position, position: vertices.toSeq)}.toTable +func initMesh*(positions: openArray[Vec3f], indices: openArray[array[3, uint16|int16]]): auto = + let meshdata = {asAttribute(default(Vec3f), "position"): MeshData(thetype: Position, position: positions.toSeq)}.toTable var smallIndices = newSeq[array[3, uint16]](indices.len) for i, tri in enumerate(indices): smallIndices[i] = [uint16(tri[0]), uint16(tri[1]), uint16(tri[3])] - Mesh(vertexCount: vertices.len, data: meshdata, indexType: Small, smallIndices: smallIndices) + Mesh(vertexCount: positions.len, data: meshdata, indexType: Small, smallIndices: smallIndices) func size*(meshdata: MeshData): uint64 = @@ -85,7 +91,7 @@ result += d.size proc rawData[T: seq](value: var T): (pointer, uint64) = - (pointer(addr(value)), uint64(sizeof(get(genericParams(typeof(value)), 0)) * value.len)) + (pointer(addr(value[0])), uint64(sizeof(get(genericParams(typeof(value)), 0)) * value.len)) proc getRawData(data: var MeshData): (pointer, uint64) = case data.thetype: diff -r 7b695fb335ed -r 056e08dfad10 src/semicongine/scene.nim --- a/src/semicongine/scene.nim Sun Apr 02 01:22:09 2023 +0700 +++ b/src/semicongine/scene.nim Mon Apr 03 00:06:24 2023 +0700 @@ -11,7 +11,8 @@ type Drawable* = object - buffers*: seq[(Buffer, uint64)] # buffer + offset from buffer + buffer*: Buffer # buffer + offsets*: seq[uint64] # offsets from buffer elementCount*: uint32 # number of vertices or indices instanceCount*: uint32 # number of instance case indexed*: bool @@ -28,14 +29,20 @@ func `$`*(drawable: Drawable): string = if drawable.indexed: - &"Drawable(elementCount: {drawable.elementCount}, instanceCount: {drawable.instanceCount}, buffers: {drawable.buffers}, indexType: {drawable.indexType})" + &"Drawable(elementCount: {drawable.elementCount}, instanceCount: {drawable.instanceCount}, buffer: {drawable.buffer}, offsets: {drawable.offsets}, indexType: {drawable.indexType})" else: - &"Drawable(elementCount: {drawable.elementCount}, instanceCount: {drawable.instanceCount}, buffers: {drawable.buffers})" + &"Drawable(elementCount: {drawable.elementCount}, instanceCount: {drawable.instanceCount}, buffer: {drawable.buffer}, offsets: {drawable.offsets})" + +proc destroy(drawable: var Drawable) = + drawable.buffer.destroy() + if drawable.indexed: + drawable.indexBuffer.destroy() proc setupDrawables(scene: var Scene, pipeline: Pipeline) = assert pipeline.device.vk.valid - assert not (pipeline.vk in scene.drawables) - + if pipeline.vk in scene.drawables: + for drawable in scene.drawables[pipeline.vk].mitems: + drawable.destroy() scene.drawables[pipeline.vk] = @[] var @@ -63,9 +70,9 @@ memoryFlags=[VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT], ) var offset = 0'u64 - var drawable = Drawable(elementCount: vertexCount, indexed: false, instanceCount: 1) + var drawable = Drawable(elementCount: vertexCount, buffer: buffer, indexed: false, instanceCount: 1) for inputAttr in pipeline.inputs.vertexInputs: - drawable.buffers.add (buffer, offset) + drawable.offsets.add offset for mesh in nonIMeshes: var (pdata, size) = mesh.getRawData(inputAttr) buffer.setData(pdata, size, offset) @@ -110,8 +117,4 @@ proc destroy*(scene: var Scene) = for drawables in scene.drawables.mvalues: for drawable in drawables.mitems: - for (buffer, offset) in drawable.buffers.mitems: - # if buffer.vk.valid: # required because we allow duplicates in drawable.buffers - buffer.destroy() - if drawable.indexed: - drawable.indexBuffer.destroy() + drawable.destroy() diff -r 7b695fb335ed -r 056e08dfad10 src/semicongine/vulkan/buffer.nim --- a/src/semicongine/vulkan/buffer.nim Sun Apr 02 01:22:09 2023 +0700 +++ b/src/semicongine/vulkan/buffer.nim Mon Apr 03 00:06:24 2023 +0700 @@ -118,4 +118,4 @@ assert buffer.memory.vk.valid buffer.memory.free buffer.device.vk.vkDestroyBuffer(buffer.vk, nil) - buffer.vk.reset() + buffer = default(Buffer) diff -r 7b695fb335ed -r 056e08dfad10 src/semicongine/vulkan/instance.nim --- a/src/semicongine/vulkan/instance.nim Sun Apr 02 01:22:09 2023 +0700 +++ b/src/semicongine/vulkan/instance.nim Mon Apr 03 00:06:24 2023 +0700 @@ -106,6 +106,8 @@ ): VkBool32 {.cdecl.} = log LEVEL_MAPPING[messageSeverity], &"{toEnums messageTypes}: {pCallbackData.pMessage}" + if messageSeverity == VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + echo getStackTrace() return false proc createDebugMessenger*( diff -r 7b695fb335ed -r 056e08dfad10 src/semicongine/vulkan/memory.nim --- a/src/semicongine/vulkan/memory.nim Sun Apr 02 01:22:09 2023 +0700 +++ b/src/semicongine/vulkan/memory.nim Mon Apr 03 00:06:24 2023 +0700 @@ -91,4 +91,4 @@ assert memory.vk.valid memory.device.vk.vkFreeMemory(memory.vk, nil) - memory.vk.reset + memory = default(DeviceMemory) diff -r 7b695fb335ed -r 056e08dfad10 src/semicongine/vulkan/pipeline.nim --- a/src/semicongine/vulkan/pipeline.nim Sun Apr 02 01:22:09 2023 +0700 +++ b/src/semicongine/vulkan/pipeline.nim Mon Apr 03 00:06:24 2023 +0700 @@ -2,6 +2,7 @@ import ./device import ./descriptor import ./shader +import ./utils import ../gpu_data @@ -20,6 +21,137 @@ if shader.stage == VK_SHADER_STAGE_VERTEX_BIT: return shader.inputs +proc createPipeline*(device: Device, renderPass: VkRenderPass, vertexShader: Shader, fragmentShader: Shader, inFlightFrames: int, subpass = 0'u32): Pipeline = + assert renderPass.valid + assert device.vk.valid + assert vertexShader.stage == VK_SHADER_STAGE_VERTEX_BIT + assert fragmentShader.stage == VK_SHADER_STAGE_FRAGMENT_BIT + + result.device = device + result.shaders = @[vertexShader, fragmentShader] + + var descriptors = @[Descriptor( + thetype: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + count: 1, + stages: @[VK_SHADER_STAGE_VERTEX_BIT], + itemsize: vertexShader.uniforms.size(), + )] + if vertexShader.uniforms == fragmentShader.uniforms: + descriptors[0].stages.add VK_SHADER_STAGE_FRAGMENT_BIT + else: + descriptors.add Descriptor( + thetype: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + count: 1, + stages: @[VK_SHADER_STAGE_FRAGMENT_BIT], + itemsize: fragmentShader.uniforms.size(), + ) + result.descriptorSetLayout = device.createDescriptorSetLayout(descriptors) + + # TODO: Push constants + # var pushConstant = VkPushConstantRange( + # stageFlags: toBits shaderStage, + # offset: 0, + # size: 0, + # ) + var descriptorSetLayouts: seq[VkDescriptorSetLayout] = @[result.descriptorSetLayout.vk] + # var pushConstants: seq[VkPushConstantRange] = @[pushConstant] + var pipelineLayoutInfo = VkPipelineLayoutCreateInfo( + sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + setLayoutCount: uint32(descriptorSetLayouts.len), + pSetLayouts: descriptorSetLayouts.toCPointer, + # pushConstantRangeCount: uint32(pushConstants.len), + # pPushConstantRanges: pushConstants.toCPointer, + ) + checkVkResult vkCreatePipelineLayout(device.vk, addr(pipelineLayoutInfo), nil, addr(result.layout)) + + var + bindings: seq[VkVertexInputBindingDescription] + attributes: seq[VkVertexInputAttributeDescription] + vertexInputInfo = vertexShader.getVertexInputInfo(bindings, attributes) + inputAssembly = VkPipelineInputAssemblyStateCreateInfo( + sType: VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + topology: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + primitiveRestartEnable: VK_FALSE, + ) + viewportState = VkPipelineViewportStateCreateInfo( + sType: VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + viewportCount: 1, + scissorCount: 1, + ) + rasterizer = VkPipelineRasterizationStateCreateInfo( + sType: VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + depthClampEnable: VK_FALSE, + rasterizerDiscardEnable: VK_FALSE, + polygonMode: VK_POLYGON_MODE_FILL, + lineWidth: 1.0, + cullMode: toBits [VK_CULL_MODE_BACK_BIT], + frontFace: VK_FRONT_FACE_CLOCKWISE, + depthBiasEnable: VK_FALSE, + depthBiasConstantFactor: 0.0, + depthBiasClamp: 0.0, + depthBiasSlopeFactor: 0.0, + ) + multisampling = VkPipelineMultisampleStateCreateInfo( + sType: VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + sampleShadingEnable: VK_FALSE, + rasterizationSamples: VK_SAMPLE_COUNT_1_BIT, + minSampleShading: 1.0, + pSampleMask: nil, + alphaToCoverageEnable: VK_FALSE, + alphaToOneEnable: VK_FALSE, + ) + colorBlendAttachment = VkPipelineColorBlendAttachmentState( + colorWriteMask: toBits [VK_COLOR_COMPONENT_R_BIT, VK_COLOR_COMPONENT_G_BIT, VK_COLOR_COMPONENT_B_BIT, VK_COLOR_COMPONENT_A_BIT], + blendEnable: VK_TRUE, + srcColorBlendFactor: VK_BLEND_FACTOR_SRC_ALPHA, + dstColorBlendFactor: VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, + colorBlendOp: VK_BLEND_OP_ADD, + srcAlphaBlendFactor: VK_BLEND_FACTOR_ONE, + dstAlphaBlendFactor: VK_BLEND_FACTOR_ZERO, + alphaBlendOp: VK_BLEND_OP_ADD, + ) + colorBlending = VkPipelineColorBlendStateCreateInfo( + sType: VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + logicOpEnable: false, + attachmentCount: 1, + pAttachments: addr(colorBlendAttachment), + ) + dynamicStates = @[VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR] + dynamicState = VkPipelineDynamicStateCreateInfo( + sType: VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + dynamicStateCount: uint32(dynamicStates.len), + pDynamicStates: dynamicStates.toCPointer, + ) + stages = @[vertexShader.getPipelineInfo(), fragmentShader.getPipelineInfo()] + createInfo = VkGraphicsPipelineCreateInfo( + sType: VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + stageCount: uint32(stages.len), + pStages: stages.toCPointer, + pVertexInputState: addr(vertexInputInfo), + pInputAssemblyState: addr(inputAssembly), + pViewportState: addr(viewportState), + pRasterizationState: addr(rasterizer), + pMultisampleState: addr(multisampling), + pDepthStencilState: nil, + pColorBlendState: addr(colorBlending), + pDynamicState: addr(dynamicState), + layout: result.layout, + renderPass: renderPass, + subpass: subpass, + basePipelineHandle: VkPipeline(0), + basePipelineIndex: -1, + ) + checkVkResult vkCreateGraphicsPipelines( + device.vk, + VkPipelineCache(0), + 1, + addr(createInfo), + nil, + addr(result.vk) + ) + result.descriptorPool = result.device.createDescriptorSetPool(@[(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1'u32)]) + result.descriptorSets = result.descriptorPool.allocateDescriptorSet(result.descriptorSetLayout, inFlightFrames) + proc destroy*(pipeline: var Pipeline) = assert pipeline.device.vk.valid assert pipeline.vk.valid diff -r 7b695fb335ed -r 056e08dfad10 src/semicongine/vulkan/renderpass.nim --- a/src/semicongine/vulkan/renderpass.nim Sun Apr 02 01:22:09 2023 +0700 +++ b/src/semicongine/vulkan/renderpass.nim Mon Apr 03 00:06:24 2023 +0700 @@ -5,8 +5,6 @@ import ./device import ./pipeline import ./shader -import ./descriptor -import ../gpu_data import ../math @@ -68,137 +66,6 @@ result.subpasses = pSubpasses checkVkResult device.vk.vkCreateRenderPass(addr(createInfo), nil, addr(result.vk)) -proc attachPipeline(renderPass: var RenderPass, vertexShader: Shader, fragmentShader: Shader, subpass = 0'u32) = - assert renderPass.vk.valid - assert renderPass.device.vk.valid - assert vertexShader.stage == VK_SHADER_STAGE_VERTEX_BIT - assert fragmentShader.stage == VK_SHADER_STAGE_FRAGMENT_BIT - - var pipeline = Pipeline(device: renderPass.device, shaders: @[vertexShader, fragmentShader]) - - var descriptors = @[Descriptor( - thetype: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - count: 1, - stages: @[VK_SHADER_STAGE_VERTEX_BIT], - itemsize: vertexShader.uniforms.size(), - )] - if vertexShader.uniforms == fragmentShader.uniforms: - descriptors[0].stages.add VK_SHADER_STAGE_FRAGMENT_BIT - else: - descriptors.add Descriptor( - thetype: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - count: 1, - stages: @[VK_SHADER_STAGE_FRAGMENT_BIT], - itemsize: fragmentShader.uniforms.size(), - ) - pipeline.descriptorSetLayout = renderPass.device.createDescriptorSetLayout(descriptors) - - # TODO: Push constants - # var pushConstant = VkPushConstantRange( - # stageFlags: toBits shaderStage, - # offset: 0, - # size: 0, - # ) - var descriptorSetLayouts: seq[VkDescriptorSetLayout] = @[pipeline.descriptorSetLayout.vk] - # var pushConstants: seq[VkPushConstantRange] = @[pushConstant] - var pipelineLayoutInfo = VkPipelineLayoutCreateInfo( - sType: VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, - setLayoutCount: uint32(descriptorSetLayouts.len), - pSetLayouts: descriptorSetLayouts.toCPointer, - # pushConstantRangeCount: uint32(pushConstants.len), - # pPushConstantRanges: pushConstants.toCPointer, - ) - checkVkResult vkCreatePipelineLayout(renderPass.device.vk, addr(pipelineLayoutInfo), nil, addr(pipeline.layout)) - - var - bindings: seq[VkVertexInputBindingDescription] - attributes: seq[VkVertexInputAttributeDescription] - vertexInputInfo = vertexShader.getVertexInputInfo(bindings, attributes) - inputAssembly = VkPipelineInputAssemblyStateCreateInfo( - sType: VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, - topology: VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, - primitiveRestartEnable: VK_FALSE, - ) - viewportState = VkPipelineViewportStateCreateInfo( - sType: VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, - viewportCount: 1, - scissorCount: 1, - ) - rasterizer = VkPipelineRasterizationStateCreateInfo( - sType: VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, - depthClampEnable: VK_FALSE, - rasterizerDiscardEnable: VK_FALSE, - polygonMode: VK_POLYGON_MODE_FILL, - lineWidth: 1.0, - cullMode: toBits [VK_CULL_MODE_BACK_BIT], - frontFace: VK_FRONT_FACE_CLOCKWISE, - depthBiasEnable: VK_FALSE, - depthBiasConstantFactor: 0.0, - depthBiasClamp: 0.0, - depthBiasSlopeFactor: 0.0, - ) - multisampling = VkPipelineMultisampleStateCreateInfo( - sType: VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, - sampleShadingEnable: VK_FALSE, - rasterizationSamples: VK_SAMPLE_COUNT_1_BIT, - minSampleShading: 1.0, - pSampleMask: nil, - alphaToCoverageEnable: VK_FALSE, - alphaToOneEnable: VK_FALSE, - ) - colorBlendAttachment = VkPipelineColorBlendAttachmentState( - colorWriteMask: toBits [VK_COLOR_COMPONENT_R_BIT, VK_COLOR_COMPONENT_G_BIT, VK_COLOR_COMPONENT_B_BIT, VK_COLOR_COMPONENT_A_BIT], - blendEnable: VK_TRUE, - srcColorBlendFactor: VK_BLEND_FACTOR_SRC_ALPHA, - dstColorBlendFactor: VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, - colorBlendOp: VK_BLEND_OP_ADD, - srcAlphaBlendFactor: VK_BLEND_FACTOR_ONE, - dstAlphaBlendFactor: VK_BLEND_FACTOR_ZERO, - alphaBlendOp: VK_BLEND_OP_ADD, - ) - colorBlending = VkPipelineColorBlendStateCreateInfo( - sType: VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, - logicOpEnable: false, - attachmentCount: 1, - pAttachments: addr(colorBlendAttachment), - ) - dynamicStates = @[VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR] - dynamicState = VkPipelineDynamicStateCreateInfo( - sType: VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, - dynamicStateCount: uint32(dynamicStates.len), - pDynamicStates: dynamicStates.toCPointer, - ) - stages = @[vertexShader.getPipelineInfo(), fragmentShader.getPipelineInfo()] - createInfo = VkGraphicsPipelineCreateInfo( - sType: VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, - stageCount: uint32(stages.len), - pStages: stages.toCPointer, - pVertexInputState: addr(vertexInputInfo), - pInputAssemblyState: addr(inputAssembly), - pViewportState: addr(viewportState), - pRasterizationState: addr(rasterizer), - pMultisampleState: addr(multisampling), - pDepthStencilState: nil, - pColorBlendState: addr(colorBlending), - pDynamicState: addr(dynamicState), - layout: pipeline.layout, - renderPass: renderPass.vk, - subpass: subpass, - basePipelineHandle: VkPipeline(0), - basePipelineIndex: -1, - ) - checkVkResult vkCreateGraphicsPipelines( - renderPass.device.vk, - VkPipelineCache(0), - 1, - addr(createInfo), - nil, - addr(pipeline.vk) - ) - pipeline.descriptorPool = pipeline.device.createDescriptorSetPool(@[(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1'u32)]) - pipeline.descriptorSets = pipeline.descriptorPool.allocateDescriptorSet(pipeline.descriptorSetLayout, renderPass.inFlightFrames) - renderPass.subpasses[subpass].pipelines.add pipeline - proc simpleForwardRenderPass*(device: Device, format: VkFormat, vertexShader: Shader, fragmentShader: Shader, inFlightFrames: int, clearColor=Vec4f([0.8'f32, 0.8'f32, 0.8'f32, 1'f32])): RenderPass = assert device.vk.valid var @@ -229,7 +96,7 @@ dstAccessMask: toBits [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT], )] result = device.createRenderPass(attachments=attachments, subpasses=subpasses, dependencies=dependencies, inFlightFrames=inFlightFrames) - result.attachPipeline(vertexShader, fragmentShader, 0) + result.subpasses[0].pipelines.add device.createPipeline(result.vk, vertexShader, fragmentShader, inFlightFrames, 0) proc destroy*(renderPass: var RenderPass) = assert renderPass.device.vk.valid diff -r 7b695fb335ed -r 056e08dfad10 src/semicongine/vulkan/shader.nim --- a/src/semicongine/vulkan/shader.nim Sun Apr 02 01:22:09 2023 +0700 +++ b/src/semicongine/vulkan/shader.nim Mon Apr 03 00:06:24 2023 +0700 @@ -13,22 +13,31 @@ import ../gpu_data +const DEFAULT_SHADER_VERSION = 450 +const DEFAULT_SHADER_ENTRYPOINT = "main" + let logger = newConsoleLogger() addHandler(logger) type + ShaderCode = object + stage: VkShaderStageFlagBits + entrypoint: string + binary: seq[uint32] + inputs: AttributeGroup + uniforms: AttributeGroup + outputs: AttributeGroup Shader* = object device: Device + vk*: VkShaderModule stage*: VkShaderStageFlagBits - vk*: VkShaderModule entrypoint*: string inputs*: AttributeGroup uniforms*: AttributeGroup outputs*: AttributeGroup -proc compileGLSLToSPIRV*(stage: VkShaderStageFlagBits, shaderSource: string, entrypoint: string): seq[uint32] {.compileTime.} = - +proc compileGlslToSPIRV(stage: VkShaderStageFlagBits, shaderSource: string, entrypoint: string): seq[uint32] {.compileTime.} = func stage2string(stage: VkShaderStageFlagBits): string {.compileTime.} = case stage of VK_SHADER_STAGE_VERTEX_BIT: "vert" @@ -75,56 +84,56 @@ i += 4 -proc shaderCode*( - inputs: AttributeGroup, - uniforms: AttributeGroup, - outputs: AttributeGroup, +proc compileGlslShader*( stage: VkShaderStageFlagBits, - version: int, - entrypoint: string, + inputs=AttributeGroup(), + uniforms=AttributeGroup(), + outputs=AttributeGroup(), + version=DEFAULT_SHADER_VERSION , + entrypoint=DEFAULT_SHADER_ENTRYPOINT , body: seq[string] -): seq[uint32] {.compileTime.} = +): ShaderCode {.compileTime.} = var code = @[&"#version {version}", ""] & - inputs.glslInput() & @[""] & - uniforms.glslUniforms() & @[""] & - outputs.glslOutput() & @[""] & + (if inputs.attributes.len > 0: inputs.glslInput() & @[""] else: @[]) & + (if uniforms.attributes.len > 0: uniforms.glslUniforms() & @[""] else: @[]) & + (if outputs.attributes.len > 0: outputs.glslOutput() & @[""] else: @[]) & @[&"void {entrypoint}(){{"] & body & @[&"}}"] - compileGLSLToSPIRV(stage, code.join("\n"), entrypoint) - - -proc shaderCode*( - inputs: AttributeGroup, - uniforms: AttributeGroup, - outputs: AttributeGroup, - stage: VkShaderStageFlagBits, - version: int, - entrypoint: string, - body: string -): seq[uint32] {.compileTime.} = - return shaderCode(inputs, uniforms, outputs, stage, version, entrypoint, @[body]) - - -proc createShader*( - device: Device, - inputs: AttributeGroup, - uniforms: AttributeGroup, - outputs: AttributeGroup, - stage: VkShaderStageFlagBits, - entrypoint: string, - binary: seq[uint32] -): Shader = - assert device.vk.valid - assert len(binary) > 0 - - result.device = device result.inputs = inputs result.uniforms = uniforms result.outputs = outputs result.entrypoint = entrypoint result.stage = stage - var bin = binary + result.binary = compileGlslToSPIRV(stage, code.join("\n"), entrypoint) + + +proc compileGlslShader*( + stage: VkShaderStageFlagBits, + inputs: AttributeGroup=AttributeGroup(), + uniforms: AttributeGroup=AttributeGroup(), + outputs: AttributeGroup=AttributeGroup(), + version=DEFAULT_SHADER_VERSION , + entrypoint=DEFAULT_SHADER_ENTRYPOINT , + body: string +): ShaderCode {.compileTime.} = + return compileGlslShader(stage, inputs, uniforms, outputs, version, entrypoint, @[body]) + + +proc createShaderModule*( + device: Device, + shaderCode: ShaderCode, +): Shader = + assert device.vk.valid + assert len(shaderCode.binary) > 0 + + result.device = device + result.inputs = shaderCode.inputs + result.uniforms = shaderCode.uniforms + result.outputs = shaderCode.outputs + result.entrypoint = shaderCode.entrypoint + result.stage = shaderCode.stage + var bin = shaderCode.binary var createInfo = VkShaderModuleCreateInfo( sType: VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, codeSize: uint(bin.len * sizeof(uint32)), diff -r 7b695fb335ed -r 056e08dfad10 src/semicongine/vulkan/swapchain.nim --- a/src/semicongine/vulkan/swapchain.nim Sun Apr 02 01:22:09 2023 +0700 +++ b/src/semicongine/vulkan/swapchain.nim Mon Apr 03 00:06:24 2023 +0700 @@ -160,8 +160,8 @@ debug "Draw ", drawable var buffers: seq[VkBuffer] var offsets: seq[VkDeviceSize] - for (buffer, offset) in drawable.buffers: - buffers.add buffer.vk + for offset in drawable.offsets: + buffers.add drawable.buffer.vk offsets.add VkDeviceSize(offset) commandBuffer.vkCmdBindVertexBuffers( firstBinding=0'u32, diff -r 7b695fb335ed -r 056e08dfad10 tests/test_vulkan_wrapper.nim --- a/tests/test_vulkan_wrapper.nim Sun Apr 02 01:22:09 2023 +0700 +++ b/tests/test_vulkan_wrapper.nim Mon Apr 03 00:06:24 2023 +0700 @@ -45,7 +45,7 @@ var instance = thewindow.createInstance( vulkanVersion=VK_MAKE_API_VERSION(0, 1, 3, 0), instanceExtensions= @["VK_EXT_debug_utils"], - layers= @["VK_LAYER_KHRONOS_validation"] + layers= @["VK_LAYER_KHRONOS_validation", "VK_LAYER_MESA_overlay"] ) var debugger = instance.createDebugMessenger() @@ -58,45 +58,64 @@ selectedPhysicalDevice.filterForGraphicsPresentationQueues() ) - const inputs = AttributeGroup(attributes: @[attr(name="position", thetype=Float32, components=3)]) - const uniforms = AttributeGroup() - const outputs = AttributeGroup(attributes: @[attr(name="fragpos", thetype=Float32, components=3)]) - const fragOutput = AttributeGroup(attributes: @[attr(name="color", thetype=Float32, components=4)]) - const vertexBinary = shaderCode(inputs=inputs, uniforms=uniforms, outputs=outputs, stage=VK_SHADER_STAGE_VERTEX_BIT, version=450, entrypoint="main", "fragpos = position;") - const fragmentBinary = shaderCode(inputs=outputs, uniforms=uniforms, outputs=fragOutput, stage=VK_SHADER_STAGE_FRAGMENT_BIT, version=450, entrypoint="main", "color = vec4(1, 1, 1, 1);") + const + vertexInput = initAttributeGroup( + asAttribute(default(Vec3f), "position"), + asAttribute(default(Vec3f), "color"), + ) + vertexOutput = initAttributeGroup(asAttribute(default(Vec3f), "outcolor")) + fragOutput = initAttributeGroup(asAttribute(default(Vec4f), "color")) + vertexCode = compileGlslShader( + stage=VK_SHADER_STAGE_VERTEX_BIT, + inputs=vertexInput, + outputs=vertexOutput, + body="""gl_Position = vec4(position, 1.0); outcolor = color;""" + ) + fragmentCode = compileGlslShader( + stage=VK_SHADER_STAGE_FRAGMENT_BIT, + inputs=vertexOutput, + outputs=fragOutput, + body="color = vec4(outcolor, 1);" + ) var - vertexshader = device.createShader(inputs, uniforms, outputs, VK_SHADER_STAGE_VERTEX_BIT, "main", vertexBinary) - fragmentshader = device.createShader(inputs, uniforms, outputs, VK_SHADER_STAGE_FRAGMENT_BIT, "main", fragmentBinary) + vertexshader = device.createShaderModule(vertexCode) + fragmentshader = device.createShaderModule(fragmentCode) surfaceFormat = device.physicalDevice.getSurfaceFormats().filterSurfaceFormat() renderPass = device.simpleForwardRenderPass(surfaceFormat.format, vertexshader, fragmentshader, 2) - var (swapchain, res) = device.createSwapchain(renderPass, surfaceFormat, device.firstGraphicsQueue().get().family, 2) + (swapchain, res) = device.createSwapchain(renderPass, surfaceFormat, device.firstGraphicsQueue().get().family, 2) if res != VK_SUCCESS: raise newException(Exception, "Unable to create swapchain") var thescene = Scene( name: "main", root: newEntity("root", - newEntity("triangle1", newMesh([newVec3f(-0.5, -0.5), newVec3f(0.5, 0.5), newVec3f(0.5, -0.5)])), - newEntity("triangle2", newMesh([newVec3f(-0.5, -0.5), newVec3f(0.5, -0.5), newVec3f(0.5, 0.5)])), + newEntity("triangle1", initMesh( + positions=[newVec3f(0.0, -0.5), newVec3f(0.5, 0.5), newVec3f(-0.5, 0.5)], + colors=[newVec3f(1.0, 0.0, 0.0), newVec3f(0.0, 1.0, 0.0), newVec3f(0.0, 0.0, 1.0)], + )), ) ) thescene.setupDrawables(renderPass) echo "Setup successfull, start rendering" - for i in 0 ..< 1: + for i in 0 ..< 1000: discard swapchain.drawScene(thescene) echo "Rendered ", swapchain.framesRendered, " frames" + checkVkResult device.vk.vkDeviceWaitIdle() + + # cleanup echo "Start cleanup" + # logical + thescene.destroy() - # cleanup - checkVkResult device.vk.vkDeviceWaitIdle() - thescene.destroy() + # rendering objects vertexshader.destroy() fragmentshader.destroy() renderPass.destroy() swapchain.destroy() + + # global objects device.destroy() - debugger.destroy() instance.destroy()