# HG changeset patch # User Sam # Date 1680802327 -25200 # Node ID dfaddaf96f09c973ba73c94521caee9622f68751 # Parent 2780d9aad14286e8a0a7cb839de659a5c7ad08f4 did: refactor GPU data types, more generic, prepare to use for decriptors/uniforms diff -r 2780d9aad142 -r dfaddaf96f09 src/semicongine/entity.nim --- a/src/semicongine/entity.nim Thu Apr 06 00:30:56 2023 +0700 +++ b/src/semicongine/entity.nim Fri Apr 07 00:32:07 2023 +0700 @@ -9,7 +9,7 @@ Entity* = ref object of RootObj name*: string - transform*: Mat44 # todo: cache transform + only update VBO when transform changed + transform*: Mat4 # todo: cache transform + only update VBO when transform changed parent*: Entity children*: seq[Entity] components*: seq[Component] @@ -37,7 +37,7 @@ func newEntity*(name: string = ""): Entity = result = new Entity result.name = name - result.transform = Unit44 + result.transform = Unit4 if result.name == "": result.name = &"Entity[{$(cast[ByteAddress](result))}]" @@ -47,7 +47,7 @@ for child in children: result.add child result.name = name - result.transform = Unit44 + result.transform = Unit4 if result.name == "": result.name = &"Entity[{$(cast[ByteAddress](result))}]" @@ -59,10 +59,10 @@ result.add part if result.name == "": result.name = &"Entity[{$(cast[ByteAddress](result))}]" - result.transform = Unit44 + result.transform = Unit4 -func getModelTransform*(entity: Entity): Mat44 = - result = Unit44 +func getModelTransform*(entity: Entity): Mat4 = + result = Unit4 var currentEntity = entity while currentEntity != nil: result = currentEntity.transform * result diff -r 2780d9aad142 -r dfaddaf96f09 src/semicongine/gpu_data.nim --- a/src/semicongine/gpu_data.nim Thu Apr 06 00:30:56 2023 +0700 +++ b/src/semicongine/gpu_data.nim Fri Apr 07 00:32:07 2023 +0700 @@ -7,7 +7,9 @@ import ./math type - CountType = 1'u32 .. 4'u32 + GPUType = 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] + +type DataType* = enum Float32 Float64 @@ -19,47 +21,112 @@ UInt16 UInt32 UInt64 + Vec2I32 + Vec2I64 + Vec3I32 + Vec3I64 + Vec4I32 + Vec4I64 + Vec2U32 + Vec2U64 + Vec3U32 + Vec3U64 + Vec4U32 + Vec4U64 + Vec2F32 + Vec2F64 + Vec3F32 + Vec3F64 + Vec4F32 + Vec4F64 + Mat2F32 + Mat2F64 + Mat23F32 + Mat23F64 + Mat32F32 + Mat32F64 + Mat3F32 + Mat3F64 + Mat34F32 + Mat34F64 + Mat43F32 + Mat43F64 + Mat4F32 + Mat4F64 + DataValue* = object + case thetype*: DataType + of Float32: float32: float32 + of Float64: float64: float64 + of Int8: int8: int8 + of Int16: int16: int16 + of Int32: int32: int32 + of Int64: int64: int64 + of UInt8: uint8: uint8 + of UInt16: uint16: uint16 + of UInt32: uint32: uint32 + of UInt64: uint64: uint64 + of Vec2I32: vec2i32: TVec2[int32] + of Vec2I64: vec2i64: TVec2[int64] + of Vec3I32: vec3i32: TVec3[int32] + of Vec3I64: vec3i64: TVec3[int64] + of Vec4I32: vec4i32: TVec4[int32] + of Vec4I64: vec4i64: TVec4[int64] + of Vec2U32: vec2u32: TVec2[uint32] + of Vec2U64: vec2u64: TVec2[uint64] + of Vec3U32: vec3u32: TVec3[uint32] + of Vec3U64: vec3u64: TVec3[uint64] + of Vec4U32: vec4u32: TVec4[uint32] + of Vec4U64: vec4u64: TVec4[uint64] + of Vec2F32: vec2f32: TVec2[float32] + of Vec2F64: vec2f64: TVec2[float64] + of Vec3F32: vec3f32: TVec3[float32] + of Vec3F64: vec3f64: TVec3[float64] + of Vec4F32: vec4f32: TVec4[float32] + of Vec4F64: vec4f64: TVec4[float64] + of Mat2F32: mat2f32: TMat2[float32] + of Mat2F64: mat2f64: TMat2[float64] + of Mat23F32: mat23f32: TMat23[float32] + of Mat23F64: mat23f64: TMat23[float64] + of Mat32F32: mat32f32: TMat32[float32] + of Mat32F64: mat32f64: TMat32[float64] + of Mat3F32: mat3f32: TMat3[float32] + of Mat3F64: mat3f64: TMat3[float64] + of Mat34F32: mat34f32: TMat34[float32] + of Mat34F64: mat34f64: TMat34[float64] + of Mat43F32: mat43f32: TMat43[float32] + of Mat43F64: mat43f64: TMat43[float64] + of Mat4F32: mat4f32: TMat4[float32] + of Mat4F64: mat4f64: TMat4[float64] MemoryLocation* = enum VRAM, VRAMVisible, RAM # VRAM is fastest, VRAMVisible allows updating memory directly, may be slower - Attribute* = object + VertexAttribute* = object name*: string thetype*: DataType - components*: CountType # how many components the vectors has (1 means scalar) - rows*: CountType # used to split matrices into rows of vectors perInstance*: bool memoryLocation*: MemoryLocation AttributeGroup* = object - attributes*: seq[Attribute] + attributes*: seq[VertexAttribute] -func initAttributeGroup*(attrs: varargs[Attribute]): auto = +func initAttributeGroup*(attrs: varargs[VertexAttribute]): auto = AttributeGroup(attributes: attrs.toSeq) -func vertexInputs*(group: AttributeGroup): seq[Attribute] = +func vertexInputs*(group: AttributeGroup): seq[VertexAttribute] = for attr in group.attributes: if attr.perInstance == false: result.add attr -func instanceInputs*(group: AttributeGroup): seq[Attribute] = +func instanceInputs*(group: AttributeGroup): seq[VertexAttribute] = for attr in group.attributes: if attr.perInstance == false: result.add attr -func attr*( - name: string, - thetype: DataType, - components=CountType(1), - rows=CountType(1), - perInstance=false, - memoryLocation=VRAMVisible, -): auto = - Attribute( - name: name, - thetype: thetype, - components: components, - rows: rows, - perInstance: perInstance, - memoryLocation: memoryLocation, - ) + +func numberOfVertexInputAttributeDescriptors*(thetype: DataType): uint32 = + case thetype: + of Mat2F32, Mat2F64, Mat23F32, Mat23F64: 2 + of Mat32F32, Mat32F64, Mat3F32, Mat3F64, Mat34F32, Mat34F64: 3 + of Mat43F32, Mat43F64, Mat4F32, Mat4F64: 4 + else: 1 func size*(thetype: DataType): uint32 = case thetype: @@ -73,18 +140,48 @@ of UInt16: 2 of UInt32: 4 of UInt64: 8 + of Vec2I32: 8 + of Vec2I64: 16 + of Vec3I32: 12 + of Vec3I64: 24 + of Vec4I32: 16 + of Vec4I64: 32 + of Vec2U32: 8 + of Vec2U64: 16 + of Vec3U32: 12 + of Vec3U64: 24 + of Vec4U32: 16 + of Vec4U64: 32 + of Vec2F32: 8 + of Vec2F64: 16 + of Vec3F32: 12 + of Vec3F64: 24 + of Vec4F32: 16 + of Vec4F64: 32 + of Mat2F32: 16 + of Mat2F64: 32 + of Mat23F32: 24 + of Mat23F64: 48 + of Mat32F32: 24 + of Mat32F64: 48 + of Mat3F32: 36 + of Mat3F64: 72 + of Mat34F32: 48 + of Mat34F64: 92 + of Mat43F32: 48 + of Mat43F64: 92 + of Mat4F32: 64 + of Mat4F64: 128 -func size*(attribute: Attribute, perRow=false): uint32 = - if perRow: - attribute.thetype.size * attribute.components - else: - attribute.thetype.size * attribute.components * attribute.rows +func size*(attribute: VertexAttribute, perDescriptor=false): uint32 = + if perDescriptor: attribute.thetype.size div attribute.thetype.numberOfVertexInputAttributeDescriptors + else: attribute.thetype.size func size*(thetype: AttributeGroup): uint32 = for attribute in thetype.attributes: result += attribute.size -func getDataType*[T: SomeNumber](value: T): DataType = +func getDataType*[T: GPUType|int|uint|float](): DataType = when T is float32: Float32 elif T is float64: Float64 elif T is int8: Int8 @@ -101,86 +198,149 @@ elif T is uint and sizeof(uint) == sizeof(uint32): UInt32 elif T is float and sizeof(float) == sizeof(float32): Float32 elif T is float and sizeof(float) == sizeof(float64): Float64 + elif T is TVec2[int32]: Vec2I32 + elif T is TVec2[int64]: Vec2I64 + elif T is TVec3[int32]: Vec3I32 + elif T is TVec3[int64]: Vec3I64 + elif T is TVec4[int32]: Vec4I32 + elif T is TVec4[int64]: Vec4I64 + elif T is TVec2[uint32]: Vec2U32 + elif T is TVec2[uint64]: Vec2U64 + elif T is TVec3[uint32]: Vec3U32 + elif T is TVec3[uint64]: Vec3U64 + elif T is TVec4[uint32]: Vec4U32 + elif T is TVec4[uint64]: Vec4U64 + elif T is TVec2[float32]: Vec2F32 + elif T is TVec2[float64]: Vec2F64 + elif T is TVec3[float32]: Vec3F32 + elif T is TVec3[float64]: Vec3F64 + elif T is TVec4[float32]: Vec4F32 + elif T is TVec4[float64]: Vec4F64 + elif T is TMat2[float32]: Mat2F32 + elif T is TMat2[float64]: Mat2F64 + elif T is TMat23[float32]: Mat23F32 + elif T is TMat23[float64]: Mat23F64 + elif T is TMat32[float32]: Mat32F32 + elif T is TMat32[float64]: Mat32F64 + elif T is TMat3[float32]: Mat3F32 + elif T is TMat3[float64]: Mat3F64 + elif T is TMat34[float32]: Mat34F32 + elif T is TMat34[float64]: Mat34F64 + elif T is TMat43[float32]: Mat43F32 + elif T is TMat43[float64]: Mat43F64 + elif T is TMat4[float32]: Mat4F32 + elif T is TMat4[float64]: Mat4F64 else: static: raise newException(Exception, &"Unsupported data type for GPU data: {name(T)}" ) -func asAttribute*[T: SomeNumber|TMat|TVec](value: T, name: string): Attribute = - when not (T is SomeNumber): - let nonScalarDatatype = getDataType(default(get(genericParams(typeof(value)), 0))) +func attr*[T: GPUType]( + name: string, + perInstance=false, + memoryLocation=VRAMVisible, +): auto = + VertexAttribute( + name: name, + thetype: getDataType[T](), + perInstance: perInstance, + memoryLocation: memoryLocation, + ) - when T is SomeNumber: attr(name, getDataType(default(T))) - elif T is TMat22: attr(name, nonScalarDatatype, 2, 2) - elif T is TMat23: attr(name, nonScalarDatatype, 3, 2) - elif T is TMat32: attr(name, nonScalarDatatype, 3, 2) - elif T is TMat33: attr(name, nonScalarDatatype, 3, 3) - elif T is TMat34: attr(name, nonScalarDatatype, 4, 3) - elif T is TMat43: attr(name, nonScalarDatatype, 3, 4) - elif T is TMat44: attr(name, nonScalarDatatype, 4, 4) - elif T is TVec2: attr(name, nonScalarDatatype, 2) - elif T is TVec3: attr(name, nonScalarDatatype, 3) - elif T is TVec4: attr(name, nonScalarDatatype, 4) - else: {.error "Unsupported attribute type for GPU data".} - -func asAttribute*[T: SomeNumber|TMat|TVec](): Attribute = - asAttribute(default(T), name(T)) +func get*[T: GPUType|int|uint|float](value: DataValue): T = + case value.thetype + of Float32: value.float32 + of Float64: value.float64 + of Int8: value.int8 + of Int16: value.int16 + of Int32: value.int32 + of Int64: value.int64 + of UInt8: value.uint8 + of UInt16: value.uint16 + of UInt32: value.uint32 + of UInt64: value.uint64 + of Vec2I32: value.vec2i32 + of Vec2I64: value.vec2i64 + of Vec3I32: value.vec3i32 + of Vec3I64: value.vec3i64 + of Vec4I32: value.vec4i32 + of Vec4I64: value.vec4i64 + of Vec2U32: value.vec2u32 + of Vec2U64: value.vec2u64 + of Vec3U32: value.vec3u32 + of Vec3U64: value.vec3u64 + of Vec4U32: value.vec4u32 + of Vec4U64: value.vec4u64 + of Vec2F32: value.vec2f32 + of Vec2F64: value.vec2f64 + of Vec3F32: value.vec3f32 + of Vec3F64: value.vec3f64 + of Vec4F32: value.vec4f32 + of Vec4F64: value.vec4f64 + of Mat2F32: value.mat2f32 + of Mat2F64: value.mat2f64 + of Mat23F32: value.mat23f32 + of Mat23F64: value.mat23f64 + of Mat32F32: value.mat32f32 + of Mat32F64: value.mat32f64 + of Mat3F32: value.mat3f32 + of Mat3F64: value.mat3f64 + of Mat34F32: value.mat34f32 + of Mat34F64: value.mat34f64 + of Mat43F32: value.mat43f32 + of Mat43F64: value.mat43f64 + of Mat4F32: value.mat4f32 + of Mat4F64: value.mat4f64 const TYPEMAP = { - CountType(1): { - UInt8: VK_FORMAT_R8_UINT, - Int8: VK_FORMAT_R8_SINT, - UInt16: VK_FORMAT_R16_UINT, - Int16: VK_FORMAT_R16_SINT, - UInt32: VK_FORMAT_R32_UINT, - Int32: VK_FORMAT_R32_SINT, - UInt64: VK_FORMAT_R64_UINT, - Int64: VK_FORMAT_R64_SINT, Float32: VK_FORMAT_R32_SFLOAT, Float64: VK_FORMAT_R64_SFLOAT, - }.toTable, - CountType(2): { - UInt8: VK_FORMAT_R8G8_UINT, - Int8: VK_FORMAT_R8G8_SINT, - UInt16: VK_FORMAT_R16G16_UINT, - Int16: VK_FORMAT_R16G16_SINT, - UInt32: VK_FORMAT_R32G32_UINT, - Int32: VK_FORMAT_R32G32_SINT, - UInt64: VK_FORMAT_R64G64_UINT, - Int64: VK_FORMAT_R64G64_SINT, - Float32: VK_FORMAT_R32G32_SFLOAT, - Float64: VK_FORMAT_R64G64_SFLOAT, - }.toTable, - CountType(3): { - UInt8: VK_FORMAT_R8G8B8_UINT, - Int8: VK_FORMAT_R8G8B8_SINT, - UInt16: VK_FORMAT_R16G16B16_UINT, - Int16: VK_FORMAT_R16G16B16_SINT, - UInt32: VK_FORMAT_R32G32B32_UINT, - Int32: VK_FORMAT_R32G32B32_SINT, - UInt64: VK_FORMAT_R64G64B64_UINT, - Int64: VK_FORMAT_R64G64B64_SINT, - Float32: VK_FORMAT_R32G32B32_SFLOAT, - Float64: VK_FORMAT_R64G64B64_SFLOAT, - }.toTable, - CountType(4): { - UInt8: VK_FORMAT_R8G8B8A8_UINT, - Int8: VK_FORMAT_R8G8B8A8_SINT, - UInt16: VK_FORMAT_R16G16B16A16_UINT, - Int16: VK_FORMAT_R16G16B16A16_SINT, - UInt32: VK_FORMAT_R32G32B32A32_UINT, - Int32: VK_FORMAT_R32G32B32A32_SINT, - UInt64: VK_FORMAT_R64G64B64A64_UINT, - Int64: VK_FORMAT_R64G64B64A64_SINT, - Float32: VK_FORMAT_R32G32B32A32_SFLOAT, - Float64: VK_FORMAT_R64G64B64A64_SFLOAT, - }.toTable, + Int8: VK_FORMAT_R8_SINT, + Int16: VK_FORMAT_R16_SINT, + Int32: VK_FORMAT_R32_SINT, + Int64: VK_FORMAT_R64_SINT, + UInt8: VK_FORMAT_R8_UINT, + UInt16: VK_FORMAT_R16_UINT, + UInt32: VK_FORMAT_R32_UINT, + UInt64: VK_FORMAT_R64_UINT, + Vec2I32: VK_FORMAT_R32G32_SINT, + Vec2I64: VK_FORMAT_R64G64_SINT, + Vec3I32: VK_FORMAT_R32G32B32_SINT, + Vec3I64: VK_FORMAT_R64G64B64_SINT, + Vec4I32: VK_FORMAT_R32G32B32A32_SINT, + Vec4I64: VK_FORMAT_R64G64B64A64_SINT, + Vec2U32: VK_FORMAT_R32G32_UINT, + Vec2U64: VK_FORMAT_R64G64_UINT, + Vec3U32: VK_FORMAT_R32G32B32_UINT, + Vec3U64: VK_FORMAT_R64G64B64_UINT, + Vec4U32: VK_FORMAT_R32G32B32A32_UINT, + Vec4U64: VK_FORMAT_R64G64B64A64_UINT, + Vec2F32: VK_FORMAT_R32G32_SFLOAT, + Vec2F64: VK_FORMAT_R64G64_SFLOAT, + Vec3F32: VK_FORMAT_R32G32B32_SFLOAT, + Vec3F64: VK_FORMAT_R64G64B64_SFLOAT, + Vec4F32: VK_FORMAT_R32G32B32A32_SFLOAT, + Vec4F64: VK_FORMAT_R64G64B64A64_SFLOAT, + Mat2F32: VK_FORMAT_R32G32_SFLOAT, + Mat2F64: VK_FORMAT_R64G64_SFLOAT, + Mat23F32: VK_FORMAT_R32G32B32_SFLOAT, + Mat23F64: VK_FORMAT_R64G64B64_SFLOAT, + Mat32F32: VK_FORMAT_R32G32_SFLOAT, + Mat32F64: VK_FORMAT_R64G64_SFLOAT, + Mat3F32: VK_FORMAT_R32G32B32_SFLOAT, + Mat3F64: VK_FORMAT_R64G64B64_SFLOAT, + Mat34F32: VK_FORMAT_R32G32B32A32_SFLOAT, + Mat34F64: VK_FORMAT_R64G64B64A64_SFLOAT, + Mat43F32: VK_FORMAT_R32G32B32_SFLOAT, + Mat43F64: VK_FORMAT_R64G64B64_SFLOAT, + Mat4F32: VK_FORMAT_R32G32B32A32_SFLOAT, + Mat4F64: VK_FORMAT_R64G64B64A64_SFLOAT, }.toTable -func getVkFormat*(value: Attribute): VkFormat = - TYPEMAP[value.components][value.thetype] +func getVkFormat*(thetype: DataType): VkFormat = + TYPEMAP[thetype] # from https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap15.html -func nLocationSlots*(attribute: Attribute): uint32 = +func nLocationSlots*(thetype: DataType): uint32 = #[ single location: 16-bit scalar and vector types, and @@ -189,58 +349,101 @@ two locations 64-bit three- and four-component vectors ]# - case attribute.thetype: + case thetype: of Float32: 1 - of Float64: (if attribute.components < 3: 1 else: 2) + of Float64: 1 of Int8: 1 of Int16: 1 of Int32: 1 - of Int64: (if attribute.components < 3: 1 else: 2) + of Int64: 1 of UInt8: 1 of UInt16: 1 of UInt32: 1 - of UInt64: (if attribute.components < 3: 1 else: 2) + of UInt64: 1 + of Vec2I32: 1 + of Vec2I64: 1 + of Vec3I32: 1 + of Vec3I64: 2 + of Vec4I32: 1 + of Vec4I64: 2 + of Vec2U32: 1 + of Vec2U64: 1 + of Vec3U32: 1 + of Vec3U64: 2 + of Vec4U32: 1 + of Vec4U64: 2 + of Vec2F32: 1 + of Vec2F64: 1 + of Vec3F32: 1 + of Vec3F64: 2 + of Vec4F32: 1 + of Vec4F64: 2 + of Mat2F32: 1 + of Mat2F64: 1 + of Mat23F32: 1 + of Mat23F64: 2 + of Mat32F32: 1 + of Mat32F64: 1 + of Mat3F32: 1 + of Mat3F64: 2 + of Mat34F32: 1 + of Mat34F64: 2 + of Mat43F32: 1 + of Mat43F64: 2 + of Mat4F32: 1 + of Mat4F64: 2 -func glslType*(attribute: Attribute): string = +func glslType*(thetype: DataType): string = # todo: likely not correct as we would need to enable some # extensions somewhere (Vulkan/GLSL compiler?) to have # everything work as intended. Or maybe the GPU driver does # some automagic conversion stuf.. - - # used to ensure square matrix get only one number for side instead of two, e.g. mat2 instead of mat22 - let matrixColumns = if attribute.components == attribute.rows: "" else: $attribute.components - case attribute.rows: - of 1: - case attribute.components: - of 1: # scalars - case attribute.thetype: - of Float32: "float" - of Float64: "double" - of Int8, Int16, Int32, Int64: "int" - of UInt8, UInt16, UInt32, UInt64: "uint" - else: # vectors - case attribute.thetype: - of Float32: &"vec{attribute.components}" - of Float64: &"dvec{attribute.components}" - of Int8, Int16, Int32, Int64: &"ivec{attribute.components}" - of UInt8, UInt16, UInt32, UInt64: &"uvec{attribute.components}" - else: - case attribute.components: - of 1: raise newException(Exception, &"Unsupported matrix-column-count: {attribute.components}") - else: - case attribute.thetype: - of Float32: &"mat{attribute.rows}{matrixColumns}" - of Float64: &"dmat{attribute.rows}{matrixColumns}" - else: raise newException(Exception, &"Unsupported matrix-component type: {attribute.thetype}") + case thetype: + of Float32: "float" + of Float64: "double" + of Int8, Int16, Int32, Int64: "int" + of UInt8, UInt16, UInt32, UInt64: "uint" + of Vec2I32: "ivec2" + of Vec2I64: "ivec2" + of Vec3I32: "ivec3" + of Vec3I64: "ivec3" + of Vec4I32: "ivec4" + of Vec4I64: "ivec4" + of Vec2U32: "uvec2" + of Vec2U64: "uvec2" + of Vec3U32: "uvec3" + of Vec3U64: "uvec3" + of Vec4U32: "uvec4" + of Vec4U64: "uvec4" + of Vec2F32: "vec2" + of Vec2F64: "dvec2" + of Vec3F32: "vec3" + of Vec3F64: "dvec3" + of Vec4F32: "vec4" + of Vec4F64: "dvec4" + of Mat2F32: "mat2" + of Mat2F64: "dmat2" + of Mat23F32: "mat23" + of Mat23F64: "dmat23" + of Mat32F32: "mat32" + of Mat32F64: "dmat32" + of Mat3F32: "mat3" + of Mat3F64: "dmat3" + of Mat34F32: "mat34" + of Mat34F64: "dmat34" + of Mat43F32: "mat43" + of Mat43F64: "dmat43" + of Mat4F32: "mat4" + of Mat4F64: "dmat4" func glslInput*(group: AttributeGroup): seq[string] = if group.attributes.len == 0: return @[] var i = 0'u32 for attribute in group.attributes: - result.add &"layout(location = {i}) in {attribute.glslType} {attribute.name};" - for j in 0 ..< attribute.rows: - i += attribute.nLocationSlots + result.add &"layout(location = {i}) in {attribute.thetype.glslType} {attribute.name};" + for j in 0 ..< attribute.thetype.numberOfVertexInputAttributeDescriptors: + i += attribute.thetype.nLocationSlots func glslUniforms*(group: AttributeGroup, blockName="Uniforms", binding=0): seq[string] = if group.attributes.len == 0: @@ -248,7 +451,7 @@ # currently only a single uniform block supported, therefore binding = 0 result.add(&"layout(binding = {binding}) uniform T{blockName} {{") for attribute in group.attributes: - result.add(&" {attribute.glslType} {attribute.name};") + result.add(&" {attribute.thetype.glslType} {attribute.name};") result.add(&"}} {blockName};") func glslOutput*(group: AttributeGroup): seq[string] = @@ -256,10 +459,10 @@ return @[] var i = 0'u32 for attribute in group.attributes: - result.add &"layout(location = {i}) out {attribute.glslType} {attribute.name};" + result.add &"layout(location = {i}) out {attribute.thetype.glslType} {attribute.name};" i += 1 -func groupByMemoryLocation*(attributes: openArray[Attribute]): Table[MemoryLocation, seq[Attribute]] = +func groupByMemoryLocation*(attributes: openArray[VertexAttribute]): Table[MemoryLocation, seq[VertexAttribute]] = for attr in attributes: if not (attr.memoryLocation in result): result[attr.memoryLocation] = @[] diff -r 2780d9aad142 -r dfaddaf96f09 src/semicongine/math/matrix.nim --- a/src/semicongine/math/matrix.nim Thu Apr 06 00:30:56 2023 +0700 +++ b/src/semicongine/math/matrix.nim Fri Apr 07 00:32:07 2023 +0700 @@ -16,39 +16,39 @@ # which prevents the type system from identifying the correct type at times) # # Though, great news is that objects have zero overhead! - TMat22*[T: SomeNumber] = object + TMat2*[T: SomeNumber] = object data*: array[4, T] TMat23*[T: SomeNumber] = object data*: array[6, T] TMat32*[T: SomeNumber] = object data*: array[6, T] - TMat33*[T: SomeNumber] = object + TMat3*[T: SomeNumber] = object data*: array[9, T] TMat34*[T: SomeNumber] = object data*: array[12, T] TMat43*[T: SomeNumber] = object data*: array[12, T] - TMat44*[T: SomeNumber] = object + TMat4*[T: SomeNumber] = object data*: array[16, T] - TMat* = TMat22|TMat33|TMat44|TMat23|TMat32|TMat34|TMat43 - Mat22* = TMat22[float32] + TMat* = TMat2|TMat3|TMat4|TMat23|TMat32|TMat34|TMat43 + Mat2* = TMat2[float32] Mat23* = TMat23[float32] Mat32* = TMat32[float32] - Mat33* = TMat33[float32] + Mat3* = TMat3[float32] Mat34* = TMat34[float32] Mat43* = TMat43[float32] - Mat44* = TMat44[float32] + Mat4* = TMat4[float32] -func unit22[T: SomeNumber](): auto {.compiletime.} = TMat22[T](data:[ +func unit2[T: SomeNumber](): auto {.compiletime.} = TMat2[T](data:[ T(1), T(0), T(0), T(1), ]) -func unit33[T: SomeNumber](): auto {.compiletime.} = TMat33[T](data:[ +func unit3[T: SomeNumber](): auto {.compiletime.} = TMat3[T](data:[ T(1), T(0), T(0), T(0), T(1), T(0), T(0), T(0), T(1), ]) -func unit44[T: SomeNumber](): auto {.compiletime.} = TMat44[T](data: [ +func unit4[T: SomeNumber](): auto {.compiletime.} = TMat4[T](data: [ T(1), T(0), T(0), T(0), T(0), T(1), T(0), T(0), T(0), T(0), T(1), T(0), @@ -67,40 +67,40 @@ if theType[^1].isDigit: typename = typename & theType[^1] result.add(newConstStmt( - postfix(ident("Unit22" & typename), "*"), - newCall(nnkBracketExpr.newTree(ident("unit22"), ident(theType))) + postfix(ident("Unit2" & typename), "*"), + newCall(nnkBracketExpr.newTree(ident("unit2"), ident(theType))) )) result.add(newConstStmt( - postfix(ident("Unit33" & typename), "*"), - newCall(nnkBracketExpr.newTree(ident("unit33"), ident(theType))) + postfix(ident("Unit3" & typename), "*"), + newCall(nnkBracketExpr.newTree(ident("unit3"), ident(theType))) )) result.add(newConstStmt( - postfix(ident("Unit44" & typename), "*"), - newCall(nnkBracketExpr.newTree(ident("unit44"), ident(theType))) + postfix(ident("Unit4" & typename), "*"), + newCall(nnkBracketExpr.newTree(ident("unit4"), ident(theType))) )) generateAllConsts() -const Unit22* = unit22[float32]() -const Unit33* = unit33[float32]() -const Unit44* = unit44[float32]() +const Unit2* = unit2[float32]() +const Unit3* = unit3[float32]() +const Unit4* = unit4[float32]() template rowCount*(m: typedesc): int = - when m is TMat22: 2 + when m is TMat2: 2 elif m is TMat23: 2 elif m is TMat32: 3 - elif m is TMat33: 3 + elif m is TMat3: 3 elif m is TMat34: 3 elif m is TMat43: 4 - elif m is TMat44: 4 + elif m is TMat4: 4 template columnCount*(m: typedesc): int = - when m is TMat22: 2 + when m is TMat2: 2 elif m is TMat23: 3 elif m is TMat32: 2 - elif m is TMat33: 3 + elif m is TMat3: 3 elif m is TMat34: 4 elif m is TMat43: 3 - elif m is TMat44: 4 + elif m is TMat4: 4 func toString[T](value: T): string = @@ -124,32 +124,32 @@ result &= filler & strvalues[i] & " " result = $T & "\n" & result -func `$`*(v: TMat22[SomeNumber]): string = toString[TMat22[SomeNumber]](v) +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: TMat33[SomeNumber]): string = toString[TMat33[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: TMat44[SomeNumber]): string = toString[TMat44[SomeNumber]](v) +func `$`*(v: TMat4[SomeNumber]): string = toString[TMat4[SomeNumber]](v) func `[]`*[T: TMat](m: T, row, col: int): auto = m.data[col + row * T.columnCount] proc `[]=`*[T: TMat, U](m: var T, row, col: int, value: U) = m.data[col + row * T.columnCount] = value -func row*[T: TMat22](m: T, i: 0..1): auto = TVec2([m[i, 0], m[i, 1]]) +func row*[T: TMat2](m: T, i: 0..1): auto = TVec2([m[i, 0], m[i, 1]]) func row*[T: TMat32](m: T, i: 0..2): auto = TVec2([m[i, 0], m[i, 1]]) func row*[T: TMat23](m: T, i: 0..1): auto = TVec3([m[i, 0], m[i, 1], m[i, 2]]) -func row*[T: TMat33](m: T, i: 0..2): auto = TVec3([m[i, 0], m[i, 1], m[i, 2]]) +func row*[T: TMat3](m: T, i: 0..2): auto = TVec3([m[i, 0], m[i, 1], m[i, 2]]) func row*[T: TMat43](m: T, i: 0..3): auto = TVec3([m[i, 0], m[i, 1], m[i, 2]]) func row*[T: TMat34](m: T, i: 0..2): auto = TVec4([m[i, 0], m[i, 1], m[i, 2], m[i, 3]]) -func row*[T: TMat44](m: T, i: 0..3): auto = TVec4([m[i, 0], m[i, 1], m[i, 2], m[i, 3]]) +func row*[T: TMat4](m: T, i: 0..3): auto = TVec4([m[i, 0], m[i, 1], m[i, 2], m[i, 3]]) -func col*[T: TMat22](m: T, i: 0..1): auto = TVec2([m[0, i], m[1, i]]) +func col*[T: TMat2](m: T, i: 0..1): auto = TVec2([m[0, i], m[1, i]]) func col*[T: TMat23](m: T, i: 0..2): auto = TVec2([m[0, i], m[1, i]]) func col*[T: TMat32](m: T, i: 0..1): auto = TVec3([m[0, i], m[1, i], m[2, i]]) -func col*[T: TMat33](m: T, i: 0..2): auto = TVec3([m[0, i], m[1, i], m[2, i]]) +func col*[T: TMat3](m: T, i: 0..2): auto = TVec3([m[0, i], m[1, i], m[2, i]]) func col*[T: TMat34](m: T, i: 0..3): auto = TVec3([m[0, i], m[1, i], m[2, i]]) func col*[T: TMat43](m: T, i: 0..2): auto = TVec4([m[0, i], m[1, i], m[2, i], m[3, i]]) -func col*[T: TMat44](m: T, i: 0..3): auto = TVec4([m[0, i], m[1, i], m[2, i], m[3, i]]) +func col*[T: TMat4](m: T, i: 0..3): auto = TVec4([m[0, i], m[1, i], m[2, i], m[3, i]]) proc createMatMatMultiplicationOperator(leftType: typedesc, rightType: typedesc, outType: typedesc): NimNode = var data = nnkBracket.newTree() @@ -254,36 +254,36 @@ result = newStmtList() for op in ["+", "-", "*", "/"]: - result.add(createMatScalarOperator(TMat22, op)) + result.add(createMatScalarOperator(TMat2, op)) result.add(createMatScalarOperator(TMat23, op)) result.add(createMatScalarOperator(TMat32, op)) - result.add(createMatScalarOperator(TMat33, op)) + result.add(createMatScalarOperator(TMat3, op)) result.add(createMatScalarOperator(TMat34, op)) result.add(createMatScalarOperator(TMat43, op)) - result.add(createMatScalarOperator(TMat44, op)) + result.add(createMatScalarOperator(TMat4, op)) - result.add(createMatMatMultiplicationOperator(TMat22, TMat22, TMat22)) - result.add(createMatMatMultiplicationOperator(TMat22, TMat23, TMat23)) - result.add(createMatMatMultiplicationOperator(TMat23, TMat32, TMat22)) - result.add(createMatMatMultiplicationOperator(TMat23, TMat33, TMat23)) - result.add(createMatMatMultiplicationOperator(TMat32, TMat22, TMat32)) - result.add(createMatMatMultiplicationOperator(TMat32, TMat23, TMat33)) - result.add(createMatMatMultiplicationOperator(TMat33, TMat32, TMat32)) - result.add(createMatMatMultiplicationOperator(TMat33, TMat33, TMat33)) - result.add(createMatMatMultiplicationOperator(TMat33, TMat34, TMat34)) - result.add(createMatMatMultiplicationOperator(TMat43, TMat33, TMat43)) - result.add(createMatMatMultiplicationOperator(TMat43, TMat34, TMat44)) - result.add(createMatMatMultiplicationOperator(TMat44, TMat43, TMat43)) - result.add(createMatMatMultiplicationOperator(TMat44, TMat44, TMat44)) + result.add(createMatMatMultiplicationOperator(TMat2, TMat2, TMat2)) + result.add(createMatMatMultiplicationOperator(TMat2, TMat23, TMat23)) + result.add(createMatMatMultiplicationOperator(TMat23, TMat32, TMat2)) + result.add(createMatMatMultiplicationOperator(TMat23, TMat3, TMat23)) + result.add(createMatMatMultiplicationOperator(TMat32, TMat2, TMat32)) + result.add(createMatMatMultiplicationOperator(TMat32, TMat23, TMat3)) + result.add(createMatMatMultiplicationOperator(TMat3, TMat32, TMat32)) + result.add(createMatMatMultiplicationOperator(TMat3, TMat3, TMat3)) + result.add(createMatMatMultiplicationOperator(TMat3, TMat34, TMat34)) + result.add(createMatMatMultiplicationOperator(TMat43, TMat3, TMat43)) + result.add(createMatMatMultiplicationOperator(TMat43, TMat34, TMat4)) + result.add(createMatMatMultiplicationOperator(TMat4, TMat43, TMat43)) + result.add(createMatMatMultiplicationOperator(TMat4, TMat4, TMat4)) - result.add(createVecMatMultiplicationOperator(TMat22, TVec2)) - result.add(createVecMatMultiplicationOperator(TMat33, TVec3)) - result.add(createVecMatMultiplicationOperator(TMat44, TVec4)) + result.add(createVecMatMultiplicationOperator(TMat2, TVec2)) + result.add(createVecMatMultiplicationOperator(TMat3, TVec3)) + result.add(createVecMatMultiplicationOperator(TMat4, TVec4)) createAllMultiplicationOperators() -func transposed*[T](m: TMat22[T]): TMat22[T] = TMat22[T](data: [ +func transposed*[T](m: TMat2[T]): TMat2[T] = TMat2[T](data: [ m[0, 0], m[1, 0], m[0, 1], m[1, 1], ]) @@ -296,7 +296,7 @@ m[0, 0], m[1, 0], m[2, 0], m[0, 1], m[1, 1], m[2, 1], ]) -func transposed*[T](m: TMat33[T]): TMat33[T] = TMat33[T](data: [ +func transposed*[T](m: TMat3[T]): TMat3[T] = TMat3[T](data: [ m[0, 0], m[1, 0], m[2, 0], m[0, 1], m[1, 1], m[2, 1], m[0, 2], m[1, 2], m[2, 2], @@ -312,48 +312,48 @@ m[0, 2], m[1, 2], m[2, 2], m[0, 3], m[1, 3], m[2, 3], ]) -func transposed*[T](m: TMat44[T]): TMat44[T] = TMat44[T](data: [ +func transposed*[T](m: TMat4[T]): TMat4[T] = TMat4[T](data: [ m[0, 0], m[1, 0], m[2, 0], m[3, 0], m[0, 1], m[1, 1], m[2, 1], m[3, 1], m[0, 2], m[1, 2], m[2, 2], m[3, 2], m[0, 3], m[1, 3], m[2, 3], m[3, 3], ]) -func translate2d*[T](x, y: T): TMat33[T] = TMat33[T](data: [ +func translate2d*[T](x, y: T): TMat3[T] = TMat3[T](data: [ T(1), T(0), x, T(0), T(1), y, T(0), T(0), T(1), ]) -func scale2d*[T](sx, sy: T): TMat33[T] = TMat33[T](data: [ +func scale2d*[T](sx, sy: T): TMat3[T] = TMat3[T](data: [ sx, T(0), T(0), T(0), sy, T(0), T(0), T(0), T(1), ]) -func rotate2d*[T](angle: T): TMat33[T] = TMat33[T](data: [ +func rotate2d*[T](angle: T): TMat3[T] = TMat3[T](data: [ cos(angle), -sin(angle), T(0), sin(angle), cos(angle), T(0), T(0), T(0), T(1), ]) -func translate3d*[T](x, y, z: T): TMat44[T] = TMat44[T](data: [ +func translate3d*[T](x, y, z: T): TMat4[T] = TMat4[T](data: [ T(1), T(0), T(0), x, T(0), T(1), T(0), y, T(0), T(0), T(1), z, T(0), T(0), T(0), T(1), ]) -func scale3d*[T](sx, sy, sz: T): TMat44[T] = TMat44[T](data: [ +func scale3d*[T](sx, sy, sz: T): TMat4[T] = TMat4[T](data: [ sx, T(0), T(0), T(0), T(0), sy, T(0), T(0), T(0), T(0), sz, T(0), T(0), T(0), T(0), T(1), ]) -func rotate3d*[T](angle: T, a: TVec3[T]): TMat44[T] = +func rotate3d*[T](angle: T, a: TVec3[T]): TMat4[T] = let cosa = cos(angle) sina = sin(angle) x = a[0] y = a[1] z = a[2] - TMat44[T](data: [ + TMat4[T](data: [ x * x * (1 - cosa) + cosa, y * x * (1 - cosa) - z * sina, z * x * (1 - cosa) + y * sina, T(0), x * y * (1 - cosa) + z * sina, y * y * (1 - cosa) + cosa, z * y * (1 - cosa) - x * sina, T(0), x * z * (1 - cosa) - y * sina, y * z * (1 - cosa) + x * sina, z * z * (1 - cosa) + cosa, T(0), @@ -370,25 +370,25 @@ for i in 0 ..< result.data.len: result.data[i] = rand(1.0) -makeRandomInit(TMat22) +makeRandomInit(TMat2) makeRandomInit(TMat23) makeRandomInit(TMat32) -makeRandomInit(TMat33) +makeRandomInit(TMat3) makeRandomInit(TMat34) makeRandomInit(TMat43) -makeRandomInit(TMat44) +makeRandomInit(TMat4) -func perspective*[T: SomeFloat](fovy, aspect, zNear, zFar: T): TMat44[T] = +func perspective*[T: SomeFloat](fovy, aspect, zNear, zFar: T): TMat4[T] = let tanHalfFovy = tan(fovy / T(2)) - return TMat44[T](data:[ + return TMat4[T](data:[ T(1) / (aspect * tanHalfFovy), T(0), T(0), T(0), T(0), T(1) / tanHalfFovy, T(0), T(0), T(0), T(0), T(zFar / (zFar - zNear)), T(-(zFar * zNear) / (zFar - zNear)), T(0), T(0), T(1), T(1), ]) -func ortho*[T: SomeFloat](left, right, top, bottom, zNear, zFar: T): TMat44[T] = - TMat44[T](data:[ +func ortho*[T: SomeFloat](left, right, top, bottom, zNear, zFar: T): TMat4[T] = + TMat4[T](data:[ T(2) / (right - left), T(0), T(0), -(right + left) / (right - left), T(0), T(2) / (bottom - top), T(0), -(bottom + top) / (bottom - top), T(0), T(0), T(1) / (zFar - zNear), -zNear / (zFar - zNear), diff -r 2780d9aad142 -r dfaddaf96f09 src/semicongine/mesh.nim --- a/src/semicongine/mesh.nim Thu Apr 06 00:30:56 2023 +0700 +++ b/src/semicongine/mesh.nim Fri Apr 07 00:32:07 2023 +0700 @@ -15,7 +15,7 @@ Position, Color, Normal, Tangent, BiTangent, TextureCoordinate MeshIndexType* = enum None - Tiny # up to 2^8 vertices + Tiny # up to 2^8 vertices # TODO: need to check and enable support for this Small # up to 2^16 vertices Big # up to 2^32 vertices MeshData = object @@ -28,7 +28,7 @@ of TextureCoordinate: texturecoord: seq[Vec2f] Mesh* = ref object of Component vertexCount*: uint32 - data: Table[Attribute, MeshData] + data: Table[VertexAttribute, MeshData] case indexType*: MeshIndexType of None: discard of Tiny: tinyIndices*: seq[array[3, uint8]] @@ -57,9 +57,9 @@ result = new Mesh result.vertexCount = uint32(positions.len) result.indexType = None - result.data[asAttribute(default(Vec3f), "position")] = MeshData(thetype: Position, position: positions.toSeq) + result.data[attr[Vec3f]("position")] = MeshData(thetype: Position, position: positions.toSeq) if colors.len > 0: - result.data[asAttribute(default(Vec3f), "color")] = MeshData(thetype: Color, color: colors.toSeq) + result.data[attr[Vec3f]("color")] = MeshData(thetype: Color, color: colors.toSeq) func newMesh*(positions: openArray[Vec3f], colors: openArray[Vec3f]=[], indices: openArray[array[3, uint32|int32|int]], autoResize=true): auto = @@ -67,16 +67,16 @@ result = new Mesh result.vertexCount = uint32(positions.len) - result.data[asAttribute(default(Vec3f), "position")] = MeshData(thetype: Position, position: positions.toSeq) + result.data[attr[Vec3f]("position")] = MeshData(thetype: Position, position: positions.toSeq) if colors.len > 0: - result.data[asAttribute(default(Vec3f), "color")] = MeshData(thetype: Color, color: colors.toSeq) + result.data[attr[Vec3f]("color")] = MeshData(thetype: Color, color: colors.toSeq) for i in indices: assert uint32(i[0]) < result.vertexCount assert uint32(i[1]) < result.vertexCount assert uint32(i[2]) < result.vertexCount - if autoResize and uint32(positions.len) < uint32(high(uint8)) and false: # todo: check feature support + if autoResize and uint32(positions.len) < uint32(high(uint8)) and false: # TODO: check feature support result.indexType = Tiny for i, tri in enumerate(indices): result.tinyIndices.add [uint8(tri[0]), uint8(tri[1]), uint8(tri[2])] @@ -94,9 +94,9 @@ result = new Mesh result.vertexCount = uint32(positions.len) - result.data[asAttribute(default(Vec3f), "position")] = MeshData(thetype: Position, position: positions.toSeq) + result.data[attr[Vec3f]("position")] = MeshData(thetype: Position, position: positions.toSeq) if colors.len > 0: - result.data[asAttribute(default(Vec3f), "color")] = MeshData(thetype: Color, color: colors.toSeq) + result.data[attr[Vec3f]("color")] = MeshData(thetype: Color, color: colors.toSeq) for i in indices: assert i[0] < result.vertexCount @@ -108,13 +108,13 @@ func newMesh*(positions: openArray[Vec3f], colors: openArray[Vec3f]=[], indices: openArray[array[3, uint8|int8]]): auto = assert colors.len == 0 or colors.len == positions.len - assert false # todo: check feature support + assert false # TODO: check feature support result = new Mesh result.vertexCount = uint32(positions.len) - result.data[asAttribute(default(Vec3f), "position")] = MeshData(thetype: Position, position: positions.toSeq) + result.data[attr[Vec3f]("position")] = MeshData(thetype: Position, position: positions.toSeq) if colors.len > 0: - result.data[asAttribute(default(Vec3f), "color")] = MeshData(thetype: Color, color: colors.toSeq) + result.data[attr[Vec3f]("color")] = MeshData(thetype: Color, color: colors.toSeq) for i in indices: assert i[0] < result.vertexCount @@ -134,7 +134,7 @@ of BiTangent: meshdata.bitangent.size of TextureCoordinate: meshdata.texturecoord.size -func attributeSize*(mesh: Mesh, attribute: Attribute): uint64 = +func attributeSize*(mesh: Mesh, attribute: VertexAttribute): uint64 = mesh.data[attribute].meshDataSize func vertexDataSize*(mesh: Mesh): uint64 = @@ -167,137 +167,14 @@ of Small: rawData(mesh.smallIndices) of Big: rawData(mesh.bigIndices) -proc hasDataFor*(mesh: Mesh, attribute: Attribute): bool = +proc hasDataFor*(mesh: Mesh, attribute: VertexAttribute): bool = assert attribute.perInstance == false, "Mesh data cannot handle per-instance attributes" attribute in mesh.data -proc getRawData*(mesh: Mesh, attribute: Attribute): (pointer, uint64) = +proc getRawData*(mesh: Mesh, attribute: VertexAttribute): (pointer, uint64) = assert attribute.perInstance == false, "Mesh data cannot handle per-instance attributes" mesh.data[attribute].getRawData() -proc getData*(mesh: Mesh, attribute: Attribute): MeshData = +proc getData*(mesh: Mesh, attribute: VertexAttribute): MeshData = assert attribute.perInstance == false, "Mesh data cannot handle per-instance attributes" mesh.data[attribute] - -#[ - -func createUberMesh*[T: object, U: uint16|uint32](meshes: openArray[Mesh[ - T, U]]): Mesh[T, U] = - var indexoffset = U(0) - for mesh in meshes: - for srcname, srcvalue in mesh.vertexData.fieldPairs: - for dstname, dstvalue in result.vertexData.fieldPairs: - when srcname == dstname: - dstvalue.data.add srcvalue.data - var indexdata: seq[array[3, U]] - for i in mesh.indices: - indexdata.add [i[0] + indexoffset, i[1] + indexoffset, i[2] + indexoffset] - result.indices.add indexdata - indexoffset += U(mesh.vertexData.VertexCount) - -func getVkIndexType[T: object, U: uint16|uint32](m: Mesh[T, - U]): VkIndexType = - when U is uint16: VK_INDEX_TYPE_UINT16 - elif U is uint32: VK_INDEX_TYPE_UINT32 - -proc createVertexBuffers*[M: Mesh]( - mesh: M, - device: VkDevice, - physicalDevice: VkPhysicalDevice, - commandPool: VkCommandPool, - queue: VkQueue, -): (seq[Buffer], uint32) = - result[1] = mesh.vertexData.VertexCount - for name, value in mesh.vertexData.fieldPairs: - assert value.data.len > 0 - var flags = if value.useOnDeviceMemory: {TransferSrc} else: {VertexBuffer} - var stagingBuffer = device.InitBuffer(physicalDevice, value.datasize, flags, {HostVisible, HostCoherent}) - copyMem(stagingBuffer.data, addr(value.data[0]), value.datasize) - - if value.useOnDeviceMemory: - var finalBuffer = device.InitBuffer(physicalDevice, value.datasize, { - TransferDst, VertexBuffer}, {DeviceLocal}) - transferBuffer(commandPool, queue, stagingBuffer, finalBuffer, - value.datasize) - stagingBuffer.trash() - result[0].add(finalBuffer) - value.buffer = finalBuffer - else: - result[0].add(stagingBuffer) - value.buffer = stagingBuffer - -proc createIndexBuffer*( - mesh: Mesh, - device: VkDevice, - physicalDevice: VkPhysicalDevice, - commandPool: VkCommandPool, - queue: VkQueue, - useDeviceLocalBuffer: bool = true # decides if data is transfered to the fast device-local memory or not -): Buffer = - let bufferSize = uint64(mesh.indices.len * sizeof(get(genericParams(typeof( - mesh.indices)), 0))) - let flags = if useDeviceLocalBuffer: {TransferSrc} else: {IndexBuffer} - - var stagingBuffer = device.InitBuffer(physicalDevice, bufferSize, flags, { - HostVisible, HostCoherent}) - copyMem(stagingBuffer.data, addr(mesh.indices[0]), bufferSize) - - if useDeviceLocalBuffer: - var finalBuffer = device.InitBuffer(physicalDevice, bufferSize, { - TransferDst, IndexBuffer}, {DeviceLocal}) - transferBuffer(commandPool, queue, stagingBuffer, finalBuffer, bufferSize) - stagingBuffer.trash() - return finalBuffer - else: - return stagingBuffer - -proc createIndexedVertexBuffers*( - mesh: Mesh, - device: VkDevice, - physicalDevice: VkPhysicalDevice, - commandPool: VkCommandPool, - queue: VkQueue, - useDeviceLocalBufferForIndices: bool = true # decides if data is transfered to the fast device-local memory or not -): (seq[Buffer], bool, Buffer, uint32, VkIndexType) = - result[0] = createVertexBuffers(mesh, device, physicalDevice, commandPool, - queue)[0] - result[1] = mesh.indexed - if mesh.indexed: - result[2] = createIndexBuffer(mesh, device, physicalDevice, commandPool, - queue, useDeviceLocalBufferForIndices) - result[3] = uint32(mesh.indices.len * mesh.indices[0].len) - result[4] = getVkIndexType(mesh) - else: - result[3] = uint32(mesh.vertexData.VertexCount) - -func quad*[VertexType, VecType, T](): Mesh[VertexType, uint16] = - result = new Mesh[VertexType, uint16] - result.indexed = true - result.indices = @[[0'u16, 1'u16, 2'u16], [2'u16, 3'u16, 0'u16]] - result.vertexData = VertexType() - for attrname, value in result.vertexData.fieldPairs: - when typeof(value) is PositionAttribute: - value.data = @[ - VecType([T(-0.5), T(-0.5), T(0)]), - VecType([T(+0.5), T(-0.5), T(0)]), - VecType([T(+0.5), T(+0.5), T(0)]), - VecType([T(-0.5), T(+0.5), T(0)]), - ] - value.useOnDeviceMemory = true - -func circle*[VertexType, VecType, T](n = 16): Mesh[VertexType, uint16] = - result = new Mesh[VertexType, uint16] - result.indexed = true - let angleStep = (2'f * PI) / float32(n) - var data = @[VecType([T(0), T(0), T(0)])] - for i in 1 .. n: - data.add VecType([T(cos(float32(i) * angleStep)), T(sin(float32(i) * - angleStep)), T(0)]) - result.indices.add [0'u16, uint16(i), uint16(i mod (n) + 1)] - - result.vertexData = VertexType() - for attrname, value in result.vertexData.fieldPairs: - when typeof(value) is PositionAttribute: - value.data = data - value.useOnDeviceMemory = true -]# diff -r 2780d9aad142 -r dfaddaf96f09 src/semicongine/scene.nim --- a/src/semicongine/scene.nim Thu Apr 06 00:30:56 2023 +0700 +++ b/src/semicongine/scene.nim Fri Apr 07 00:32:07 2023 +0700 @@ -23,6 +23,10 @@ of false: discard + ShaderGlobal* = ref object of Component + name*: string + value*: DataValue + Scene* = object name*: string root*: Entity @@ -75,7 +79,8 @@ of Small: smallIndexedMeshes.add mesh of Big: bigIndexedMeshes.add mesh - allIndexedMeshes = bigIndexedMeshes & smallIndexedMeshes & tinyIndexedMeshes # that we don't have to care about index alignment + # ordering meshes this way allows us to ignore value alignment (I think, needs more testing) + allIndexedMeshes = bigIndexedMeshes & smallIndexedMeshes & tinyIndexedMeshes var indicesBufferSize = 0'u64 @@ -92,7 +97,7 @@ ) for location, attributes in pipeline.inputs.vertexInputs.groupByMemoryLocation().pairs: - # setup one buffer per attribute location + # setup one buffer per attribute-location-type var bufferSize = 0'u64 for mesh in nonIndexedMeshes & allIndexedMeshes: bufferSize += mesh.vertexDataSize diff -r 2780d9aad142 -r dfaddaf96f09 src/semicongine/vulkan/descriptor.nim --- a/src/semicongine/vulkan/descriptor.nim Thu Apr 06 00:30:56 2023 +0700 +++ b/src/semicongine/vulkan/descriptor.nim Fri Apr 07 00:32:07 2023 +0700 @@ -6,12 +6,12 @@ import ./utils type - Descriptor* = object # "fields" of a DescriptorSet + Descriptor* = object # "fields" of a DescriptorSetLayout thetype*: VkDescriptorType count*: uint32 stages*: seq[VkShaderStageFlagBits] itemsize*: uint32 - DescriptorSetLayout* = object # "type description of a DescriptorSet + DescriptorSetLayout* = object # "type-description" of a DescriptorSet device: Device vk*: VkDescriptorSetLayout descriptors*: seq[Descriptor] diff -r 2780d9aad142 -r dfaddaf96f09 src/semicongine/vulkan/shader.nim --- a/src/semicongine/vulkan/shader.nim Thu Apr 06 00:30:56 2023 +0700 +++ b/src/semicongine/vulkan/shader.nim Fri Apr 07 00:32:07 2023 +0700 @@ -157,14 +157,14 @@ inputRate: if attribute.perInstance: VK_VERTEX_INPUT_RATE_INSTANCE else: VK_VERTEX_INPUT_RATE_VERTEX, ) # allows to submit larger data structures like Mat44, for most other types will be 1 - for i in 0 ..< attribute.rows: + for i in 0 ..< attribute.thetype.numberOfVertexInputAttributeDescriptors: attributes.add VkVertexInputAttributeDescription( binding: binding, location: location, - format: getVkFormat(attribute), - offset: i * attribute.size(perRow=true), + format: attribute.thetype.getVkFormat, + offset: i * attribute.size(perDescriptor=true), ) - location += attribute.nLocationSlots + location += attribute.thetype.nLocationSlots inc binding return VkPipelineVertexInputStateCreateInfo( diff -r 2780d9aad142 -r dfaddaf96f09 tests/test_vulkan_wrapper.nim --- a/tests/test_vulkan_wrapper.nim Thu Apr 06 00:30:56 2023 +0700 +++ b/tests/test_vulkan_wrapper.nim Fri Apr 07 00:32:07 2023 +0700 @@ -56,11 +56,11 @@ # INIT RENDERER: const vertexInput = initAttributeGroup( - asAttribute(default(Vec3f), "position"), - asAttribute(default(Vec3f), "color"), + attr[Vec3f]("position"), + attr[Vec3f]("color"), ) - vertexOutput = initAttributeGroup(asAttribute(default(Vec3f), "outcolor")) - fragOutput = initAttributeGroup(asAttribute(default(Vec4f), "color")) + vertexOutput = initAttributeGroup(attr[Vec3f]("outcolor")) + fragOutput = initAttributeGroup(attr[Vec4f]("color")) vertexCode = compileGlslShader( stage=VK_SHADER_STAGE_VERTEX_BIT, inputs=vertexInput,