# HG changeset patch # User Sam # Date 1681062796 -25200 # Node ID 9e7bcc8e0e529ab147376d3c2ddd45a831164595 # Parent 90537a8887ae186aa6176ca92a3919c863f54ac6 did: refactor mesh code, prepare for instance-data diff -r 90537a8887ae -r 9e7bcc8e0e52 src/semicongine/gpu_data.nim --- a/src/semicongine/gpu_data.nim Sun Apr 09 01:04:54 2023 +0700 +++ b/src/semicongine/gpu_data.nim Mon Apr 10 00:53:16 2023 +0700 @@ -6,9 +6,7 @@ import ./math type - 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 + 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] DataType* = enum Float32 Float64 @@ -96,6 +94,51 @@ of Mat43F64: mat43f64: TMat43[float64] of Mat4F32: mat4f32: TMat4[float32] of Mat4F64: mat4f64: TMat4[float64] + DataList* = object + len*: uint32 + case thetype*: DataType + of Float32: float32: seq[float32] + of Float64: float64: seq[float64] + of Int8: int8: seq[int8] + of Int16: int16: seq[int16] + of Int32: int32: seq[int32] + of Int64: int64: seq[int64] + of UInt8: uint8: seq[uint8] + of UInt16: uint16: seq[uint16] + of UInt32: uint32: seq[uint32] + of UInt64: uint64: seq[uint64] + of Vec2I32: vec2i32: seq[TVec2[int32]] + of Vec2I64: vec2i64: seq[TVec2[int64]] + of Vec3I32: vec3i32: seq[TVec3[int32]] + of Vec3I64: vec3i64: seq[TVec3[int64]] + of Vec4I32: vec4i32: seq[TVec4[int32]] + of Vec4I64: vec4i64: seq[TVec4[int64]] + of Vec2U32: vec2u32: seq[TVec2[uint32]] + of Vec2U64: vec2u64: seq[TVec2[uint64]] + of Vec3U32: vec3u32: seq[TVec3[uint32]] + of Vec3U64: vec3u64: seq[TVec3[uint64]] + of Vec4U32: vec4u32: seq[TVec4[uint32]] + of Vec4U64: vec4u64: seq[TVec4[uint64]] + of Vec2F32: vec2f32: seq[TVec2[float32]] + of Vec2F64: vec2f64: seq[TVec2[float64]] + of Vec3F32: vec3f32: seq[TVec3[float32]] + of Vec3F64: vec3f64: seq[TVec3[float64]] + of Vec4F32: vec4f32: seq[TVec4[float32]] + of Vec4F64: vec4f64: seq[TVec4[float64]] + of Mat2F32: mat2f32: seq[TMat2[float32]] + of Mat2F64: mat2f64: seq[TMat2[float64]] + of Mat23F32: mat23f32: seq[TMat23[float32]] + of Mat23F64: mat23f64: seq[TMat23[float64]] + of Mat32F32: mat32f32: seq[TMat32[float32]] + of Mat32F64: mat32f64: seq[TMat32[float64]] + of Mat3F32: mat3f32: seq[TMat3[float32]] + of Mat3F64: mat3f64: seq[TMat3[float64]] + of Mat34F32: mat34f32: seq[TMat34[float32]] + of Mat34F64: mat34f64: seq[TMat34[float64]] + of Mat43F32: mat43f32: seq[TMat43[float32]] + of Mat43F64: mat43f64: seq[TMat43[float64]] + of Mat4F32: mat4f32: seq[TMat4[float32]] + of Mat4F64: mat4f64: seq[TMat4[float64]] MemoryLocation* = enum VRAM, VRAMVisible, RAM # VRAM is fastest, VRAMVisible allows updating memory directly, may be slower ShaderAttribute* = object @@ -166,7 +209,7 @@ of Mat43F64: 92 of Mat4F32: 64 of Mat4F64: 128 - + func size*(attribute: ShaderAttribute, perDescriptor=false): uint32 = if perDescriptor: attribute.thetype.size div attribute.thetype.numberOfVertexInputAttributeDescriptors else: attribute.thetype.size @@ -175,6 +218,12 @@ for attribute in thetype: result += attribute.size +func size*(value: DataValue): uint32 = + value.thetype.size + +func size*(value: DataList): uint32 = + value.thetype.size * value.len + func getDataType*[T: GPUType|int|uint|float](): DataType = when T is float32: Float32 elif T is float64: Float64 @@ -290,7 +339,57 @@ elif T is TMat4[float32]: value.mat4f32 elif T is TMat4[float64]: value.mat4f64 -proc getRawData*(value: var DataValue): (pointer, uint64) = +func get*[T: GPUType|int|uint|float](value: DataList): seq[T] = + when T is float32: value.float32 + elif T is float64: value.float64 + elif T is int8: value.int8 + elif T is int16: value.int16 + elif T is int32: value.int32 + elif T is int64: value.int64 + elif T is uint8: value.uint8 + elif T is uint16: value.uint16 + elif T is uint32: value.uint32 + elif T is uint64: value.uint64 + elif T is int and sizeof(int) == sizeof(int32): value.int32 + elif T is int and sizeof(int) == sizeof(int64): value.int64 + elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32 + elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64 + elif T is float and sizeof(float) == sizeof(float32): value.float32 + elif T is float and sizeof(float) == sizeof(float64): value.float64 + elif T is TVec2[int32]: value.vec2i32 + elif T is TVec2[int64]: value.vec2i64 + elif T is TVec3[int32]: value.vec3i32 + elif T is TVec3[int64]: value.vec3i64 + elif T is TVec4[int32]: value.vec4i32 + elif T is TVec4[int64]: value.vec4i64 + elif T is TVec2[uint32]: value.vec2u32 + elif T is TVec2[uint64]: value.vec2u64 + elif T is TVec3[uint32]: value.vec3u32 + elif T is TVec3[uint64]: value.vec3u64 + elif T is TVec4[uint32]: value.vec4u32 + elif T is TVec4[uint64]: value.vec4u64 + elif T is TVec2[float32]: value.vec2f32 + elif T is TVec2[float64]: value.vec2f64 + elif T is TVec3[float32]: value.vec3f32 + elif T is TVec3[float64]: value.vec3f64 + elif T is TVec4[float32]: value.vec4f32 + elif T is TVec4[float64]: value.vec4f64 + elif T is TMat2[float32]: value.mat2f32 + elif T is TMat2[float64]: value.mat2f64 + elif T is TMat23[float32]: value.mat23f + elif T is TMat23[float64]: value.mat23f64 + elif T is TMat32[float32]: value.mat32f32 + elif T is TMat32[float64]: value.mat32f64 + elif T is TMat3[float32]: value.mat3f32 + elif T is TMat3[float64]: value.mat3f64 + elif T is TMat34[float32]: value.mat34f32 + elif T is TMat34[float64]: value.mat34f64 + elif T is TMat43[float32]: value.mat43f32 + elif T is TMat43[float64]: value.mat43f64 + elif T is TMat4[float32]: value.mat4f32 + elif T is TMat4[float64]: value.mat4f64 + +func getRawData*(value: var DataValue): (pointer, uint32) = result[1] = value.thetype.size case value.thetype of Float32: result[0] = addr value.float32 @@ -336,6 +435,52 @@ of Mat4F32: result[0] = addr value.mat4f32 of Mat4F64: result[0] = addr value.mat4f64 +func getRawData*(value: var DataList): (pointer, uint32) = + result[1] = value.thetype.size * value.len + case value.thetype + of Float32: result[0] = addr value.float32[0] + of Float64: result[0] = addr value.float64[0] + of Int8: result[0] = addr value.int8[0] + of Int16: result[0] = addr value.int16[0] + of Int32: result[0] = addr value.int32[0] + of Int64: result[0] = addr value.int64[0] + of UInt8: result[0] = addr value.uint8[0] + of UInt16: result[0] = addr value.uint16[0] + of UInt32: result[0] = addr value.uint32[0] + of UInt64: result[0] = addr value.uint64[0] + of Vec2I32: result[0] = addr value.vec2i32[0] + of Vec2I64: result[0] = addr value.vec2i64[0] + of Vec3I32: result[0] = addr value.vec3i32[0] + of Vec3I64: result[0] = addr value.vec3i64[0] + of Vec4I32: result[0] = addr value.vec4i32[0] + of Vec4I64: result[0] = addr value.vec4i64[0] + of Vec2U32: result[0] = addr value.vec2u32[0] + of Vec2U64: result[0] = addr value.vec2u64[0] + of Vec3U32: result[0] = addr value.vec3u32[0] + of Vec3U64: result[0] = addr value.vec3u64[0] + of Vec4U32: result[0] = addr value.vec4u32[0] + of Vec4U64: result[0] = addr value.vec4u64[0] + of Vec2F32: result[0] = addr value.vec2f32[0] + of Vec2F64: result[0] = addr value.vec2f64[0] + of Vec3F32: result[0] = addr value.vec3f32[0] + of Vec3F64: result[0] = addr value.vec3f64[0] + of Vec4F32: result[0] = addr value.vec4f32[0] + of Vec4F64: result[0] = addr value.vec4f64[0] + of Mat2F32: result[0] = addr value.mat2f32[0] + of Mat2F64: result[0] = addr value.mat2f64[0] + of Mat23F32: result[0] = addr value.mat23f32[0] + of Mat23F64: result[0] = addr value.mat23f64[0] + of Mat32F32: result[0] = addr value.mat32f32[0] + of Mat32F64: result[0] = addr value.mat32f64[0] + of Mat3F32: result[0] = addr value.mat3f32[0] + of Mat3F64: result[0] = addr value.mat3f64[0] + of Mat34F32: result[0] = addr value.mat34f32[0] + of Mat34F64: result[0] = addr value.mat34f64[0] + of Mat43F32: result[0] = addr value.mat43f32[0] + of Mat43F64: result[0] = addr value.mat43f64[0] + of Mat4F32: result[0] = addr value.mat4f32[0] + of Mat4F64: result[0] = addr value.mat4f64[0] + func setValue*[T: GPUType|int|uint|float](value: var DataValue, data: T) = when T is float32: value.float32 = data elif T is float64: value.float64 = data @@ -386,6 +531,107 @@ elif T is TMat4[float32]: value.mat4f32 = data elif T is TMat4[float64]: value.mat4f64 = data +func setValues*[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) = + value.len = uint32(data.len) + when T is float32: value.float32 = data + elif T is float64: value.float64 = data + elif T is int8: value.int8 = data + elif T is int16: value.int16 = data + elif T is int32: value.int32 = data + elif T is int64: value.int64 = data + elif T is uint8: value.uint8 = data + elif T is uint16: value.uint16 = data + elif T is uint32: value.uint32 = data + elif T is uint64: value.uint64 = data + elif T is int and sizeof(int) == sizeof(int32): value.int32 = data + elif T is int and sizeof(int) == sizeof(int64): value.int64 = data + elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32 = data + elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64 = data + elif T is float and sizeof(float) == sizeof(float32): value.float32 = data + elif T is float and sizeof(float) == sizeof(float64): value.float64 = data + elif T is TVec2[int32]: value.vec2i32 = data + elif T is TVec2[int64]: value.vec2i64 = data + elif T is TVec3[int32]: value.vec3i32 = data + elif T is TVec3[int64]: value.vec3i64 = data + elif T is TVec4[int32]: value.vec4i32 = data + elif T is TVec4[int64]: value.vec4i64 = data + elif T is TVec2[uint32]: value.vec2u32 = data + elif T is TVec2[uint64]: value.vec2u64 = data + elif T is TVec3[uint32]: value.vec3u32 = data + elif T is TVec3[uint64]: value.vec3u64 = data + elif T is TVec4[uint32]: value.vec4u32 = data + elif T is TVec4[uint64]: value.vec4u64 = data + elif T is TVec2[float32]: value.vec2f32 = data + elif T is TVec2[float64]: value.vec2f64 = data + elif T is TVec3[float32]: value.vec3f32 = data + elif T is TVec3[float64]: value.vec3f64 = data + elif T is TVec4[float32]: value.vec4f32 = data + elif T is TVec4[float64]: value.vec4f64 = data + elif T is TMat2[float32]: value.mat2f32 = data + elif T is TMat2[float64]: value.mat2f64 = data + elif T is TMat23[float32]: value.mat23f32 = data + elif T is TMat23[float64]: value.mat23f64 = data + elif T is TMat32[float32]: value.mat32f32 = data + elif T is TMat32[float64]: value.mat32f64 = data + elif T is TMat3[float32]: value.mat3f32 = data + elif T is TMat3[float64]: value.mat3f64 = data + elif T is TMat34[float32]: value.mat34f32 = data + elif T is TMat34[float64]: value.mat34f64 = data + elif T is TMat43[float32]: value.mat43f32 = data + elif T is TMat43[float64]: value.mat43f64 = data + elif T is TMat4[float32]: value.mat4f32 = data + elif T is TMat4[float64]: value.mat4f64 = data +func setValue*[T: GPUType|int|uint|float](value: var DataList, i: uint32, data: T) = + assert i < value.len + when T is float32: value.float32[i] = data + elif T is float64: value.float64[i] = data + elif T is int8: value.int8[i] = data + elif T is int16: value.int16[i] = data + elif T is int32: value.int32[i] = data + elif T is int64: value.int64[i] = data + elif T is uint8: value.uint8[i] = data + elif T is uint16: value.uint16[i] = data + elif T is uint32: value.uint32[i] = data + elif T is uint64: value.uint64[i] = data + elif T is int and sizeof(int) == sizeof(int32): value.int32[i] = data + elif T is int and sizeof(int) == sizeof(int64): value.int64[i] = data + elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[i] = data + elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[i] = data + elif T is float and sizeof(float) == sizeof(float32): value.float32[i] = data + elif T is float and sizeof(float) == sizeof(float64): value.float64[i] = data + elif T is TVec2[int32]: value.vec2i32[i] = data + elif T is TVec2[int64]: value.vec2i64[i] = data + elif T is TVec3[int32]: value.vec3i32[i] = data + elif T is TVec3[int64]: value.vec3i64[i] = data + elif T is TVec4[int32]: value.vec4i32[i] = data + elif T is TVec4[int64]: value.vec4i64[i] = data + elif T is TVec2[uint32]: value.vec2u32[i] = data + elif T is TVec2[uint64]: value.vec2u64[i] = data + elif T is TVec3[uint32]: value.vec3u32[i] = data + elif T is TVec3[uint64]: value.vec3u64[i] = data + elif T is TVec4[uint32]: value.vec4u32[i] = data + elif T is TVec4[uint64]: value.vec4u64[i] = data + elif T is TVec2[float32]: value.vec2f32[i] = data + elif T is TVec2[float64]: value.vec2f64[i] = data + elif T is TVec3[float32]: value.vec3f32[i] = data + elif T is TVec3[float64]: value.vec3f64[i] = data + elif T is TVec4[float32]: value.vec4f32[i] = data + elif T is TVec4[float64]: value.vec4f64[i] = data + elif T is TMat2[float32]: value.mat2f32[i] = data + elif T is TMat2[float64]: value.mat2f64[i] = data + elif T is TMat23[float32]: value.mat23f32[i] = data + elif T is TMat23[float64]: value.mat23f64[i] = data + elif T is TMat32[float32]: value.mat32f32[i] = data + elif T is TMat32[float64]: value.mat32f64[i] = data + elif T is TMat3[float32]: value.mat3f32[i] = data + elif T is TMat3[float64]: value.mat3f64[i] = data + elif T is TMat34[float32]: value.mat34f32[i] = data + elif T is TMat34[float64]: value.mat34f64[i] = data + elif T is TMat43[float32]: value.mat43f32[i] = data + elif T is TMat43[float64]: value.mat43f64[i] = data + elif T is TMat4[float32]: value.mat4f32[i] = data + elif T is TMat4[float64]: value.mat4f64[i] = data + const TYPEMAP = { Float32: VK_FORMAT_R32_SFLOAT, Float64: VK_FORMAT_R64_SFLOAT, diff -r 90537a8887ae -r 9e7bcc8e0e52 src/semicongine/mesh.nim --- a/src/semicongine/mesh.nim Sun Apr 09 01:04:54 2023 +0700 +++ b/src/semicongine/mesh.nim Mon Apr 10 00:53:16 2023 +0700 @@ -4,36 +4,28 @@ import std/strformat import std/sequtils -import ./vulkan/utils import ./vulkan/api import ./gpu_data import ./entity import ./math type - SurfaceDataType = enum - Position, Color, Normal, Tangent, BiTangent, TextureCoordinate MeshIndexType* = enum None 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 - case thetype*: SurfaceDataType - of Position: position: seq[Vec3f] - of Color: color: seq[Vec3f] - of Normal: normal: seq[Vec3f] - of Tangent: tangent: seq[Vec3f] - of BiTangent: bitangent: seq[Vec3f] - of TextureCoordinate: texturecoord: seq[Vec2f] Mesh* = ref object of Component vertexCount*: uint32 - data: Table[ShaderAttribute, MeshData] + indicesCount*: uint32 + instanceCount*: uint32 + vertexdata: Table[string, DataList] + instancedata: Table[string, DataList] case indexType*: MeshIndexType of None: discard - of Tiny: tinyIndices*: seq[array[3, uint8]] - of Small: smallIndices*: seq[array[3, uint16]] - of Big: bigIndices*: seq[array[3, uint32]] + of Tiny: tinyIndices: seq[array[3, uint8]] + of Small: smallIndices: seq[array[3, uint16]] + of Big: bigIndices: seq[array[3, uint32]] converter toVulkan*(indexType: MeshIndexType): VkIndexType = case indexType: @@ -42,139 +34,96 @@ of Small: VK_INDEX_TYPE_UINT16 of Big: VK_INDEX_TYPE_UINT32 -func indicesCount*(mesh: Mesh): uint32 = - case mesh.indexType: - of None: 0 - of Tiny: mesh.tinyIndices.len * 3 - of Small: mesh.smallIndices.len * 3 - of Big: mesh.bigIndices.len * 3 - method `$`*(mesh: Mesh): string = &"Mesh ({mesh.vertexCount})" -func newMesh*(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[attr[Vec3f]("position")] = MeshData(thetype: Position, position: positions.toSeq) - if colors.len > 0: - 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 = +func newMesh*( + positions: openArray[Vec3f], + indices: openArray[array[3, uint32|int32|uint16|int16|int]], + colors: openArray[Vec3f]=[], + instances=1'u32, + autoResize=true +): auto = assert colors.len == 0 or colors.len == positions.len result = new Mesh result.vertexCount = uint32(positions.len) - result.data[attr[Vec3f]("position")] = MeshData(thetype: Position, position: positions.toSeq) + result.indicesCount = uint32(indices.len * 3) + result.instanceCount = instances + result.vertexdata["position"] = DataList(thetype: Vec3F32) + setValues(result.vertexdata["position"], positions.toSeq) if colors.len > 0: - result.data[attr[Vec3f]("color")] = MeshData(thetype: Color, color: colors.toSeq) + result.vertexdata["color"] = DataList(thetype: Vec3F32) + setValues(result.vertexdata["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 - result.indexType = Tiny - for i, tri in enumerate(indices): - result.tinyIndices.add [uint8(tri[0]), uint8(tri[1]), uint8(tri[2])] - elif autoResize and uint32(positions.len) < uint32(high(uint16)): - result.indexType = Small - for i, tri in enumerate(indices): - result.smallIndices.add [uint16(tri[0]), uint16(tri[1]), uint16(tri[2])] + if indices.len == 0: + result.indexType = None else: - result.indexType = Big - for i, tri in enumerate(indices): - result.bigIndices.add [uint32(tri[0]), uint32(tri[1]), uint32(tri[2])] - -func newMesh*(positions: openArray[Vec3f], colors: openArray[Vec3f]=[], indices: openArray[array[3, uint16|int16]]): auto = - assert colors.len == 0 or colors.len == positions.len - - result = new Mesh - result.vertexCount = uint32(positions.len) - result.data[attr[Vec3f]("position")] = MeshData(thetype: Position, position: positions.toSeq) - if colors.len > 0: - result.data[attr[Vec3f]("color")] = MeshData(thetype: Color, color: colors.toSeq) - - for i in indices: - assert i[0] < result.vertexCount - assert i[1] < result.vertexCount - assert i[2] < result.vertexCount - result.indexType = Small - for i, tri in enumerate(indices): - result.smallIndices.add [uint16(tri[0]), uint16(tri[1]), uint16(tri[2])] + 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])] + elif autoResize and uint32(positions.len) < uint32(high(uint16)): + result.indexType = Small + for i, tri in enumerate(indices): + result.smallIndices.add [uint16(tri[0]), uint16(tri[1]), uint16(tri[2])] + else: + result.indexType = Big + for i, tri in enumerate(indices): + result.bigIndices.add [uint32(tri[0]), uint32(tri[1]), uint32(tri[2])] -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 - - result = new Mesh - result.vertexCount = uint32(positions.len) - result.data[attr[Vec3f]("position")] = MeshData(thetype: Position, position: positions.toSeq) - if colors.len > 0: - result.data[attr[Vec3f]("color")] = MeshData(thetype: Color, color: colors.toSeq) - - for i in indices: - assert i[0] < result.vertexCount - assert i[1] < result.vertexCount - assert i[2] < result.vertexCount - result.indexType = Tiny - for i, tri in enumerate(indices): - result.smallIndices.add [uint8(tri[0]), uint8(tri[1]), uint8(tri[2])] +func newMesh*( + positions: openArray[Vec3f], + colors: openArray[Vec3f]=[], + instances=1'u32, +): auto = + newMesh(positions, newSeq[array[3, int]](), colors, instances) +func vertexDataSize*(mesh: Mesh): uint32 = + for d in mesh.vertexdata.values: + result += d.size -func meshDataSize*(meshdata: MeshData): uint64 = - case meshdata.thetype: - of Position: meshdata.position.size - of Color: meshdata.color.size - of Normal: meshdata.normal.size - of Tangent: meshdata.tangent.size - of BiTangent: meshdata.bitangent.size - of TextureCoordinate: meshdata.texturecoord.size - -func attributeSize*(mesh: Mesh, attribute: ShaderAttribute): uint64 = - mesh.data[attribute].meshDataSize - -func vertexDataSize*(mesh: Mesh): uint64 = - for d in mesh.data.values: - result += d.meshDataSize - -func indexDataSize*(mesh: Mesh): uint64 = +func indexDataSize*(mesh: Mesh): uint32 = case mesh.indexType of None: 0 of Tiny: mesh.tinyIndices.len * sizeof(get(genericParams(typeof(mesh.tinyIndices)), 0)) of Small: mesh.smallIndices.len * sizeof(get(genericParams(typeof(mesh.smallIndices)), 0)) of Big: mesh.bigIndices.len * sizeof(get(genericParams(typeof(mesh.bigIndices)), 0)) -proc rawData[T: seq](value: var T): (pointer, uint64) = - (pointer(addr(value[0])), uint64(sizeof(get(genericParams(typeof(value)), 0)) * value.len)) +func instanceDataSize*(mesh: Mesh): uint32 = + for d in mesh.instancedata.values: + result += d.size -proc getRawData(data: var MeshData): (pointer, uint64) = - case data.thetype: - of Position: rawData(data.position) - of Color: rawData(data.color) - of Normal: rawData(data.normal) - of Tangent: rawData(data.tangent) - of BiTangent: rawData(data.bitangent) - of TextureCoordinate: rawData(data.texturecoord) +func rawData[T: seq](value: var T): (pointer, uint32) = + (pointer(addr(value[0])), uint32(sizeof(get(genericParams(typeof(value)), 0)) * value.len)) -proc getRawIndexData*(mesh: Mesh): (pointer, uint64) = +func getRawIndexData*(mesh: Mesh): (pointer, uint32) = case mesh.indexType: of None: raise newException(Exception, "Trying to get index data for non-indexed mesh") of Tiny: rawData(mesh.tinyIndices) of Small: rawData(mesh.smallIndices) of Big: rawData(mesh.bigIndices) -proc hasDataFor*(mesh: Mesh, attribute: ShaderAttribute): bool = - assert attribute.perInstance == false, "Mesh data cannot handle per-instance attributes" - attribute in mesh.data +func hasVertexDataFor*(mesh: Mesh, attribute: string): bool = + attribute in mesh.vertexdata + +func hasInstanceDataFor*(mesh: Mesh, attribute: string): bool = + attribute in mesh.instancedata + +func getRawVertexData*(mesh: Mesh, attribute: string): (pointer, uint32) = + mesh.vertexdata[attribute].getRawData() -proc getRawData*(mesh: Mesh, attribute: ShaderAttribute): (pointer, uint64) = - assert attribute.perInstance == false, "Mesh data cannot handle per-instance attributes" - mesh.data[attribute].getRawData() +func getRawInstanceData*(mesh: Mesh, attribute: string): (pointer, uint32) = + mesh.instancedata[attribute].getRawData() -proc getData*(mesh: Mesh, attribute: ShaderAttribute): MeshData = - assert attribute.perInstance == false, "Mesh data cannot handle per-instance attributes" - mesh.data[attribute] +proc setInstanceData*[T: GPUType|int|uint|float](mesh: var Mesh, attribute: string, data: seq[T]) = + assert uint32(data.len) == mesh.instanceCount + assert not (attribute in mesh.instancedata) + mesh.instancedata[attribute] = DataList(thetype: getDataType[T]()) + setValues(mesh.instancedata[attribute], data) diff -r 90537a8887ae -r 9e7bcc8e0e52 src/semicongine/scene.nim --- a/src/semicongine/scene.nim Sun Apr 09 01:04:54 2023 +0700 +++ b/src/semicongine/scene.nim Mon Apr 10 00:53:16 2023 +0700 @@ -46,7 +46,7 @@ value.setValue(data) ShaderGlobal(name: name, value: value) -proc getBuffers*(scene: Scene, pipeline: VkPipeline): seq[Buffer] = +func getBuffers*(scene: Scene, pipeline: VkPipeline): seq[Buffer] = var counted: seq[VkBuffer] for drawable in scene.drawables[pipeline]: if not (drawable.buffer.vk in counted): @@ -80,7 +80,7 @@ allIndexedMeshes: seq[Mesh] for mesh in allComponentsOfType[Mesh](scene.root): for inputAttr in pipeline.inputs.vertexInputs: - assert mesh.hasDataFor(inputAttr), &"{mesh} missing data for {inputAttr}" + assert mesh.hasVertexDataFor(inputAttr.name), &"{mesh} missing data for {inputAttr}" case mesh.indexType: of None: nonIndexedMeshes.add mesh of Tiny: tinyIndexedMeshes.add mesh @@ -120,6 +120,7 @@ mappable=location in [VRAMVisible, RAM], ) + # TODO: gather instance data/buffers # non-indexed mesh drawable if nonIndexedMeshes.len > 0: var vertexCount = 0'u32 @@ -127,11 +128,16 @@ vertexCount += mesh.vertexCount # remark: we merge all meshes into a single drawcall... smart?# # I think bad for instancing... - var nonIndexedDrawable = Drawable(elementCount: vertexCount, buffer: buffer, indexed: false, instanceCount: 1) + var nonIndexedDrawable = Drawable( + elementCount: vertexCount, + buffer: buffer, + indexed: false, + instanceCount: 1 + ) for inputAttr in attributes: nonIndexedDrawable.offsets.add bufferOffset for mesh in nonIndexedMeshes: - var (pdata, size) = mesh.getRawData(inputAttr) + var (pdata, size) = mesh.getRawVertexData(inputAttr.name) buffer.setData(pdata, size, bufferOffset) bufferOffset += size scene.drawables[pipeline.vk].add nonIndexedDrawable @@ -152,7 +158,7 @@ indexOffset += size for inputAttr in attributes: drawable.offsets.add bufferOffset - var (pdata, size) = mesh.getRawData(inputAttr) + var (pdata, size) = mesh.getRawVertexData(inputAttr.name) buffer.setData(pdata, size, bufferOffset) bufferOffset += size scene.drawables[pipeline.vk].add drawable @@ -162,5 +168,5 @@ for pipeline in subpass.pipelines: scene.setupDrawables(pipeline) -proc getDrawables*(scene: Scene, pipeline: Pipeline): seq[Drawable] = +func getDrawables*(scene: Scene, pipeline: Pipeline): seq[Drawable] = scene.drawables.getOrDefault(pipeline.vk, @[]) diff -r 90537a8887ae -r 9e7bcc8e0e52 tests/test_vulkan_wrapper.nim --- a/tests/test_vulkan_wrapper.nim Sun Apr 09 01:04:54 2023 +0700 +++ b/tests/test_vulkan_wrapper.nim Mon Apr 10 00:53:16 2023 +0700 @@ -57,7 +57,7 @@ vertexInput = @[ attr[Vec3f]("position"), attr[Vec3f]("color"), - attr[Mat4]("transform", perInstance=true) + attr[Vec3f]("translate", perInstance=true) ] vertexOutput = @[attr[Vec3f]("outcolor")] uniforms = @[attr[float32]("time")] @@ -87,6 +87,7 @@ # INIT SCENE var time = initShaderGlobal("time", 0.0'f32) + #[ var thescene = Scene( name: "main", root: newEntity("root", @@ -123,6 +124,19 @@ )), ) ) + ]# + var mymesh = newMesh( + 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)], + ) + setInstanceData[Vec3f](mymesh, "translate", @[newVec3f(0.3, 0.3)]) + var thescene = Scene( + name: "main", + root: newEntity("root", + newEntity("stuff", time), + newEntity("triangle", mymesh), + ) + ) thescene.setupDrawables(renderPass) swapchain.setupUniforms(thescene)