# HG changeset patch # User sam # Date 1722011964 -25200 # Node ID c4f98eb4bb0541e64723c589956a5434ce30b4bf # Parent 01e9f41d35b1ed227d63aeb0cf7252578f81a3fb fix: a few things diff -r 01e9f41d35b1 -r c4f98eb4bb05 semiconginev2/core/matrix.nim --- a/semiconginev2/core/matrix.nim Fri Jul 26 23:04:01 2024 +0700 +++ b/semiconginev2/core/matrix.nim Fri Jul 26 23:39:24 2024 +0700 @@ -103,7 +103,7 @@ elif m is TMat4: 16 -func toString[T: TMat](value: T): string = +func toMatString[T: TMat](value: T): string = var strvalues: seq[string] maxwidth = 0 @@ -123,13 +123,13 @@ result &= " " result &= filler & strvalues[i] & " " -func `$`*(v: TMat2[SomeNumber]): string = toString[TMat2[SomeNumber]](v) -func `$`*(v: TMat23[SomeNumber]): string = toString[TMat23[SomeNumber]](v) -func `$`*(v: TMat32[SomeNumber]): string = toString[TMat32[SomeNumber]](v) -func `$`*(v: TMat3[SomeNumber]): string = toString[TMat3[SomeNumber]](v) -func `$`*(v: TMat34[SomeNumber]): string = toString[TMat34[SomeNumber]](v) -func `$`*(v: TMat43[SomeNumber]): string = toString[TMat43[SomeNumber]](v) -func `$`*(v: TMat4[SomeNumber]): string = toString[TMat4[SomeNumber]](v) +func `$`*(v: TMat2[SomeNumber]): string = toMatString[TMat2[SomeNumber]](v) +func `$`*(v: TMat23[SomeNumber]): string = toMatString[TMat23[SomeNumber]](v) +func `$`*(v: TMat32[SomeNumber]): string = toMatString[TMat32[SomeNumber]](v) +func `$`*(v: TMat3[SomeNumber]): string = toMatString[TMat3[SomeNumber]](v) +func `$`*(v: TMat34[SomeNumber]): string = toMatString[TMat34[SomeNumber]](v) +func `$`*(v: TMat43[SomeNumber]): string = toMatString[TMat43[SomeNumber]](v) +func `$`*(v: TMat4[SomeNumber]): string = toMatString[TMat4[SomeNumber]](v) func `[]`*[T: TMat](m: T, row, col: int): auto = m.data[col + row * T.ColumnCount] func `[]=`*[T: TMat, U](m: var T, row, col: int, value: U) = m.data[col + row * T.ColumnCount] = value diff -r 01e9f41d35b1 -r c4f98eb4bb05 semiconginev2/core/vector.nim --- a/semiconginev2/core/vector.nim Fri Jul 26 23:04:01 2024 +0700 +++ b/semiconginev2/core/vector.nim Fri Jul 26 23:39:24 2024 +0700 @@ -102,16 +102,16 @@ func To*[T](v: TVec3): auto = TVec3([T(v[0]), T(v[1]), T(v[2])]) func To*[T](v: TVec4): auto = TVec4([T(v[0]), T(v[1]), T(v[2]), T(v[3])]) -func toString[T: TVec](value: T): string = +func toVecString[T: TVec](value: T): string = var items: seq[string] for item in value: items.add(&"{item.float:.5f}") & "(" & join(items, " ") & ")" -func `$`*(v: TVec1[SomeNumber]): string = toString[TVec1[SomeNumber]](v) -func `$`*(v: TVec2[SomeNumber]): string = toString[TVec2[SomeNumber]](v) -func `$`*(v: TVec3[SomeNumber]): string = toString[TVec3[SomeNumber]](v) -func `$`*(v: TVec4[SomeNumber]): string = toString[TVec4[SomeNumber]](v) +func `$`*(v: TVec1[SomeNumber]): string = toVecString[TVec1[SomeNumber]](v) +func `$`*(v: TVec2[SomeNumber]): string = toVecString[TVec2[SomeNumber]](v) +func `$`*(v: TVec3[SomeNumber]): string = toVecString[TVec3[SomeNumber]](v) +func `$`*(v: TVec4[SomeNumber]): string = toVecString[TVec4[SomeNumber]](v) func Length*(vec: TVec1): auto = vec[0] func Length*(vec: TVec2[SomeFloat]): auto = sqrt(vec[0] * vec[0] + vec[1] * vec[1]) diff -r 01e9f41d35b1 -r c4f98eb4bb05 semiconginev2/gltf.nim --- a/semiconginev2/gltf.nim Fri Jul 26 23:04:01 2024 +0700 +++ b/semiconginev2/gltf.nim Fri Jul 26 23:39:24 2024 +0700 @@ -233,31 +233,32 @@ if "matrix" in node: for i in 0 ..< node["matrix"].len: result.transform[i] = node["matrix"][i].getFloat() + result.transform = result.transform.Transposed() + else: + var (t, r, s) = (Unit4, Unit4, Unit4) + if "translation" in node: + t = Translate( + float32(node["translation"][0].getFloat()), + float32(node["translation"][1].getFloat()), + float32(node["translation"][2].getFloat()) + ) + if "rotation" in node: + t = Rotate( + float32(node["rotation"][3].getFloat()), + NewVec3f( + float32(node["rotation"][0].getFloat()), + float32(node["rotation"][1].getFloat()), + float32(node["rotation"][2].getFloat()) + ) + ) + if "scale" in node: + t = Scale( + float32(node["scale"][0].getFloat()), + float32(node["scale"][1].getFloat()), + float32(node["scale"][2].getFloat()) + ) - var (t, r, s) = (Unit4, Unit4, Unit4) - if "translation" in node: - t = Translate( - float32(node["translation"][0].getFloat()), - float32(node["translation"][1].getFloat()), - float32(node["translation"][2].getFloat()) - ) - if "rotation" in node: - t = Rotate( - float32(node["rotation"][3].getFloat()), - NewVec3f( - float32(node["rotation"][0].getFloat()), - float32(node["rotation"][1].getFloat()), - float32(node["rotation"][2].getFloat()) - ) - ) - if "scale" in node: - t = Scale( - float32(node["scale"][0].getFloat()), - float32(node["scale"][1].getFloat()), - float32(node["scale"][2].getFloat()) - ) - - result.transform = t * r * s * result.transform + result.transform = t * r * s proc ReadglTF*[TMesh, TMaterial]( stream: Stream, diff -r 01e9f41d35b1 -r c4f98eb4bb05 semiconginev2/rendering.nim --- a/semiconginev2/rendering.nim Fri Jul 26 23:04:01 2024 +0700 +++ b/semiconginev2/rendering.nim Fri Jul 26 23:39:24 2024 +0700 @@ -14,6 +14,7 @@ const MAX_DESCRIPTORSETS = 4 const SURFACE_FORMAT* = VK_FORMAT_B8G8R8A8_SRGB const DEPTH_FORMAT* = VK_FORMAT_D32_SFLOAT +const PUSH_CONSTANT_SIZE = 128 # custom pragmas to classify shader attributes template VertexAttribute* {.pragma.} diff -r 01e9f41d35b1 -r c4f98eb4bb05 semiconginev2/rendering/renderer.nim --- a/semiconginev2/rendering/renderer.nim Fri Jul 26 23:04:01 2024 +0700 +++ b/semiconginev2/rendering/renderer.nim Fri Jul 26 23:39:24 2024 +0700 @@ -670,6 +670,16 @@ ) = Render(commandBuffer, pipeline, mesh, EMPTY()) +proc assertValidPushConstantType(TShader, TPushConstant: typedesc) = + assert sizeof(TPushConstant) <= PUSH_CONSTANT_SIZE, "Push constant values must be <= 128 bytes" + var foundPushConstant = false + for fieldname, fieldvalue in default(TShader).fieldPairs(): + when hasCustomPragma(fieldvalue, PushConstantAttribute): + assert typeof(fieldvalue) is TPushConstant, "Provided push constant has not same type as declared in shader" + assert foundPushConstant == false, "More than on push constant found in shader" + foundPushConstant = true + assert foundPushConstant == true, "No push constant found in shader" + proc RenderWithPushConstant*[TShader, TMesh, TInstance, TPushConstant]( commandBuffer: VkCommandBuffer, pipeline: Pipeline[TShader], @@ -677,12 +687,13 @@ instances: TInstance, pushConstant: TPushConstant, ) = + static: assertValidPushConstantType(TShader, TPushConstant) vkCmdPushConstants( commandBuffer = commandBuffer, layout = pipeline.layout, stageFlags = VkShaderStageFlags(VK_SHADER_STAGE_ALL_GRAPHICS), offset = 0, - size = 128, + size = PUSH_CONSTANT_SIZE, pValues = addr(pushConstant) ); Render(commandBuffer, pipeline, mesh, instances) @@ -692,12 +703,13 @@ mesh: TMesh, pushConstant: TPushConstant, ) = + static: assertValidPushConstantType(TShader, TPushConstant) vkCmdPushConstants( commandBuffer = commandBuffer, layout = pipeline.layout, stageFlags = VkShaderStageFlags(VK_SHADER_STAGE_ALL_GRAPHICS), offset = 0, - size = 128, + size = PUSH_CONSTANT_SIZE, pValues = addr(pushConstant) ); Render(commandBuffer, pipeline, mesh, EMPTY()) diff -r 01e9f41d35b1 -r c4f98eb4bb05 semiconginev2/rendering/shaders.nim --- a/semiconginev2/rendering/shaders.nim Fri Jul 26 23:04:01 2024 +0700 +++ b/semiconginev2/rendering/shaders.nim Fri Jul 26 23:39:24 2024 +0700 @@ -376,7 +376,7 @@ let pushConstant = VkPushConstantRange( stageFlags: VkShaderStageFlags(VK_SHADER_STAGE_ALL_GRAPHICS), offset: 0, - size: 128, # currently supported everywhere, places for two mat4 + size: PUSH_CONSTANT_SIZE, # currently supported everywhere, places for two mat4 ) let pipelineLayoutInfo = VkPipelineLayoutCreateInfo( diff -r 01e9f41d35b1 -r c4f98eb4bb05 tests/test_gltf.nim --- a/tests/test_gltf.nim Fri Jul 26 23:04:01 2024 +0700 +++ b/tests/test_gltf.nim Fri Jul 26 23:39:24 2024 +0700 @@ -11,6 +11,11 @@ var renderdata = InitRenderData() type + ObjectData = object + transform: Mat4 + Camera = object + view: Mat4 + perspective: Mat4 Material = object color: Vec4f = NewVec4f(1, 1, 1, 1) colorTexture: int32 = -1 @@ -24,7 +29,9 @@ emissiveTexture: int32 = -1 MainDescriptors = object material: GPUValue[Material, UniformBuffer] + camera: GPUValue[Camera, UniformBufferMapped] Shader = object + objectData {.PushConstantAttribute.}: ObjectData position {.VertexAttribute.}: Vec3f uv {.VertexAttribute.}: Vec2f fragmentColor {.Pass.}: Vec4f @@ -36,7 +43,7 @@ void main() { fragmentColor = vec4(1, 1, 1, 1); fragmentUv = uv; - gl_Position = vec4(position, 1); + gl_Position = vec4(position, 1) * camera.perspective * camera.view; }""" fragmentCode: string = """void main() { outColor = fragmentColor;}""" Mesh = object @@ -61,18 +68,28 @@ emissiveFactor: "emissive", ) ) + var descriptors = asDescriptorSet( + MainDescriptors( + camera: asGPUValue(Camera( + view: Unit4, + perspective: Unit4, + ), UniformBufferMapped) + ) + ) for mesh in mitems(gltfData.meshes): for primitive in mitems(mesh): renderdata.AssignBuffers(primitive[0]) - renderdata.FlushAllMemory() + renderdata.AssignBuffers(descriptors) var pipeline = CreatePipeline[Shader](renderPass = vulkan.swapchain.renderPass) + InitDescriptorSet(renderdata, pipeline.descriptorSetLayouts[0], descriptors) + renderdata.FlushAllMemory() proc drawNode(commandbuffer: VkCommandBuffer, pipeline: Pipeline, nodeId: int, transform: Mat4 = Unit4) = let nodeTransform = gltfData.nodes[nodeId].transform * transform if gltfData.nodes[nodeId].mesh >= 0: for primitive in gltfData.meshes[gltfData.nodes[nodeId].mesh]: - Render(commandbuffer = commandbuffer, pipeline = pipeline, mesh = primitive[0]) + RenderWithPushConstant(commandbuffer = commandbuffer, pipeline = pipeline, mesh = primitive[0], pushConstant = ObjectData(transform: nodeTransform)) for childNode in gltfData.nodes[nodeId].children: drawNode(commandbuffer = commandbuffer, pipeline = pipeline, nodeId = childNode, transform = nodeTransform) @@ -85,8 +102,9 @@ WithRenderPass(vulkan.swapchain.renderPass, framebuffer, commandbuffer, vulkan.swapchain.width, vulkan.swapchain.height, NewVec4f(0, 0, 0, 0)): WithPipeline(commandbuffer, pipeline): - for nodeId in gltfData.scenes[0]: - drawNode(commandbuffer = commandbuffer, pipeline = pipeline, nodeId = nodeId) + WithBind(commandbuffer, (descriptors, ), pipeline): + for nodeId in gltfData.scenes[0]: + drawNode(commandbuffer = commandbuffer, pipeline = pipeline, nodeId = nodeId) # cleanup checkVkResult vkDeviceWaitIdle(vulkan.device)