Mercurial > games > semicongine
changeset 1373:19469f21f34e
did: implement vecs as distinct types
author | sam <sam@basx.dev> |
---|---|
date | Fri, 06 Dec 2024 22:20:39 +0700 |
parents | 2da623ec519b |
children | 92c089136a05 |
files | semicongine/contrib/algorithms/texture_packing.nim semicongine/core.nim semicongine/core/vector.nim semicongine/rendering.nim semicongine/rendering/renderer.nim semicongine/rendering/shaders.nim semicongine/text/font.nim |
diffstat | 7 files changed, 193 insertions(+), 37 deletions(-) [+] |
line wrap: on
line diff
--- a/semicongine/contrib/algorithms/texture_packing.nim Wed Dec 04 22:17:41 2024 +0700 +++ b/semicongine/contrib/algorithms/texture_packing.nim Fri Dec 06 22:20:39 2024 +0700 @@ -84,10 +84,10 @@ for y in 0 ..< rect.h: for x in 0 ..< rect.w: when T is Gray: - assert result.atlas[rect.x + x, rect.y + y] == [0'u8], + assert result.atlas[rect.x + x, rect.y + y] == default(T), "Atlas texture packing encountered an overlap error" elif T is BGRA: - assert result.atlas[rect.x + x, rect.y + y] == [0'u8, 0'u8, 0'u8, 0'u8], + assert result.atlas[rect.x + x, rect.y + y] == default(T), "Atlas texture packing encountered an overlap error" else: {.error: "Unsupported type for texture packing".}
--- a/semicongine/core.nim Wed Dec 04 22:17:41 2024 +0700 +++ b/semicongine/core.nim Fri Dec 06 22:20:39 2024 +0700 @@ -1,3 +1,4 @@ +import std/hashes import std/macros import std/math import std/monotimes
--- a/semicongine/core/vector.nim Wed Dec 04 22:17:41 2024 +0700 +++ b/semicongine/core/vector.nim Fri Dec 06 22:20:39 2024 +0700 @@ -1,8 +1,8 @@ type - TVec1*[T: SomeNumber] = array[1, T] - TVec2*[T: SomeNumber] = array[2, T] - TVec3*[T: SomeNumber] = array[3, T] - TVec4*[T: SomeNumber] = array[4, T] + TVec1*[T: SomeNumber] = distinct array[1, T] + TVec2*[T: SomeNumber] = distinct array[2, T] + TVec3*[T: SomeNumber] = distinct array[3, T] + TVec4*[T: SomeNumber] = distinct array[4, T] TVec* = TVec1 | TVec2 | TVec3 | TVec4 Vec1f* = TVec1[float32] Vec2f* = TVec2[float32] @@ -18,8 +18,107 @@ Vec4u* = TVec4[uint32] # support for shorts + Vec1i8* = TVec1[int8] + Vec1u8* = TVec1[uint8] Vec2i8* = TVec2[int8] + Vec2u8* = TVec2[uint8] Vec3i8* = TVec3[int8] + Vec3u8* = TVec3[uint8] + +# stuff to allow working like an array, despite 'distinct' + +converter toArray*[T](v: TVec1[T]): array[1, T] = + array[1, T](v) + +converter toArray*[T](v: TVec2[T]): array[2, T] = + array[2, T](v) + +converter toArray*[T](v: TVec3[T]): array[3, T] = + array[3, T](v) + +converter toArray*[T](v: TVec4[T]): array[4, T] = + array[4, T](v) + +template `[]`*[T](v: TVec1[T], i: Ordinal): T = + (array[1, T](v))[i] + +template `[]`*[T](v: TVec2[T], i: Ordinal): T = + (array[2, T](v))[i] + +template `[]`*[T](v: TVec3[T], i: Ordinal): T = + (array[3, T](v))[i] + +template `[]`*[T](v: TVec4[T], i: Ordinal): T = + (array[4, T](v))[i] + +template `[]=`*[T](v: TVec1[T], i: Ordinal, a: T) = + (array[1, T](v))[i] = a + +template `[]=`*[T](v: TVec2[T], i: Ordinal, a: T) = + (array[2, T](v))[i] = a + +template `[]=`*[T](v: TVec3[T], i: Ordinal, a: T) = + (array[3, T](v))[i] = a + +template `[]=`*[T](v: TVec4[T], i: Ordinal, a: T) = + (array[4, T](v))[i] = a + +template `==`*[T](a, b: TVec1[T]): bool = + `==`(array[1, T](a), array[1, T](b)) + +template `==`*[T](a, b: TVec2[T]): bool = + `==`(array[2, T](a), array[2, T](b)) + +template `==`*[T](a, b: TVec3[T]): bool = + `==`(array[3, T](a), array[3, T](b)) + +template `==`*[T](a, b: TVec4[T]): bool = + `==`(array[4, T](a), array[4, T](b)) + +func len*(v: TVec1): int = + 1 +func len*(v: TVec2): int = + 2 +func len*(v: TVec3): int = + 3 +func len*(v: TVec4): int = + 4 + +func sum*[T](v: TVec1[T]): T = + sum(array[1, T](v)) +func sum*[T](v: TVec2[T]): T = + sum(array[2, T](v)) +func sum*[T](v: TVec3[T]): T = + sum(array[3, T](v)) +func sum*[T](v: TVec4[T]): T = + sum(array[4, T](v)) + +func hash*[T](v: TVec1[T]): Hash = + hash(array[1, T](v)) +func hash*[T](v: TVec2[T]): Hash = + hash(array[2, T](v)) +func hash*[T](v: TVec3[T]): Hash = + hash(array[3, T](v)) +func hash*[T](v: TVec4[T]): Hash = + hash(array[4, T](v)) + +iterator items*[T](v: TVec1[T]): T = + yield v[0] + +iterator items*[T](v: TVec2[T]): T = + yield v[0] + yield v[1] + +iterator items*[T](v: TVec3[T]): T = + yield v[0] + yield v[1] + yield v[2] + +iterator items*[T](v: TVec4[T]): T = + yield v[0] + yield v[1] + yield v[2] + yield v[3] func toVec1*[T: SomeNumber](orig: TVec3[T] | TVec4[T]): TVec1[T] = TVec1[T]([orig[0]]) @@ -94,12 +193,23 @@ vec4i(0, 0, 0, 0) # shortcuts Vec3i8 +func vec1i8*[T: SomeInteger](x: T): Vec1i8 = + Vec1i8([int8(x)]) +func vec1i8*(): Vec1i8 = + vec1i8(0) +func vec1u8*[T: SomeInteger](x: T): Vec1u8 = + Vec1u8([uint8(x)]) +func vec1u8*(): Vec1u8 = + vec1u8(0) + +# missing: unsigned ones func vec2i8*[T, S: SomeInteger](x: T, y: S): Vec2i8 = Vec2i8([int8(x), int8(y)]) func vec2i8*[T: SomeInteger](x: T): Vec2i8 = vec2i8(x, 0) func vec2i8*(): Vec2i8 = vec2i8(0, 0) + func vec3i8*[T, S, U: SomeInteger](x: T, y: S, z: U): Vec3i8 = Vec3i8([int8(x), int8(y), int8(z)]) func vec3i8*[T, S: SomeInteger](x: T, y: S): Vec3i8 =
--- a/semicongine/rendering.nim Wed Dec 04 22:17:41 2024 +0700 +++ b/semicongine/rendering.nim Fri Dec 06 22:20:39 2024 +0700 @@ -131,6 +131,8 @@ IndexBufferMapped UniformBuffer UniformBufferMapped + StorageBuffer + StorageBufferMapped MemoryBlock* = object vk: VkDeviceMemory @@ -198,12 +200,20 @@ const `countname` {.inject.} = 1'u32 body `bindingNumber`.inc - elif typeof(`valuename`) is GPUValue: + 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: @@ -211,12 +221,20 @@ const `countname` {.inject.} = uint32(typeof(`valuename`).len) body `bindingNumber`.inc - elif elementType(`valuename`) is GPUValue: + 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 else: {. error: "Unsupported descriptor type: " & typetraits.name(typeof(`valuename`)) @@ -385,7 +403,8 @@ initSwapchain(renderPass, vSync = vSync, tripleBuffering = tripleBuffering) proc destroyVulkan*() = - clearSwapchain() + if vulkan.swapchain != nil: + clearSwapchain() vkDestroyDevice(vulkan.device, nil) vkDestroySurfaceKHR(vulkan.instance, vulkan.surface, nil) if vulkan.debugMessenger.Valid:
--- a/semicongine/rendering/renderer.nim Wed Dec 04 22:17:41 2024 +0700 +++ b/semicongine/rendering/renderer.nim Fri Dec 06 22:20:39 2024 +0700 @@ -1,20 +1,16 @@ func pointerAddOffset[T: SomeInteger](p: pointer, offset: T): pointer = cast[pointer](cast[T](p) + offset) -func usage(bType: BufferType): seq[VkBufferUsageFlagBits] = - case bType - of VertexBuffer: - @[VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] - of VertexBufferMapped: - @[VK_BUFFER_USAGE_VERTEX_BUFFER_BIT] - of IndexBuffer: - @[VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] - of IndexBufferMapped: - @[VK_BUFFER_USAGE_INDEX_BUFFER_BIT] - of UniformBuffer: - @[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT] - of UniformBufferMapped: - @[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT] +const BUFFER_USAGE: array[BufferType, seq[VkBufferUsageFlagBits]] = [ + VertexBuffer: @[VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT], + VertexBufferMapped: @[VK_BUFFER_USAGE_VERTEX_BUFFER_BIT], + IndexBuffer: @[VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT], + IndexBufferMapped: @[VK_BUFFER_USAGE_INDEX_BUFFER_BIT], + UniformBuffer: @[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT], + UniformBufferMapped: @[VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT], + StorageBuffer: @[VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT], + StorageBufferMapped: @[VK_BUFFER_USAGE_STORAGE_BUFFER_BIT], +] proc getVkFormat(grayscale: bool, usage: openArray[VkImageUsageFlagBits]): VkFormat = let formats = @@ -56,7 +52,8 @@ typeof(gpuData).TBuffer func needsMapping(bType: BufferType): bool = - bType in [VertexBufferMapped, IndexBufferMapped, UniformBufferMapped] + bType in + [VertexBufferMapped, IndexBufferMapped, UniformBufferMapped, StorageBufferMapped] template needsMapping(gpuData: GPUData): untyped = gpuData.bufferType.needsMapping @@ -259,7 +256,7 @@ renderData: var RenderData, size: uint64, bufferType: BufferType ): Buffer = result = Buffer( - vk: svkCreateBuffer(size, bufferType.usage), + vk: svkCreateBuffer(size, BUFFER_USAGE[bufferType]), size: size, rawPointer: nil, offsetNextFree: 0, @@ -394,6 +391,9 @@ VkDescriptorPoolSize( thetype: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, descriptorCount: descriptorPoolLimit ), + VkDescriptorPoolSize( + thetype: VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, descriptorCount: descriptorPoolLimit + ), ] var poolInfo = VkDescriptorPoolCreateInfo( sType: VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, @@ -504,13 +504,14 @@ proc createVulkanImage(renderData: var RenderData, image: var ImageObject) = assert image.vk == VkImage(0), "Image has already been created" - var usage = @[VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_USAGE_SAMPLED_BIT] + var imgUsage = @[VK_IMAGE_USAGE_TRANSFER_DST_BIT, VK_IMAGE_USAGE_SAMPLED_BIT] if image.isRenderTarget: - usage.add VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT - let format = getVkFormat(grayscale = elementType(image.data) is Gray, usage = usage) + imgUsage.add VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT + let format = + getVkFormat(grayscale = elementType(image.data) is Gray, usage = imgUsage) image.vk = svkCreate2DImage( - image.width, image.height, format, usage, image.samples, image.nLayers + image.width, image.height, format, imgUsage, image.samples, image.nLayers ) renderData.images.add image.vk image.sampler = createSampler(
--- a/semicongine/rendering/shaders.nim Wed Dec 04 22:17:41 2024 +0700 +++ b/semicongine/rendering/shaders.nim Fri Dec 06 22:20:39 2024 +0700 @@ -79,6 +79,9 @@ const n = typetraits.name(T) {.error: "Unsupported data type on GPU: " & n.} +func glslType[T: SupportedGPUType](value: openArray[T]): string = + return glslType(default(T)) & "[]" + func vkType[T: SupportedGPUType](value: T): VkFormat = when T is float32: VK_FORMAT_R32_SFLOAT @@ -264,12 +267,23 @@ ") uniform " & glslType(descriptorValue) & " " & descriptorName & ";" descriptorBinding.inc elif typeof(descriptorValue) is GPUValue: + let bufferType = + if typeof(descriptorValue).TBuffer in [UniformBuffer, UniformBufferMapped]: + "uniform" + else: + "readonly buffer" uniforms.add "layout(set=" & $setIndex & ", binding = " & $descriptorBinding & - ") uniform T" & descriptorName & " {" + ") " & bufferType & " T" & descriptorName & " {" when typeof(descriptorValue.data) is object: for blockFieldName, blockFieldValue in descriptorValue.data.fieldPairs(): - assert typeof(blockFieldValue) is SupportedGPUType, - "uniform block field '" & blockFieldName & "' is not a SupportedGPUType" + 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" uniforms.add " " & glslType(blockFieldValue) & " " & blockFieldName & ";" uniforms.add "} " & descriptorName & ";" else: @@ -287,13 +301,24 @@ descriptorName & "" & arrayDecl & ";" descriptorBinding.inc elif elementType(descriptorValue) is GPUValue: + let bufferType = + if typeof(descriptorValue).TBuffer in [UniformBuffer, UniformBufferMapped]: + "uniform" + else: + "readonly buffer" uniforms.add "layout(set=" & $setIndex & ", binding = " & $descriptorBinding & - ") uniform T" & descriptorName & " {" + ") " & bufferType & " T" & descriptorName & " {" for blockFieldName, blockFieldValue in default(elementType(descriptorValue)).data .fieldPairs(): - assert typeof(blockFieldValue) is SupportedGPUType, - "uniform block field '" & blockFieldName & "' is not a SupportedGPUType" + 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" uniforms.add " " & glslType(blockFieldValue) & " " & blockFieldName & ";" uniforms.add "} " & descriptorName & "[" & $descriptorValue.len & "];" descriptorBinding.inc
--- a/semicongine/text/font.nim Wed Dec 04 22:17:41 2024 +0700 +++ b/semicongine/text/font.nim Fri Dec 06 22:20:39 2024 +0700 @@ -97,10 +97,10 @@ if width > 0 and height > 0: var bitmap = newSeq[Gray](width * height) for i in 0 ..< width * height: - bitmap[i] = [data[i].uint8] + bitmap[i] = vec1u8(data[i].uint8) images.add Image[Gray](width: width.uint32, height: height.uint32, data: bitmap) else: - images.add Image[Gray](width: 1, height: 1, data: @[[0'u8]]) + images.add Image[Gray](width: 1, height: 1, data: @[vec1u8()]) nativeFree(data)