Mercurial > games > semicongine
changeset 1375:ca3299ea1bdf
did: make vector distinct from arrays, better code for compile-time handling of descriptors
author | sam <sam@basx.dev> |
---|---|
date | Sat, 07 Dec 2024 21:34:24 +0700 |
parents | 92c089136a05 |
children | aaf8fa2c7bb2 9ca552dad5fc |
files | semicongine/core/vector.nim semicongine/rendering.nim semicongine/rendering/renderer.nim semicongine/rendering/shaders.nim semicongine/text.nim tests/test_rendering.nim |
diffstat | 6 files changed, 107 insertions(+), 99 deletions(-) [+] |
line wrap: on
line diff
--- a/semicongine/core/vector.nim Fri Dec 06 22:48:25 2024 +0700 +++ b/semicongine/core/vector.nim Sat Dec 07 21:34:24 2024 +0700 @@ -84,6 +84,15 @@ func len*(v: TVec4): int = 4 +func `$`*[T](v: TVec1[T]): string = + `$`(array[1, T](v)) +func `$`*[T](v: TVec2[T]): string = + `$`(array[2, T](v)) +func `$`*[T](v: TVec3[T]): string = + `$`(array[3, T](v)) +func `$`*[T](v: TVec4[T]): string = + `$`(array[4, T](v)) + func sum*[T](v: TVec1[T]): T = sum(array[1, T](v)) func sum*[T](v: TVec2[T]): T =
--- a/semicongine/rendering.nim Fri Dec 06 22:48:25 2024 +0700 +++ b/semicongine/rendering.nim Sat Dec 07 21:34:24 2024 +0700 @@ -189,58 +189,58 @@ proc `[]=`*[T, S](a: var GPUArray[T, S], i: SomeInteger, value: T) = a.data[i] = value -template forDescriptorFields( - shader: typed, valuename, typename, countname, bindingNumber, body: untyped -): untyped = - var `bindingNumber` {.inject.} = 0'u32 - for theFieldname, `valuename` in fieldPairs(shader): - when typeof(`valuename`) is ImageObject: - block: - const `typename` {.inject.} = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER - const `countname` {.inject.} = 1'u32 - body - `bindingNumber`.inc - elif typeof(`valuename`) is GPUValue and - typeof(`valuename`).TBuffer in [UniformBuffer, UniformBufferMapped]: - block: - const `typename` {.inject.} = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER - const `countname` {.inject.} = 1'u32 - body - `bindingNumber`.inc - elif typeof(`valuename`) is GPUValue and - typeof(`valuename`).TBuffer in [StorageBuffer, StorageBufferMapped]: - block: - const `typename` {.inject.} = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER - const `countname` {.inject.} = 1'u32 - body - `bindingNumber`.inc - elif typeof(`valuename`) is array: - when elementType(`valuename`) is ImageObject: - block: - const `typename` {.inject.} = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER - const `countname` {.inject.} = uint32(typeof(`valuename`).len) - body - `bindingNumber`.inc - elif elementType(`valuename`) is GPUValue and - elementType(`valuename`).TBuffer in [UniformBuffer, UniformBufferMapped]: - block: - const `typename` {.inject.} = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER - const `countname` {.inject.} = len(`valuename`).uint32 - body - `bindingNumber`.inc - elif elementType(`valuename`) is GPUValue and - elementType(`valuename`).TBuffer in [StorageBuffer, StorageBufferMapped]: - block: - const `typename` {.inject.} = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER - const `countname` {.inject.} = len(`valuename`).uint32 - body - `bindingNumber`.inc +func getBufferType*[A, B](value: GPUValue[A, B]): BufferType {.compileTime.} = + B + +func getBufferType*[A, B]( + value: openArray[GPUValue[A, B]] +): BufferType {.compileTime.} = + B + +func getDescriptorType[T](): VkDescriptorType {.compileTIme.} = + when T is ImageObject: + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER + elif T is GPUValue: + when getBufferType(default(T)) in [UniformBuffer, UniformBufferMapped]: + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + elif getBufferType(default(T)) in [StorageBuffer, StorageBufferMapped]: + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + else: + {.error: "Unsupported descriptor type: " & typetraits.name(T).} + elif T is array: + when elementType(default(T)) is ImageObject: + VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER + elif elementType(default(T)) is GPUValue: + when getBufferType(default(elementType(default(T)))) in + [UniformBuffer, UniformBufferMapped]: + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + elif getBufferType(default(elementType(default(T)))) in + [StorageBuffer, StorageBufferMapped]: + VK_DESCRIPTOR_TYPE_STORAGE_BUFFER else: - {. - error: "Unsupported descriptor type: " & typetraits.name(typeof(`valuename`)) - .} + {.error: "Unsupported descriptor type: " & typetraits.name(T).} else: - {.error: "Unsupported descriptor type: " & typetraits.name(typeof(`valuename`)).} + {.error: "Unsupported descriptor type: " & typetraits.name(T).} + else: + {.error: "Unsupported descriptor type: " & typetraits.name(T).} + +func getDescriptorCount[T](): uint32 {.compileTIme.} = + when T is array: + len(T) + else: + 1 + +func getBindingNumber[T](field: static string): uint32 {.compileTime.} = + var c = 0'u32 + var found = false + for name, value in fieldPairs(default(T)): + when name == field: + result = c + found = true + else: + inc c + assert found, + "Field '" & field & "' of descriptor '" & typetraits.name(T) & "' not found" proc currentFiF*(): int = assert vulkan.swapchain != nil, "Swapchain has not been initialized yet"
--- a/semicongine/rendering/renderer.nim Fri Dec 06 22:48:25 2024 +0700 +++ b/semicongine/rendering/renderer.nim Sat Dec 07 21:34:24 2024 +0700 @@ -124,16 +124,17 @@ var imageWrites = newSeqOfCap[VkDescriptorImageInfo](1024) var bufferWrites = newSeqOfCap[VkDescriptorBufferInfo](1024) - forDescriptorFields( - descriptorSet.data, fieldValue, descriptorType, descriptorCount, - descriptorBindingNumber, - ): + for theFieldname, fieldvalue in fieldPairs(descriptorSet.data): + const descriptorType = getDescriptorType[typeof(fieldvalue)]() + const descriptorCount = getDescriptorCount[typeof(fieldvalue)]() + const descriptorBindingNumber = + getBindingNumber[typeof(descriptorSet.data)](theFieldname) for i in 0 ..< descriptorSet.vk.len: - when typeof(fieldValue) is GPUValue: + when typeof(fieldvalue) is GPUValue: bufferWrites.add VkDescriptorBufferInfo( - buffer: fieldValue.buffer.vk, - offset: fieldValue.offset, - range: fieldValue.size, + buffer: fieldvalue.buffer.vk, + offset: fieldvalue.offset, + range: fieldvalue.size, ) descriptorSetWrites.add VkWriteDescriptorSet( sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, @@ -145,10 +146,10 @@ pImageInfo: nil, pBufferInfo: addr(bufferWrites[^1]), ) - elif typeof(fieldValue) is ImageObject: + elif typeof(fieldvalue) is ImageObject: imageWrites.add VkDescriptorImageInfo( - sampler: fieldValue.sampler, - imageView: fieldValue.imageView, + sampler: fieldvalue.sampler, + imageView: fieldvalue.imageView, imageLayout: VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, ) descriptorSetWrites.add VkWriteDescriptorSet( @@ -161,9 +162,9 @@ pImageInfo: addr(imageWrites[^1]), pBufferInfo: nil, ) - elif typeof(fieldValue) is array: - when elementType(fieldValue) is ImageObject: - for image in fieldValue.litems: + elif typeof(fieldvalue) is array: + when elementType(fieldvalue) is ImageObject: + for image in fieldvalue.litems: imageWrites.add VkDescriptorImageInfo( sampler: image.sampler, imageView: image.imageView, @@ -179,8 +180,8 @@ pImageInfo: addr(imageWrites[^descriptorCount.int]), pBufferInfo: nil, ) - elif elementType(fieldValue) is GPUValue: - for entry in fieldValue.litems: + elif elementType(fieldvalue) is GPUValue: + for entry in fieldvalue.litems: bufferWrites.add VkDescriptorBufferInfo( buffer: entry.buffer.vk, offset: entry.offset, range: entry.size ) @@ -196,11 +197,11 @@ ) else: {. - error: "Unsupported descriptor type: " & typetraits.name(typeof(fieldValue)) + error: "Unsupported descriptor type: " & typetraits.name(typeof(fieldvalue)) .} else: {. - error: "Unsupported descriptor type: " & typetraits.name(typeof(fieldValue)) + error: "Unsupported descriptor type: " & typetraits.name(typeof(fieldvalue)) .} vkUpdateDescriptorSets(
--- a/semicongine/rendering/shaders.nim Fri Dec 06 22:48:25 2024 +0700 +++ b/semicongine/rendering/shaders.nim Sat Dec 07 21:34:24 2024 +0700 @@ -207,6 +207,12 @@ else: return 1 +func assertGPUType[T](t: T) = + assert T is SupportedGPUType, "'" & $(t) & "' is not a supported GPU type" + +func assertGPUType[T](t: openArray[T]) = + assert T is SupportedGPUType, "'" & $(t) & "' is not a supported GPU type" + proc generateShaderSource[TShader](shader: TShader): (string, string) {.compileTime.} = const GLSL_VERSION = "450" var vsInput: seq[string] @@ -268,14 +274,14 @@ descriptorBinding.inc elif typeof(descriptorValue) is GPUValue: let bufferType = - if typeof(descriptorValue).TBuffer in [UniformBuffer, UniformBufferMapped]: + if getBufferType(descriptorValue) in [UniformBuffer, UniformBufferMapped]: "uniform" else: "readonly buffer" uniforms.add "layout(set=" & $setIndex & ", binding = " & $descriptorBinding & ") " & bufferType & " T" & descriptorName & " {" when typeof(descriptorValue.data) is object: - for blockFieldName, blockFieldValue in descriptorValue.data.fieldPairs(): + for blockFieldName, blockFieldValue in fieldPairs(descriptorValue.data): when typeof(blockFieldValue) is array: assert elementType(blockFieldValue) is SupportedGPUType, bufferType & " block field '" & blockFieldName & @@ -302,23 +308,17 @@ descriptorBinding.inc elif elementType(descriptorValue) is GPUValue: let bufferType = - if typeof(descriptorValue).TBuffer in [UniformBuffer, UniformBufferMapped]: + if getBufferType(descriptorValue) in [UniformBuffer, UniformBufferMapped]: "uniform" else: "readonly buffer" uniforms.add "layout(set=" & $setIndex & ", binding = " & $descriptorBinding & ") " & bufferType & " T" & descriptorName & " {" - for blockFieldName, blockFieldValue in default(elementType(descriptorValue)).data - .fieldPairs(): - when typeof(blockFieldValue) is array: - assert elementType(blockFieldValue) is SupportedGPUType, - bufferType & " block field '" & blockFieldName & - "' is not a SupportedGPUType" - else: - assert typeof(blockFieldValue) is SupportedGPUType, - bufferType & " block field '" & blockFieldName & - "' is not a SupportedGPUType" + for blockFieldName, blockFieldValue in fieldPairs( + default(elementType(descriptorValue)).data + ): + assertGPUType(blockFieldValue) uniforms.add " " & glslType(blockFieldValue) & " " & blockFieldName & ";" uniforms.add "} " & descriptorName & "[" & $descriptorValue.len & "];" descriptorBinding.inc @@ -331,7 +331,7 @@ assert value is object, "push constants need to be objects" pushConstants.add "layout( push_constant ) uniform constants" pushConstants.add "{" - for constFieldName, constFieldValue in value.fieldPairs(): + for constFieldName, constFieldValue in fieldPairs(value): assert typeof(constFieldValue) is SupportedGPUType, "push constant field '" & constFieldName & "' is not a SupportedGPUType" pushConstants.add " " & glslType(constFieldValue) & " " & constFieldName & ";" @@ -448,13 +448,11 @@ for _, value in fieldPairs(default(TShader)): when hasCustomPragma(value, DescriptorSet): var layoutbindings: seq[VkDescriptorSetLayoutBinding] - forDescriptorFields( - value, fieldValue, descriptorType, descriptorCount, descriptorBindingNumber - ): + for theFieldname, fieldvalue in fieldPairs(value): layoutbindings.add VkDescriptorSetLayoutBinding( - binding: descriptorBindingNumber, - descriptorType: descriptorType, - descriptorCount: descriptorCount, + binding: getBindingNumber[typeof(value)](theFieldname), + descriptorType: getDescriptorType[typeof(fieldvalue)](), + descriptorCount: getDescriptorCount[typeof(fieldvalue)](), stageFlags: VkShaderStageFlags(VK_SHADER_STAGE_ALL_GRAPHICS), pImmutableSamplers: nil, )
--- a/semicongine/text.nim Fri Dec 06 22:48:25 2024 +0700 +++ b/semicongine/text.nim Sat Dec 07 21:34:24 2024 +0700 @@ -84,7 +84,7 @@ fragmentUv {.Pass.}: Vec2f fragmentColor {.PassFlat.}: Vec4f - color {.ShaderOutput.}: Vec4f + outColor {.ShaderOutput.}: Vec4f glyphData {.DescriptorSet: 0.}: GlyphDescriptors[N] vertexCode* = """void main() { @@ -105,7 +105,7 @@ if(v == 0) { discard; } - color = vec4(fragmentColor.rgb, fragmentColor.a * v); + outColor = vec4(fragmentColor.rgb, fragmentColor.a * v); }""" proc `=copy`(dest: var FontObj, source: FontObj) {.error.}
--- a/tests/test_rendering.nim Fri Dec 06 22:48:25 2024 +0700 +++ b/tests/test_rendering.nim Sat Dec 07 21:34:24 2024 +0700 @@ -1032,24 +1032,24 @@ setupSwapchain(renderpass = renderpass) # tests a simple triangle with minimalistic shader and vertex format - # test_01_triangle(time) + test_01_triangle(time) # tests instanced triangles and quads, mixing meshes and instances - # test_02_triangle_quad_instanced(time) + test_02_triangle_quad_instanced(time) # teste descriptor sets - # test_03_simple_descriptorset(time) + test_03_simple_descriptorset(time) # tests multiple descriptor sets and arrays - # test_04_multiple_descriptorsets(time) + test_04_multiple_descriptorsets(time) # rotating cube - # test_05_cube(time) + test_05_cube(time) # different draw modes (lines, points, and topologies) - # test_06_different_draw_modes(time) + test_06_different_draw_modes(time) - # test_07_png_texture(time) + test_07_png_texture(time) test_08_texture_array(time) @@ -1058,7 +1058,7 @@ clearSwapchain() # test multiple render passes - # for i, (depthBuffer, samples) in renderPasses: - # test_09_triangle_2pass(time, depthBuffer, samples) + for i, (depthBuffer, samples) in renderPasses: + test_09_triangle_2pass(time, depthBuffer, samples) destroyVulkan()