changeset 808:12f7f8a4f726

add: a few API improvments, add mesh-conversion method
author Sam <sam@basx.dev>
date Thu, 14 Sep 2023 23:59:10 +0700
parents 5a301dbdfbc1
children fe5aced90cb2
files src/semicongine/core.nim src/semicongine/core/dynamic_arrays.nim src/semicongine/core/gpu_data.nim src/semicongine/core/gpu_types.nim src/semicongine/core/materials.nim src/semicongine/core/matrix.nim src/semicongine/mesh.nim src/semicongine/resources/mesh.nim
diffstat 8 files changed, 1133 insertions(+), 1286 deletions(-) [+]
line wrap: on
line diff
--- a/src/semicongine/core.nim	Mon Sep 11 23:15:25 2023 +0700
+++ b/src/semicongine/core.nim	Thu Sep 14 23:59:10 2023 +0700
@@ -6,7 +6,8 @@
 import ./core/vulkanapi
 import ./core/buildconfig
 import ./core/color
-import ./core/gpu_data
+import ./core/gpu_types
+import ./core/dynamic_arrays
 import ./core/imagetypes
 import ./core/matrix
 import ./core/vector
@@ -17,7 +18,8 @@
 export fonttypes
 export buildconfig
 export color
-export gpu_data
+export gpu_types
+export dynamic_arrays
 export imagetypes
 export matrix
 export vector
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/semicongine/core/dynamic_arrays.nim	Thu Sep 14 23:59:10 2023 +0700
@@ -0,0 +1,674 @@
+import ./gpu_types
+import ./vector
+import ./matrix
+import ./utils
+import ./imagetypes
+
+type
+  DataList* = object
+    len*: int
+    case theType*: DataType
+    of Float32: float32: ref seq[float32]
+    of Float64: float64: ref seq[float64]
+    of Int8: int8: ref seq[int8]
+    of Int16: int16: ref seq[int16]
+    of Int32: int32: ref seq[int32]
+    of Int64: int64: ref seq[int64]
+    of UInt8: uint8: ref seq[uint8]
+    of UInt16: uint16: ref seq[uint16]
+    of UInt32: uint32: ref seq[uint32]
+    of UInt64: uint64: ref seq[uint64]
+    of Vec2I32: vec2i32: ref seq[TVec2[int32]]
+    of Vec2I64: vec2i64: ref seq[TVec2[int64]]
+    of Vec3I32: vec3i32: ref seq[TVec3[int32]]
+    of Vec3I64: vec3i64: ref seq[TVec3[int64]]
+    of Vec4I32: vec4i32: ref seq[TVec4[int32]]
+    of Vec4I64: vec4i64: ref seq[TVec4[int64]]
+    of Vec2U32: vec2u32: ref seq[TVec2[uint32]]
+    of Vec2U64: vec2u64: ref seq[TVec2[uint64]]
+    of Vec3U32: vec3u32: ref seq[TVec3[uint32]]
+    of Vec3U64: vec3u64: ref seq[TVec3[uint64]]
+    of Vec4U32: vec4u32: ref seq[TVec4[uint32]]
+    of Vec4U64: vec4u64: ref seq[TVec4[uint64]]
+    of Vec2F32: vec2f32: ref seq[TVec2[float32]]
+    of Vec2F64: vec2f64: ref seq[TVec2[float64]]
+    of Vec3F32: vec3f32: ref seq[TVec3[float32]]
+    of Vec3F64: vec3f64: ref seq[TVec3[float64]]
+    of Vec4F32: vec4f32: ref seq[TVec4[float32]]
+    of Vec4F64: vec4f64: ref seq[TVec4[float64]]
+    of Mat2F32: mat2f32: ref seq[TMat2[float32]]
+    of Mat2F64: mat2f64: ref seq[TMat2[float64]]
+    of Mat23F32: mat23f32: ref seq[TMat23[float32]]
+    of Mat23F64: mat23f64: ref seq[TMat23[float64]]
+    of Mat32F32: mat32f32: ref seq[TMat32[float32]]
+    of Mat32F64: mat32f64: ref seq[TMat32[float64]]
+    of Mat3F32: mat3f32: ref seq[TMat3[float32]]
+    of Mat3F64: mat3f64: ref seq[TMat3[float64]]
+    of Mat34F32: mat34f32: ref seq[TMat34[float32]]
+    of Mat34F64: mat34f64: ref seq[TMat34[float64]]
+    of Mat43F32: mat43f32: ref seq[TMat43[float32]]
+    of Mat43F64: mat43f64: ref seq[TMat43[float64]]
+    of Mat4F32: mat4f32: ref seq[TMat4[float32]]
+    of Mat4F64: mat4f64: ref seq[TMat4[float64]]
+    of Sampler2D: texture: ref seq[Texture]
+
+func size*(value: DataList): int =
+  value.theType.size * value.len
+
+func `==`*(a, b: DataList): bool =
+  if a.theType != b.theType:
+    return false
+  case a.theType
+    of Float32: return a.float32 == b.float32
+    of Float64: return a.float64 == b.float64
+    of Int8: return a.int8 == b.int8
+    of Int16: return a.int16 == b.int16
+    of Int32: return a.int32 == b.int32
+    of Int64: return a.int64 == b.int64
+    of UInt8: return a.uint8 == b.uint8
+    of UInt16: return a.uint16 == b.uint16
+    of UInt32: return a.uint32 == b.uint32
+    of UInt64: return a.uint64 == b.uint64
+    of Vec2I32: return a.vec2i32 == b.vec2i32
+    of Vec2I64: return a.vec2i64 == b.vec2i64
+    of Vec3I32: return a.vec3i32 == b.vec3i32
+    of Vec3I64: return a.vec3i64 == b.vec3i64
+    of Vec4I32: return a.vec4i32 == b.vec4i32
+    of Vec4I64: return a.vec4i64 == b.vec4i64
+    of Vec2U32: return a.vec2u32 == b.vec2u32
+    of Vec2U64: return a.vec2u64 == b.vec2u64
+    of Vec3U32: return a.vec3u32 == b.vec3u32
+    of Vec3U64: return a.vec3u64 == b.vec3u64
+    of Vec4U32: return a.vec4u32 == b.vec4u32
+    of Vec4U64: return a.vec4u64 == b.vec4u64
+    of Vec2F32: return a.vec2f32 == b.vec2f32
+    of Vec2F64: return a.vec2f64 == b.vec2f64
+    of Vec3F32: return a.vec3f32 == b.vec3f32
+    of Vec3F64: return a.vec3f64 == b.vec3f64
+    of Vec4F32: return a.vec4f32 == b.vec4f32
+    of Vec4F64: return a.vec4f64 == b.vec4f64
+    of Mat2F32: return a.mat2f32 == b.mat2f32
+    of Mat2F64: return a.mat2f64 == b.mat2f64
+    of Mat23F32: return a.mat23f32 == b.mat23f32
+    of Mat23F64: return a.mat23f64 == b.mat23f64
+    of Mat32F32: return a.mat32f32 == b.mat32f32
+    of Mat32F64: return a.mat32f64 == b.mat32f64
+    of Mat3F32: return a.mat3f32 == b.mat3f32
+    of Mat3F64: return a.mat3f64 == b.mat3f64
+    of Mat34F32: return a.mat34f32 == b.mat34f32
+    of Mat34F64: return a.mat34f64 == b.mat34f64
+    of Mat43F32: return a.mat43f32 == b.mat43f32
+    of Mat43F64: return a.mat43f64 == b.mat43f64
+    of Mat4F32: return a.mat4f32 == b.mat4f32
+    of Mat4F64: return a.mat4f64 == b.mat4f64
+    of Sampler2D: a.texture == b.texture
+
+proc setValues*[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) =
+  value.setLen(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
+  elif T is Texture: value.texture[] = data
+  else: {. error: "Virtual datatype has no values" .}
+
+func newDataList*(theType: DataType): DataList =
+  result = DataList(theType: theType)
+  case result.theType
+    of Float32: result.float32 = new seq[float32]
+    of Float64: result.float64 = new seq[float64]
+    of Int8: result.int8 = new seq[int8]
+    of Int16: result.int16 = new seq[int16]
+    of Int32: result.int32 = new seq[int32]
+    of Int64: result.int64 = new seq[int64]
+    of UInt8: result.uint8 = new seq[uint8]
+    of UInt16: result.uint16 = new seq[uint16]
+    of UInt32: result.uint32 = new seq[uint32]
+    of UInt64: result.uint64 = new seq[uint64]
+    of Vec2I32: result.vec2i32 = new seq[TVec2[int32]]
+    of Vec2I64: result.vec2i64 = new seq[TVec2[int64]]
+    of Vec3I32: result.vec3i32 = new seq[TVec3[int32]]
+    of Vec3I64: result.vec3i64 = new seq[TVec3[int64]]
+    of Vec4I32: result.vec4i32 = new seq[TVec4[int32]]
+    of Vec4I64: result.vec4i64 = new seq[TVec4[int64]]
+    of Vec2U32: result.vec2u32 = new seq[TVec2[uint32]]
+    of Vec2U64: result.vec2u64 = new seq[TVec2[uint64]]
+    of Vec3U32: result.vec3u32 = new seq[TVec3[uint32]]
+    of Vec3U64: result.vec3u64 = new seq[TVec3[uint64]]
+    of Vec4U32: result.vec4u32 = new seq[TVec4[uint32]]
+    of Vec4U64: result.vec4u64 = new seq[TVec4[uint64]]
+    of Vec2F32: result.vec2f32 = new seq[TVec2[float32]]
+    of Vec2F64: result.vec2f64 = new seq[TVec2[float64]]
+    of Vec3F32: result.vec3f32 = new seq[TVec3[float32]]
+    of Vec3F64: result.vec3f64 = new seq[TVec3[float64]]
+    of Vec4F32: result.vec4f32 = new seq[TVec4[float32]]
+    of Vec4F64: result.vec4f64 = new seq[TVec4[float64]]
+    of Mat2F32: result.mat2f32 = new seq[TMat2[float32]]
+    of Mat2F64: result.mat2f64 = new seq[TMat2[float64]]
+    of Mat23F32: result.mat23f32 = new seq[TMat23[float32]]
+    of Mat23F64: result.mat23f64 = new seq[TMat23[float64]]
+    of Mat32F32: result.mat32f32 = new seq[TMat32[float32]]
+    of Mat32F64: result.mat32f64 = new seq[TMat32[float64]]
+    of Mat3F32: result.mat3f32 = new seq[TMat3[float32]]
+    of Mat3F64: result.mat3f64 = new seq[TMat3[float64]]
+    of Mat34F32: result.mat34f32 = new seq[TMat34[float32]]
+    of Mat34F64: result.mat34f64 = new seq[TMat34[float64]]
+    of Mat43F32: result.mat43f32 = new seq[TMat43[float32]]
+    of Mat43F64: result.mat43f64 = new seq[TMat43[float64]]
+    of Mat4F32: result.mat4f32 = new seq[TMat4[float32]]
+    of Mat4F64: result.mat4f64 = new seq[TMat4[float64]]
+    of Sampler2D: result.texture = new seq[Texture]
+
+proc newDataList*[T: GPUType](len=0): DataList =
+  result = newDataList(getDataType[T]())
+  if len > 0:
+    result.setLen(len)
+
+proc newDataList*[T: GPUType](data: seq[T]): DataList =
+  result = newDataList(getDataType[T]())
+  result.setValues(data)
+
+proc toGPUValue*[T: GPUType](value: seq[T]): DataList =
+  result = newDataList[T](value.len)
+  result.setValue(value)
+
+func getValues*[T: GPUType|int|uint|float](value: DataList): ref 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
+  elif T is Texture: value.texture
+  else: {. error: "Virtual datatype has no values" .}
+
+func getValue*[T: GPUType|int|uint|float](value: DataList, i: int): T =
+  when T is float32: value.float32[i]
+  elif T is float64: value.float64[i]
+  elif T is int8: value.int8[i]
+  elif T is int16: value.int16[i]
+  elif T is int32: value.int32[i]
+  elif T is int64: value.int64[i]
+  elif T is uint8: value.uint8[i]
+  elif T is uint16: value.uint16[i]
+  elif T is uint32: value.uint32[i]
+  elif T is uint64: value.uint64[i]
+  elif T is int and sizeof(int) == sizeof(int32): value.int32[i]
+  elif T is int and sizeof(int) == sizeof(int64): value.int64[i]
+  elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[i]
+  elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[i]
+  elif T is float and sizeof(float) == sizeof(float32): value.float32[i]
+  elif T is float and sizeof(float) == sizeof(float64): value.float64[i]
+  elif T is TVec2[int32]: value.vec2i32[i]
+  elif T is TVec2[int64]: value.vec2i64[i]
+  elif T is TVec3[int32]: value.vec3i32[i]
+  elif T is TVec3[int64]: value.vec3i64[i]
+  elif T is TVec4[int32]: value.vec4i32[i]
+  elif T is TVec4[int64]: value.vec4i64[i]
+  elif T is TVec2[uint32]: value.vec2u32[i]
+  elif T is TVec2[uint64]: value.vec2u64[i]
+  elif T is TVec3[uint32]: value.vec3u32[i]
+  elif T is TVec3[uint64]: value.vec3u64[i]
+  elif T is TVec4[uint32]: value.vec4u32[i]
+  elif T is TVec4[uint64]: value.vec4u64[i]
+  elif T is TVec2[float32]: value.vec2f32[i]
+  elif T is TVec2[float64]: value.vec2f64[i]
+  elif T is TVec3[float32]: value.vec3f32[i]
+  elif T is TVec3[float64]: value.vec3f64[i]
+  elif T is TVec4[float32]: value.vec4f32[i]
+  elif T is TVec4[float64]: value.vec4f64[i]
+  elif T is TMat2[float32]: value.mat2f32[i]
+  elif T is TMat2[float64]: value.mat2f64[i]
+  elif T is TMat23[float32]: value.mat23f[i]
+  elif T is TMat23[float64]: value.mat23f64[i]
+  elif T is TMat32[float32]: value.mat32f32[i]
+  elif T is TMat32[float64]: value.mat32f64[i]
+  elif T is TMat3[float32]: value.mat3f32[i]
+  elif T is TMat3[float64]: value.mat3f64[i]
+  elif T is TMat34[float32]: value.mat34f32[i]
+  elif T is TMat34[float64]: value.mat34f64[i]
+  elif T is TMat43[float32]: value.mat43f32[i]
+  elif T is TMat43[float64]: value.mat43f64[i]
+  elif T is TMat4[float32]: value.mat4f32[i]
+  elif T is TMat4[float64]: value.mat4f64[i]
+  elif T is Texture: value.texture[i]
+  else: {. error: "Virtual datatype has no values" .}
+
+func getRawData*(value: var DataList): (pointer, int) =
+  if value.len == 0:
+    return (nil, 0)
+  result[1] = value.theType.size * value.len
+  case value.theType
+    of Float32: result[0] = value.float32[].toCPointer
+    of Float64: result[0] = value.float64[].toCPointer
+    of Int8: result[0] = value.int8[].toCPointer
+    of Int16: result[0] = value.int16[].toCPointer
+    of Int32: result[0] = value.int32[].toCPointer
+    of Int64: result[0] = value.int64[].toCPointer
+    of UInt8: result[0] = value.uint8[].toCPointer
+    of UInt16: result[0] = value.uint16[].toCPointer
+    of UInt32: result[0] = value.uint32[].toCPointer
+    of UInt64: result[0] = value.uint64[].toCPointer
+    of Vec2I32: result[0] = value.vec2i32[].toCPointer
+    of Vec2I64: result[0] = value.vec2i64[].toCPointer
+    of Vec3I32: result[0] = value.vec3i32[].toCPointer
+    of Vec3I64: result[0] = value.vec3i64[].toCPointer
+    of Vec4I32: result[0] = value.vec4i32[].toCPointer
+    of Vec4I64: result[0] = value.vec4i64[].toCPointer
+    of Vec2U32: result[0] = value.vec2u32[].toCPointer
+    of Vec2U64: result[0] = value.vec2u64[].toCPointer
+    of Vec3U32: result[0] = value.vec3u32[].toCPointer
+    of Vec3U64: result[0] = value.vec3u64[].toCPointer
+    of Vec4U32: result[0] = value.vec4u32[].toCPointer
+    of Vec4U64: result[0] = value.vec4u64[].toCPointer
+    of Vec2F32: result[0] = value.vec2f32[].toCPointer
+    of Vec2F64: result[0] = value.vec2f64[].toCPointer
+    of Vec3F32: result[0] = value.vec3f32[].toCPointer
+    of Vec3F64: result[0] = value.vec3f64[].toCPointer
+    of Vec4F32: result[0] = value.vec4f32[].toCPointer
+    of Vec4F64: result[0] = value.vec4f64[].toCPointer
+    of Mat2F32: result[0] = value.mat2f32[].toCPointer
+    of Mat2F64: result[0] = value.mat2f64[].toCPointer
+    of Mat23F32: result[0] = value.mat23f32[].toCPointer
+    of Mat23F64: result[0] = value.mat23f64[].toCPointer
+    of Mat32F32: result[0] = value.mat32f32[].toCPointer
+    of Mat32F64: result[0] = value.mat32f64[].toCPointer
+    of Mat3F32: result[0] = value.mat3f32[].toCPointer
+    of Mat3F64: result[0] = value.mat3f64[].toCPointer
+    of Mat34F32: result[0] = value.mat34f32[].toCPointer
+    of Mat34F64: result[0] = value.mat34f64[].toCPointer
+    of Mat43F32: result[0] = value.mat43f32[].toCPointer
+    of Mat43F64: result[0] = value.mat43f64[].toCPointer
+    of Mat4F32: result[0] = value.mat4f32[].toCPointer
+    of Mat4F64: result[0] = value.mat4f64[].toCPointer
+    of Sampler2D: result[0] = nil
+
+proc setLen*(value: var DataList, len: int) =
+  value.len = len
+  case value.theType
+    of Float32: value.float32[].setLen(len)
+    of Float64: value.float64[].setLen(len)
+    of Int8: value.int8[].setLen(len)
+    of Int16: value.int16[].setLen(len)
+    of Int32: value.int32[].setLen(len)
+    of Int64: value.int64[].setLen(len)
+    of UInt8: value.uint8[].setLen(len)
+    of UInt16: value.uint16[].setLen(len)
+    of UInt32: value.uint32[].setLen(len)
+    of UInt64: value.uint64[].setLen(len)
+    of Vec2I32: value.vec2i32[].setLen(len)
+    of Vec2I64: value.vec2i64[].setLen(len)
+    of Vec3I32: value.vec3i32[].setLen(len)
+    of Vec3I64: value.vec3i64[].setLen(len)
+    of Vec4I32: value.vec4i32[].setLen(len)
+    of Vec4I64: value.vec4i64[].setLen(len)
+    of Vec2U32: value.vec2u32[].setLen(len)
+    of Vec2U64: value.vec2u64[].setLen(len)
+    of Vec3U32: value.vec3u32[].setLen(len)
+    of Vec3U64: value.vec3u64[].setLen(len)
+    of Vec4U32: value.vec4u32[].setLen(len)
+    of Vec4U64: value.vec4u64[].setLen(len)
+    of Vec2F32: value.vec2f32[].setLen(len)
+    of Vec2F64: value.vec2f64[].setLen(len)
+    of Vec3F32: value.vec3f32[].setLen(len)
+    of Vec3F64: value.vec3f64[].setLen(len)
+    of Vec4F32: value.vec4f32[].setLen(len)
+    of Vec4F64: value.vec4f64[].setLen(len)
+    of Mat2F32: value.mat2f32[].setLen(len)
+    of Mat2F64: value.mat2f64[].setLen(len)
+    of Mat23F32: value.mat23f32[].setLen(len)
+    of Mat23F64: value.mat23f64[].setLen(len)
+    of Mat32F32: value.mat32f32[].setLen(len)
+    of Mat32F64: value.mat32f64[].setLen(len)
+    of Mat3F32: value.mat3f32[].setLen(len)
+    of Mat3F64: value.mat3f64[].setLen(len)
+    of Mat34F32: value.mat34f32[].setLen(len)
+    of Mat34F64: value.mat34f64[].setLen(len)
+    of Mat43F32: value.mat43f32[].setLen(len)
+    of Mat43F64: value.mat43f64[].setLen(len)
+    of Mat4F32: value.mat4f32[].setLen(len)
+    of Mat4F64: value.mat4f64[].setLen(len)
+    of Sampler2D: discard
+
+proc appendValues*[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) =
+  value.len += data.len
+  when T is float32: value.float32[].add data
+  elif T is float64: value.float64[].add data
+  elif T is int8: value.int8[].add data
+  elif T is int16: value.int16[].add data
+  elif T is int32: value.int32[].add data
+  elif T is int64: value.int64[].add data
+  elif T is uint8: value.uint8[].add data
+  elif T is uint16: value.uint16[].add data
+  elif T is uint32: value.uint32[].add data
+  elif T is uint64: value.uint64[].add data
+  elif T is int and sizeof(int) == sizeof(int32): value.int32[].add data
+  elif T is int and sizeof(int) == sizeof(int64): value.int64[].add data
+  elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[].add data
+  elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[].add data
+  elif T is float and sizeof(float) == sizeof(float32): value.float32[].add data
+  elif T is float and sizeof(float) == sizeof(float64): value.float64[].add data
+  elif T is TVec2[int32]: value.vec2i32[].add data
+  elif T is TVec2[int64]: value.vec2i64[].add data
+  elif T is TVec3[int32]: value.vec3i32[].add data
+  elif T is TVec3[int64]: value.vec3i64[].add data
+  elif T is TVec4[int32]: value.vec4i32[].add data
+  elif T is TVec4[int64]: value.vec4i64[].add data
+  elif T is TVec2[uint32]: value.vec2u32[].add data
+  elif T is TVec2[uint64]: value.vec2u64[].add data
+  elif T is TVec3[uint32]: value.vec3u32[].add data
+  elif T is TVec3[uint64]: value.vec3u64[].add data
+  elif T is TVec4[uint32]: value.vec4u32[].add data
+  elif T is TVec4[uint64]: value.vec4u64[].add data
+  elif T is TVec2[float32]: value.vec2f32[].add data
+  elif T is TVec2[float64]: value.vec2f64[].add data
+  elif T is TVec3[float32]: value.vec3f32[].add data
+  elif T is TVec3[float64]: value.vec3f64[].add data
+  elif T is TVec4[float32]: value.vec4f32[].add data
+  elif T is TVec4[float64]: value.vec4f64[].add data
+  elif T is TMat2[float32]: value.mat2f32[].add data
+  elif T is TMat2[float64]: value.mat2f64[].add data
+  elif T is TMat23[float32]: value.mat23f32[].add data
+  elif T is TMat23[float64]: value.mat23f64[].add data
+  elif T is TMat32[float32]: value.mat32f32[].add data
+  elif T is TMat32[float64]: value.mat32f64[].add data
+  elif T is TMat3[float32]: value.mat3f32[].add data
+  elif T is TMat3[float64]: value.mat3f64[].add data
+  elif T is TMat34[float32]: value.mat34f32[].add data
+  elif T is TMat34[float64]: value.mat34f64[].add data
+  elif T is TMat43[float32]: value.mat43f32[].add data
+  elif T is TMat43[float64]: value.mat43f64[].add data
+  elif T is TMat4[float32]: value.mat4f32[].add data
+  elif T is TMat4[float64]: value.mat4f64[].add data
+  elif T is Texture: value.texture[].add data
+  else: {. error: "Virtual datatype has no values" .}
+
+proc appendValues*(value: var DataList, data: DataList) =
+  assert value.theType == data.theType
+  value.len += data.len
+  case value.theType:
+  of Float32: value.float32[].add data.float32[]
+  of Float64: value.float64[].add data.float64[]
+  of Int8: value.int8[].add data.int8[]
+  of Int16: value.int16[].add data.int16[]
+  of Int32: value.int32[].add data.int32[]
+  of Int64: value.int64[].add data.int64[]
+  of UInt8: value.uint8[].add data.uint8[]
+  of UInt16: value.uint16[].add data.uint16[]
+  of UInt32: value.uint32[].add data.uint32[]
+  of UInt64: value.uint64[].add data.uint64[]
+  of Vec2I32: value.vec2i32[].add data.vec2i32[]
+  of Vec2I64: value.vec2i64[].add data.vec2i64[]
+  of Vec3I32: value.vec3i32[].add data.vec3i32[]
+  of Vec3I64: value.vec3i64[].add data.vec3i64[]
+  of Vec4I32: value.vec4i32[].add data.vec4i32[]
+  of Vec4I64: value.vec4i64[].add data.vec4i64[]
+  of Vec2U32: value.vec2u32[].add data.vec2u32[]
+  of Vec2U64: value.vec2u64[].add data.vec2u64[]
+  of Vec3U32: value.vec3u32[].add data.vec3u32[]
+  of Vec3U64: value.vec3u64[].add data.vec3u64[]
+  of Vec4U32: value.vec4u32[].add data.vec4u32[]
+  of Vec4U64: value.vec4u64[].add data.vec4u64[]
+  of Vec2F32: value.vec2f32[].add data.vec2f32[]
+  of Vec2F64: value.vec2f64[].add data.vec2f64[]
+  of Vec3F32: value.vec3f32[].add data.vec3f32[]
+  of Vec3F64: value.vec3f64[].add data.vec3f64[]
+  of Vec4F32: value.vec4f32[].add data.vec4f32[]
+  of Vec4F64: value.vec4f64[].add data.vec4f64[]
+  of Mat2F32: value.mat2f32[].add data.mat2f32[]
+  of Mat2F64: value.mat2f64[].add data.mat2f64[]
+  of Mat23F32: value.mat23f32[].add data.mat23f32[]
+  of Mat23F64: value.mat23f64[].add data.mat23f64[]
+  of Mat32F32: value.mat32f32[].add data.mat32f32[]
+  of Mat32F64: value.mat32f64[].add data.mat32f64[]
+  of Mat3F32: value.mat3f32[].add data.mat3f32[]
+  of Mat3F64: value.mat3f64[].add data.mat3f64[]
+  of Mat34F32: value.mat34f32[].add data.mat34f32[]
+  of Mat34F64: value.mat34f64[].add data.mat34f64[]
+  of Mat43F32: value.mat43f32[].add data.mat43f32[]
+  of Mat43F64: value.mat43f64[].add data.mat43f64[]
+  of Mat4F32: value.mat4f32[].add data.mat4f32[]
+  of Mat4F64: value.mat4f64[].add data.mat4f64[]
+  of Sampler2D: value.texture[].add data.texture[]
+
+proc setValue*[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) =
+  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
+  elif T is Texture: value.texture[] = data
+  else: {. error: "Virtual datatype has no values" .}
+
+proc setValue*[T: GPUType|int|uint|float](value: var DataList, i: int, 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
+  elif T is Texture: value.texture[i] = data
+  else: {. error: "Virtual datatype has no values" .}
+
+proc appendFrom*(a: var DataList, i: int, b: DataList, j: int) =
+  assert  a.theType == b.theType
+  case a.theType
+    of Float32: a.float32[i] = b.float32[j]
+    of Float64: a.float64[i] = b.float64[j]
+    of Int8: a.int8[i] = b.int8[j]
+    of Int16: a.int16[i] = b.int16[j]
+    of Int32: a.int32[i] = b.int32[j]
+    of Int64: a.int64[i] = b.int64[j]
+    of UInt8: a.uint8[i] = b.uint8[j]
+    of UInt16: a.uint16[i] = b.uint16[j]
+    of UInt32: a.uint32[i] = b.uint32[j]
+    of UInt64: a.uint64[i] = b.uint64[j]
+    of Vec2I32: a.vec2i32[i] = b.vec2i32[j]
+    of Vec2I64: a.vec2i64[i] = b.vec2i64[j]
+    of Vec3I32: a.vec3i32[i] = b.vec3i32[j]
+    of Vec3I64: a.vec3i64[i] = b.vec3i64[j]
+    of Vec4I32: a.vec4i32[i] = b.vec4i32[j]
+    of Vec4I64: a.vec4i64[i] = b.vec4i64[j]
+    of Vec2U32: a.vec2u32[i] = b.vec2u32[j]
+    of Vec2U64: a.vec2u64[i] = b.vec2u64[j]
+    of Vec3U32: a.vec3u32[i] = b.vec3u32[j]
+    of Vec3U64: a.vec3u64[i] = b.vec3u64[j]
+    of Vec4U32: a.vec4u32[i] = b.vec4u32[j]
+    of Vec4U64: a.vec4u64[i] = b.vec4u64[j]
+    of Vec2F32: a.vec2f32[i] = b.vec2f32[j]
+    of Vec2F64: a.vec2f64[i] = b.vec2f64[j]
+    of Vec3F32: a.vec3f32[i] = b.vec3f32[j]
+    of Vec3F64: a.vec3f64[i] = b.vec3f64[j]
+    of Vec4F32: a.vec4f32[i] = b.vec4f32[j]
+    of Vec4F64: a.vec4f64[i] = b.vec4f64[j]
+    of Mat2F32: a.mat2f32[i] = b.mat2f32[j]
+    of Mat2F64: a.mat2f64[i] = b.mat2f64[j]
+    of Mat23F32: a.mat23f32[i] = b.mat23f32[j]
+    of Mat23F64: a.mat23f64[i] = b.mat23f64[j]
+    of Mat32F32: a.mat32f32[i] = b.mat32f32[j]
+    of Mat32F64: a.mat32f64[i] = b.mat32f64[j]
+    of Mat3F32: a.mat3f32[i] = b.mat3f32[j]
+    of Mat3F64: a.mat3f64[i] = b.mat3f64[j]
+    of Mat34F32: a.mat34f32[i] = b.mat34f32[j]
+    of Mat34F64: a.mat34f64[i] = b.mat34f64[j]
+    of Mat43F32: a.mat43f32[i] = b.mat43f32[j]
+    of Mat43F64: a.mat43f64[i] = b.mat43f64[j]
+    of Mat4F32: a.mat4f32[i] = b.mat4f32[j]
+    of Mat4F64: a.mat4f64[i] = b.mat4f64[j]
+    of Sampler2D: a.texture[i] = b.texture[j]
+
+proc copy*(datalist: DataList): DataList =
+  result = newDataList(datalist.theType)
+  result.appendValues(datalist)
--- a/src/semicongine/core/gpu_data.nim	Mon Sep 11 23:15:25 2023 +0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1269 +0,0 @@
-import std/strformat
-import std/tables
-
-import ./vulkanapi
-import ./vector
-import ./matrix
-import ./utils
-import ./imagetypes
-
-type
-  Sampler2DType* = object
-  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] | Texture
-  DataType* = enum
-    Float32
-    Float64
-    Int8
-    Int16
-    Int32
-    Int64
-    UInt8
-    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
-    Sampler2D
-  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]
-    of Sampler2D: texture: Texture
-  DataList* = object
-    len*: int
-    case theType*: DataType
-    of Float32: float32: ref seq[float32]
-    of Float64: float64: ref seq[float64]
-    of Int8: int8: ref seq[int8]
-    of Int16: int16: ref seq[int16]
-    of Int32: int32: ref seq[int32]
-    of Int64: int64: ref seq[int64]
-    of UInt8: uint8: ref seq[uint8]
-    of UInt16: uint16: ref seq[uint16]
-    of UInt32: uint32: ref seq[uint32]
-    of UInt64: uint64: ref seq[uint64]
-    of Vec2I32: vec2i32: ref seq[TVec2[int32]]
-    of Vec2I64: vec2i64: ref seq[TVec2[int64]]
-    of Vec3I32: vec3i32: ref seq[TVec3[int32]]
-    of Vec3I64: vec3i64: ref seq[TVec3[int64]]
-    of Vec4I32: vec4i32: ref seq[TVec4[int32]]
-    of Vec4I64: vec4i64: ref seq[TVec4[int64]]
-    of Vec2U32: vec2u32: ref seq[TVec2[uint32]]
-    of Vec2U64: vec2u64: ref seq[TVec2[uint64]]
-    of Vec3U32: vec3u32: ref seq[TVec3[uint32]]
-    of Vec3U64: vec3u64: ref seq[TVec3[uint64]]
-    of Vec4U32: vec4u32: ref seq[TVec4[uint32]]
-    of Vec4U64: vec4u64: ref seq[TVec4[uint64]]
-    of Vec2F32: vec2f32: ref seq[TVec2[float32]]
-    of Vec2F64: vec2f64: ref seq[TVec2[float64]]
-    of Vec3F32: vec3f32: ref seq[TVec3[float32]]
-    of Vec3F64: vec3f64: ref seq[TVec3[float64]]
-    of Vec4F32: vec4f32: ref seq[TVec4[float32]]
-    of Vec4F64: vec4f64: ref seq[TVec4[float64]]
-    of Mat2F32: mat2f32: ref seq[TMat2[float32]]
-    of Mat2F64: mat2f64: ref seq[TMat2[float64]]
-    of Mat23F32: mat23f32: ref seq[TMat23[float32]]
-    of Mat23F64: mat23f64: ref seq[TMat23[float64]]
-    of Mat32F32: mat32f32: ref seq[TMat32[float32]]
-    of Mat32F64: mat32f64: ref seq[TMat32[float64]]
-    of Mat3F32: mat3f32: ref seq[TMat3[float32]]
-    of Mat3F64: mat3f64: ref seq[TMat3[float64]]
-    of Mat34F32: mat34f32: ref seq[TMat34[float32]]
-    of Mat34F64: mat34f64: ref seq[TMat34[float64]]
-    of Mat43F32: mat43f32: ref seq[TMat43[float32]]
-    of Mat43F64: mat43f64: ref seq[TMat43[float64]]
-    of Mat4F32: mat4f32: ref seq[TMat4[float32]]
-    of Mat4F64: mat4f64: ref seq[TMat4[float64]]
-    of Sampler2D: texture: ref seq[Texture]
-  MemoryPerformanceHint* = enum
-    PreferFastRead, PreferFastWrite
-  ShaderAttribute* = object
-    name*: string
-    theType*: DataType
-    arrayCount*: int
-    perInstance*: bool
-    noInterpolation: bool
-    memoryPerformanceHint*: MemoryPerformanceHint
-
-func `==`*(a, b: DataList | DataValue): bool =
-  if a.theType != b.theType:
-    return false
-  case a.theType
-    of Float32: return a.float32 == b.float32
-    of Float64: return a.float64 == b.float64
-    of Int8: return a.int8 == b.int8
-    of Int16: return a.int16 == b.int16
-    of Int32: return a.int32 == b.int32
-    of Int64: return a.int64 == b.int64
-    of UInt8: return a.uint8 == b.uint8
-    of UInt16: return a.uint16 == b.uint16
-    of UInt32: return a.uint32 == b.uint32
-    of UInt64: return a.uint64 == b.uint64
-    of Vec2I32: return a.vec2i32 == b.vec2i32
-    of Vec2I64: return a.vec2i64 == b.vec2i64
-    of Vec3I32: return a.vec3i32 == b.vec3i32
-    of Vec3I64: return a.vec3i64 == b.vec3i64
-    of Vec4I32: return a.vec4i32 == b.vec4i32
-    of Vec4I64: return a.vec4i64 == b.vec4i64
-    of Vec2U32: return a.vec2u32 == b.vec2u32
-    of Vec2U64: return a.vec2u64 == b.vec2u64
-    of Vec3U32: return a.vec3u32 == b.vec3u32
-    of Vec3U64: return a.vec3u64 == b.vec3u64
-    of Vec4U32: return a.vec4u32 == b.vec4u32
-    of Vec4U64: return a.vec4u64 == b.vec4u64
-    of Vec2F32: return a.vec2f32 == b.vec2f32
-    of Vec2F64: return a.vec2f64 == b.vec2f64
-    of Vec3F32: return a.vec3f32 == b.vec3f32
-    of Vec3F64: return a.vec3f64 == b.vec3f64
-    of Vec4F32: return a.vec4f32 == b.vec4f32
-    of Vec4F64: return a.vec4f64 == b.vec4f64
-    of Mat2F32: return a.mat2f32 == b.mat2f32
-    of Mat2F64: return a.mat2f64 == b.mat2f64
-    of Mat23F32: return a.mat23f32 == b.mat23f32
-    of Mat23F64: return a.mat23f64 == b.mat23f64
-    of Mat32F32: return a.mat32f32 == b.mat32f32
-    of Mat32F64: return a.mat32f64 == b.mat32f64
-    of Mat3F32: return a.mat3f32 == b.mat3f32
-    of Mat3F64: return a.mat3f64 == b.mat3f64
-    of Mat34F32: return a.mat34f32 == b.mat34f32
-    of Mat34F64: return a.mat34f64 == b.mat34f64
-    of Mat43F32: return a.mat43f32 == b.mat43f32
-    of Mat43F64: return a.mat43f64 == b.mat43f64
-    of Mat4F32: return a.mat4f32 == b.mat4f32
-    of Mat4F64: return a.mat4f64 == b.mat4f64
-    of Sampler2D: a.texture == b.texture
-
-func vertexInputs*(attributes: seq[ShaderAttribute]): seq[ShaderAttribute] =
-  for attr in attributes:
-    if attr.perInstance == false:
-      result.add attr
-
-func instanceInputs*(attributes: seq[ShaderAttribute]): seq[ShaderAttribute] =
-  for attr in attributes:
-    if attr.perInstance == false:
-      result.add attr
-
-func numberOfVertexInputAttributeDescriptors*(theType: DataType): int =
-  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): int =
-  case theType:
-    of Float32: 4
-    of Float64: 8
-    of Int8: 1
-    of Int16: 2
-    of Int32: 4
-    of Int64: 8
-    of UInt8: 1
-    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
-    of Sampler2D: 0
-
-func size*(attribute: ShaderAttribute, perDescriptor=false): int =
-  if perDescriptor:
-    attribute.theType.size div attribute.theType.numberOfVertexInputAttributeDescriptors
-  else:
-    if attribute.arrayCount == 0:
-      attribute.theType.size
-    else:
-      attribute.theType.size * attribute.arrayCount
-
-func size*(theType: seq[ShaderAttribute]): int =
-  for attribute in theType:
-    result += attribute.size
-
-func size*(value: DataValue): int =
-  value.theType.size
-
-func size*(value: DataList): int =
-  value.theType.size * value.len
-
-func getDataType*[T: GPUType|int|uint|float](): DataType =
-  when T is float32: Float32
-  elif T is float64: Float64
-  elif T is int8: Int8
-  elif T is int16: Int16
-  elif T is int32: Int32
-  elif T is int64: Int64
-  elif T is uint8: UInt8
-  elif T is uint16: UInt16
-  elif T is uint32: UInt32
-  elif T is uint64: UInt64
-  elif T is int and sizeof(int) == sizeof(int64): Int64
-  elif T is int and sizeof(int) == sizeof(int32): Int32
-  elif T is uint and sizeof(uint) == sizeof(uint64): UInt64
-  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
-  elif T is Texture: Sampler2D
-  else:
-    static:
-      raise newException(Exception, &"Unsupported data type for GPU data: {name(T)}" )
-
-func attr*[T: GPUType](
-  name: string,
-  perInstance=false,
-  arrayCount=0,
-  noInterpolation=false,
-  memoryPerformanceHint=PreferFastRead,
-): auto =
-  ShaderAttribute(
-    name: name,
-    theType: getDataType[T](),
-    perInstance: perInstance,
-    arrayCount: arrayCount,
-    noInterpolation: noInterpolation,
-    memoryPerformanceHint: memoryPerformanceHint,
-  )
-
-func getValue*[T: GPUType|int|uint|float](value: DataValue): 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
-  elif T is Texture: value.texture
-  else: {.error: "Virtual datatype has no value" .}
-
-proc setValues*[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) =
-  value.initData(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
-  elif T is Texture: value.texture[] = data
-  else: {. error: "Virtual datatype has no values" .}
-
-func newDataList*(theType: DataType): DataList =
-  result = DataList(theType: theType)
-  case result.theType
-    of Float32: result.float32 = new seq[float32]
-    of Float64: result.float64 = new seq[float64]
-    of Int8: result.int8 = new seq[int8]
-    of Int16: result.int16 = new seq[int16]
-    of Int32: result.int32 = new seq[int32]
-    of Int64: result.int64 = new seq[int64]
-    of UInt8: result.uint8 = new seq[uint8]
-    of UInt16: result.uint16 = new seq[uint16]
-    of UInt32: result.uint32 = new seq[uint32]
-    of UInt64: result.uint64 = new seq[uint64]
-    of Vec2I32: result.vec2i32 = new seq[TVec2[int32]]
-    of Vec2I64: result.vec2i64 = new seq[TVec2[int64]]
-    of Vec3I32: result.vec3i32 = new seq[TVec3[int32]]
-    of Vec3I64: result.vec3i64 = new seq[TVec3[int64]]
-    of Vec4I32: result.vec4i32 = new seq[TVec4[int32]]
-    of Vec4I64: result.vec4i64 = new seq[TVec4[int64]]
-    of Vec2U32: result.vec2u32 = new seq[TVec2[uint32]]
-    of Vec2U64: result.vec2u64 = new seq[TVec2[uint64]]
-    of Vec3U32: result.vec3u32 = new seq[TVec3[uint32]]
-    of Vec3U64: result.vec3u64 = new seq[TVec3[uint64]]
-    of Vec4U32: result.vec4u32 = new seq[TVec4[uint32]]
-    of Vec4U64: result.vec4u64 = new seq[TVec4[uint64]]
-    of Vec2F32: result.vec2f32 = new seq[TVec2[float32]]
-    of Vec2F64: result.vec2f64 = new seq[TVec2[float64]]
-    of Vec3F32: result.vec3f32 = new seq[TVec3[float32]]
-    of Vec3F64: result.vec3f64 = new seq[TVec3[float64]]
-    of Vec4F32: result.vec4f32 = new seq[TVec4[float32]]
-    of Vec4F64: result.vec4f64 = new seq[TVec4[float64]]
-    of Mat2F32: result.mat2f32 = new seq[TMat2[float32]]
-    of Mat2F64: result.mat2f64 = new seq[TMat2[float64]]
-    of Mat23F32: result.mat23f32 = new seq[TMat23[float32]]
-    of Mat23F64: result.mat23f64 = new seq[TMat23[float64]]
-    of Mat32F32: result.mat32f32 = new seq[TMat32[float32]]
-    of Mat32F64: result.mat32f64 = new seq[TMat32[float64]]
-    of Mat3F32: result.mat3f32 = new seq[TMat3[float32]]
-    of Mat3F64: result.mat3f64 = new seq[TMat3[float64]]
-    of Mat34F32: result.mat34f32 = new seq[TMat34[float32]]
-    of Mat34F64: result.mat34f64 = new seq[TMat34[float64]]
-    of Mat43F32: result.mat43f32 = new seq[TMat43[float32]]
-    of Mat43F64: result.mat43f64 = new seq[TMat43[float64]]
-    of Mat4F32: result.mat4f32 = new seq[TMat4[float32]]
-    of Mat4F64: result.mat4f64 = new seq[TMat4[float64]]
-    of Sampler2D: result.texture = new seq[Texture]
-
-proc newDataList*[T: GPUType](len=0): DataList =
-  result = newDataList(getDataType[T]())
-  if len > 0:
-    result.initData(len)
-
-proc newDataList*[T: GPUType](data: seq[T]): DataList =
-  result = newDataList(getDataType[T]())
-  result.setValues(data)
-
-proc toGPUValue*[T: GPUType](value: T): DataValue =
-  result = DataValue(theType: getDataType[T]())
-  result.setValue(value)
-
-proc toGPUValue*[T: GPUType](value: seq[T]): DataList =
-  result = newDataList[T](value.len)
-  result.setValue(value)
-
-func getValues*[T: GPUType|int|uint|float](value: DataList): ref 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
-  elif T is Texture: value.texture
-  else: {. error: "Virtual datatype has no values" .}
-
-func getValue*[T: GPUType|int|uint|float](value: DataList, i: int): T =
-  when T is float32: value.float32[i]
-  elif T is float64: value.float64[i]
-  elif T is int8: value.int8[i]
-  elif T is int16: value.int16[i]
-  elif T is int32: value.int32[i]
-  elif T is int64: value.int64[i]
-  elif T is uint8: value.uint8[i]
-  elif T is uint16: value.uint16[i]
-  elif T is uint32: value.uint32[i]
-  elif T is uint64: value.uint64[i]
-  elif T is int and sizeof(int) == sizeof(int32): value.int32[i]
-  elif T is int and sizeof(int) == sizeof(int64): value.int64[i]
-  elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[i]
-  elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[i]
-  elif T is float and sizeof(float) == sizeof(float32): value.float32[i]
-  elif T is float and sizeof(float) == sizeof(float64): value.float64[i]
-  elif T is TVec2[int32]: value.vec2i32[i]
-  elif T is TVec2[int64]: value.vec2i64[i]
-  elif T is TVec3[int32]: value.vec3i32[i]
-  elif T is TVec3[int64]: value.vec3i64[i]
-  elif T is TVec4[int32]: value.vec4i32[i]
-  elif T is TVec4[int64]: value.vec4i64[i]
-  elif T is TVec2[uint32]: value.vec2u32[i]
-  elif T is TVec2[uint64]: value.vec2u64[i]
-  elif T is TVec3[uint32]: value.vec3u32[i]
-  elif T is TVec3[uint64]: value.vec3u64[i]
-  elif T is TVec4[uint32]: value.vec4u32[i]
-  elif T is TVec4[uint64]: value.vec4u64[i]
-  elif T is TVec2[float32]: value.vec2f32[i]
-  elif T is TVec2[float64]: value.vec2f64[i]
-  elif T is TVec3[float32]: value.vec3f32[i]
-  elif T is TVec3[float64]: value.vec3f64[i]
-  elif T is TVec4[float32]: value.vec4f32[i]
-  elif T is TVec4[float64]: value.vec4f64[i]
-  elif T is TMat2[float32]: value.mat2f32[i]
-  elif T is TMat2[float64]: value.mat2f64[i]
-  elif T is TMat23[float32]: value.mat23f[i]
-  elif T is TMat23[float64]: value.mat23f64[i]
-  elif T is TMat32[float32]: value.mat32f32[i]
-  elif T is TMat32[float64]: value.mat32f64[i]
-  elif T is TMat3[float32]: value.mat3f32[i]
-  elif T is TMat3[float64]: value.mat3f64[i]
-  elif T is TMat34[float32]: value.mat34f32[i]
-  elif T is TMat34[float64]: value.mat34f64[i]
-  elif T is TMat43[float32]: value.mat43f32[i]
-  elif T is TMat43[float64]: value.mat43f64[i]
-  elif T is TMat4[float32]: value.mat4f32[i]
-  elif T is TMat4[float64]: value.mat4f64[i]
-  elif T is Texture: value.texture[i]
-  else: {. error: "Virtual datatype has no values" .}
-
-func getRawData*(value: var DataValue): (pointer, int) =
-  result[1] = value.theType.size
-  case value.theType
-    of Float32: result[0] = addr value.float32
-    of Float64: result[0] = addr value.float64
-    of Int8: result[0] = addr value.int8
-    of Int16: result[0] = addr value.int16
-    of Int32: result[0] = addr value.int32
-    of Int64: result[0] = addr value.int64
-    of UInt8: result[0] = addr value.uint8
-    of UInt16: result[0] = addr value.uint16
-    of UInt32: result[0] = addr value.uint32
-    of UInt64: result[0] = addr value.uint64
-    of Vec2I32: result[0] = addr value.vec2i32
-    of Vec2I64: result[0] = addr value.vec2i64
-    of Vec3I32: result[0] = addr value.vec3i32
-    of Vec3I64: result[0] = addr value.vec3i64
-    of Vec4I32: result[0] = addr value.vec4i32
-    of Vec4I64: result[0] = addr value.vec4i64
-    of Vec2U32: result[0] = addr value.vec2u32
-    of Vec2U64: result[0] = addr value.vec2u64
-    of Vec3U32: result[0] = addr value.vec3u32
-    of Vec3U64: result[0] = addr value.vec3u64
-    of Vec4U32: result[0] = addr value.vec4u32
-    of Vec4U64: result[0] = addr value.vec4u64
-    of Vec2F32: result[0] = addr value.vec2f32
-    of Vec2F64: result[0] = addr value.vec2f64
-    of Vec3F32: result[0] = addr value.vec3f32
-    of Vec3F64: result[0] = addr value.vec3f64
-    of Vec4F32: result[0] = addr value.vec4f32
-    of Vec4F64: result[0] = addr value.vec4f64
-    of Mat2F32: result[0] = addr value.mat2f32
-    of Mat2F64: result[0] = addr value.mat2f64
-    of Mat23F32: result[0] = addr value.mat23f32
-    of Mat23F64: result[0] = addr value.mat23f64
-    of Mat32F32: result[0] = addr value.mat32f32
-    of Mat32F64: result[0] = addr value.mat32f64
-    of Mat3F32: result[0] = addr value.mat3f32
-    of Mat3F64: result[0] = addr value.mat3f64
-    of Mat34F32: result[0] = addr value.mat34f32
-    of Mat34F64: result[0] = addr value.mat34f64
-    of Mat43F32: result[0] = addr value.mat43f32
-    of Mat43F64: result[0] = addr value.mat43f64
-    of Mat4F32: result[0] = addr value.mat4f32
-    of Mat4F64: result[0] = addr value.mat4f64
-    of Sampler2D: result[0] = nil
-
-func getRawData*(value: var DataList): (pointer, int) =
-  if value.len == 0:
-    return (nil, 0)
-  result[1] = value.theType.size * value.len
-  case value.theType
-    of Float32: result[0] = value.float32[].toCPointer
-    of Float64: result[0] = value.float64[].toCPointer
-    of Int8: result[0] = value.int8[].toCPointer
-    of Int16: result[0] = value.int16[].toCPointer
-    of Int32: result[0] = value.int32[].toCPointer
-    of Int64: result[0] = value.int64[].toCPointer
-    of UInt8: result[0] = value.uint8[].toCPointer
-    of UInt16: result[0] = value.uint16[].toCPointer
-    of UInt32: result[0] = value.uint32[].toCPointer
-    of UInt64: result[0] = value.uint64[].toCPointer
-    of Vec2I32: result[0] = value.vec2i32[].toCPointer
-    of Vec2I64: result[0] = value.vec2i64[].toCPointer
-    of Vec3I32: result[0] = value.vec3i32[].toCPointer
-    of Vec3I64: result[0] = value.vec3i64[].toCPointer
-    of Vec4I32: result[0] = value.vec4i32[].toCPointer
-    of Vec4I64: result[0] = value.vec4i64[].toCPointer
-    of Vec2U32: result[0] = value.vec2u32[].toCPointer
-    of Vec2U64: result[0] = value.vec2u64[].toCPointer
-    of Vec3U32: result[0] = value.vec3u32[].toCPointer
-    of Vec3U64: result[0] = value.vec3u64[].toCPointer
-    of Vec4U32: result[0] = value.vec4u32[].toCPointer
-    of Vec4U64: result[0] = value.vec4u64[].toCPointer
-    of Vec2F32: result[0] = value.vec2f32[].toCPointer
-    of Vec2F64: result[0] = value.vec2f64[].toCPointer
-    of Vec3F32: result[0] = value.vec3f32[].toCPointer
-    of Vec3F64: result[0] = value.vec3f64[].toCPointer
-    of Vec4F32: result[0] = value.vec4f32[].toCPointer
-    of Vec4F64: result[0] = value.vec4f64[].toCPointer
-    of Mat2F32: result[0] = value.mat2f32[].toCPointer
-    of Mat2F64: result[0] = value.mat2f64[].toCPointer
-    of Mat23F32: result[0] = value.mat23f32[].toCPointer
-    of Mat23F64: result[0] = value.mat23f64[].toCPointer
-    of Mat32F32: result[0] = value.mat32f32[].toCPointer
-    of Mat32F64: result[0] = value.mat32f64[].toCPointer
-    of Mat3F32: result[0] = value.mat3f32[].toCPointer
-    of Mat3F64: result[0] = value.mat3f64[].toCPointer
-    of Mat34F32: result[0] = value.mat34f32[].toCPointer
-    of Mat34F64: result[0] = value.mat34f64[].toCPointer
-    of Mat43F32: result[0] = value.mat43f32[].toCPointer
-    of Mat43F64: result[0] = value.mat43f64[].toCPointer
-    of Mat4F32: result[0] = value.mat4f32[].toCPointer
-    of Mat4F64: result[0] = value.mat4f64[].toCPointer
-    of Sampler2D: result[0] = nil
-
-proc initData*(value: var DataList, len: int) =
-  value.len = len
-  case value.theType
-    of Float32: value.float32[].setLen(len)
-    of Float64: value.float64[].setLen(len)
-    of Int8: value.int8[].setLen(len)
-    of Int16: value.int16[].setLen(len)
-    of Int32: value.int32[].setLen(len)
-    of Int64: value.int64[].setLen(len)
-    of UInt8: value.uint8[].setLen(len)
-    of UInt16: value.uint16[].setLen(len)
-    of UInt32: value.uint32[].setLen(len)
-    of UInt64: value.uint64[].setLen(len)
-    of Vec2I32: value.vec2i32[].setLen(len)
-    of Vec2I64: value.vec2i64[].setLen(len)
-    of Vec3I32: value.vec3i32[].setLen(len)
-    of Vec3I64: value.vec3i64[].setLen(len)
-    of Vec4I32: value.vec4i32[].setLen(len)
-    of Vec4I64: value.vec4i64[].setLen(len)
-    of Vec2U32: value.vec2u32[].setLen(len)
-    of Vec2U64: value.vec2u64[].setLen(len)
-    of Vec3U32: value.vec3u32[].setLen(len)
-    of Vec3U64: value.vec3u64[].setLen(len)
-    of Vec4U32: value.vec4u32[].setLen(len)
-    of Vec4U64: value.vec4u64[].setLen(len)
-    of Vec2F32: value.vec2f32[].setLen(len)
-    of Vec2F64: value.vec2f64[].setLen(len)
-    of Vec3F32: value.vec3f32[].setLen(len)
-    of Vec3F64: value.vec3f64[].setLen(len)
-    of Vec4F32: value.vec4f32[].setLen(len)
-    of Vec4F64: value.vec4f64[].setLen(len)
-    of Mat2F32: value.mat2f32[].setLen(len)
-    of Mat2F64: value.mat2f64[].setLen(len)
-    of Mat23F32: value.mat23f32[].setLen(len)
-    of Mat23F64: value.mat23f64[].setLen(len)
-    of Mat32F32: value.mat32f32[].setLen(len)
-    of Mat32F64: value.mat32f64[].setLen(len)
-    of Mat3F32: value.mat3f32[].setLen(len)
-    of Mat3F64: value.mat3f64[].setLen(len)
-    of Mat34F32: value.mat34f32[].setLen(len)
-    of Mat34F64: value.mat34f64[].setLen(len)
-    of Mat43F32: value.mat43f32[].setLen(len)
-    of Mat43F64: value.mat43f64[].setLen(len)
-    of Mat4F32: value.mat4f32[].setLen(len)
-    of Mat4F64: value.mat4f64[].setLen(len)
-    of Sampler2D: discard
-
-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
-  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
-  elif T is Texture: value.texture = data
-  else: {.error: "Virtual datatype has no value" .}
-
-proc appendValues*[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) =
-  value.len += data.len
-  when T is float32: value.float32[].add data
-  elif T is float64: value.float64[].add data
-  elif T is int8: value.int8[].add data
-  elif T is int16: value.int16[].add data
-  elif T is int32: value.int32[].add data
-  elif T is int64: value.int64[].add data
-  elif T is uint8: value.uint8[].add data
-  elif T is uint16: value.uint16[].add data
-  elif T is uint32: value.uint32[].add data
-  elif T is uint64: value.uint64[].add data
-  elif T is int and sizeof(int) == sizeof(int32): value.int32[].add data
-  elif T is int and sizeof(int) == sizeof(int64): value.int64[].add data
-  elif T is uint and sizeof(uint) == sizeof(uint32): value.uint32[].add data
-  elif T is uint and sizeof(uint) == sizeof(uint64): value.uint64[].add data
-  elif T is float and sizeof(float) == sizeof(float32): value.float32[].add data
-  elif T is float and sizeof(float) == sizeof(float64): value.float64[].add data
-  elif T is TVec2[int32]: value.vec2i32[].add data
-  elif T is TVec2[int64]: value.vec2i64[].add data
-  elif T is TVec3[int32]: value.vec3i32[].add data
-  elif T is TVec3[int64]: value.vec3i64[].add data
-  elif T is TVec4[int32]: value.vec4i32[].add data
-  elif T is TVec4[int64]: value.vec4i64[].add data
-  elif T is TVec2[uint32]: value.vec2u32[].add data
-  elif T is TVec2[uint64]: value.vec2u64[].add data
-  elif T is TVec3[uint32]: value.vec3u32[].add data
-  elif T is TVec3[uint64]: value.vec3u64[].add data
-  elif T is TVec4[uint32]: value.vec4u32[].add data
-  elif T is TVec4[uint64]: value.vec4u64[].add data
-  elif T is TVec2[float32]: value.vec2f32[].add data
-  elif T is TVec2[float64]: value.vec2f64[].add data
-  elif T is TVec3[float32]: value.vec3f32[].add data
-  elif T is TVec3[float64]: value.vec3f64[].add data
-  elif T is TVec4[float32]: value.vec4f32[].add data
-  elif T is TVec4[float64]: value.vec4f64[].add data
-  elif T is TMat2[float32]: value.mat2f32[].add data
-  elif T is TMat2[float64]: value.mat2f64[].add data
-  elif T is TMat23[float32]: value.mat23f32[].add data
-  elif T is TMat23[float64]: value.mat23f64[].add data
-  elif T is TMat32[float32]: value.mat32f32[].add data
-  elif T is TMat32[float64]: value.mat32f64[].add data
-  elif T is TMat3[float32]: value.mat3f32[].add data
-  elif T is TMat3[float64]: value.mat3f64[].add data
-  elif T is TMat34[float32]: value.mat34f32[].add data
-  elif T is TMat34[float64]: value.mat34f64[].add data
-  elif T is TMat43[float32]: value.mat43f32[].add data
-  elif T is TMat43[float64]: value.mat43f64[].add data
-  elif T is TMat4[float32]: value.mat4f32[].add data
-  elif T is TMat4[float64]: value.mat4f64[].add data
-  elif T is Texture: value.texture[].add data
-  else: {. error: "Virtual datatype has no values" .}
-
-proc appendValues*(value: var DataList, data: DataList) =
-  assert value.theType == data.theType
-  value.len += data.len
-  case value.theType:
-  of Float32: value.float32[].add data.float32[]
-  of Float64: value.float64[].add data.float64[]
-  of Int8: value.int8[].add data.int8[]
-  of Int16: value.int16[].add data.int16[]
-  of Int32: value.int32[].add data.int32[]
-  of Int64: value.int64[].add data.int64[]
-  of UInt8: value.uint8[].add data.uint8[]
-  of UInt16: value.uint16[].add data.uint16[]
-  of UInt32: value.uint32[].add data.uint32[]
-  of UInt64: value.uint64[].add data.uint64[]
-  of Vec2I32: value.vec2i32[].add data.vec2i32[]
-  of Vec2I64: value.vec2i64[].add data.vec2i64[]
-  of Vec3I32: value.vec3i32[].add data.vec3i32[]
-  of Vec3I64: value.vec3i64[].add data.vec3i64[]
-  of Vec4I32: value.vec4i32[].add data.vec4i32[]
-  of Vec4I64: value.vec4i64[].add data.vec4i64[]
-  of Vec2U32: value.vec2u32[].add data.vec2u32[]
-  of Vec2U64: value.vec2u64[].add data.vec2u64[]
-  of Vec3U32: value.vec3u32[].add data.vec3u32[]
-  of Vec3U64: value.vec3u64[].add data.vec3u64[]
-  of Vec4U32: value.vec4u32[].add data.vec4u32[]
-  of Vec4U64: value.vec4u64[].add data.vec4u64[]
-  of Vec2F32: value.vec2f32[].add data.vec2f32[]
-  of Vec2F64: value.vec2f64[].add data.vec2f64[]
-  of Vec3F32: value.vec3f32[].add data.vec3f32[]
-  of Vec3F64: value.vec3f64[].add data.vec3f64[]
-  of Vec4F32: value.vec4f32[].add data.vec4f32[]
-  of Vec4F64: value.vec4f64[].add data.vec4f64[]
-  of Mat2F32: value.mat2f32[].add data.mat2f32[]
-  of Mat2F64: value.mat2f64[].add data.mat2f64[]
-  of Mat23F32: value.mat23f32[].add data.mat23f32[]
-  of Mat23F64: value.mat23f64[].add data.mat23f64[]
-  of Mat32F32: value.mat32f32[].add data.mat32f32[]
-  of Mat32F64: value.mat32f64[].add data.mat32f64[]
-  of Mat3F32: value.mat3f32[].add data.mat3f32[]
-  of Mat3F64: value.mat3f64[].add data.mat3f64[]
-  of Mat34F32: value.mat34f32[].add data.mat34f32[]
-  of Mat34F64: value.mat34f64[].add data.mat34f64[]
-  of Mat43F32: value.mat43f32[].add data.mat43f32[]
-  of Mat43F64: value.mat43f64[].add data.mat43f64[]
-  of Mat4F32: value.mat4f32[].add data.mat4f32[]
-  of Mat4F64: value.mat4f64[].add data.mat4f64[]
-  else: raise newException(Exception, &"Unsupported data type for GPU data:" )
-
-proc appendValue*(value: var DataList, data: DataValue) =
-  assert value.theType == data.theType, &"appendValue expected {value.theType} but got {data.theType}"
-  value.len += 1
-  case value.theType:
-  of Float32: value.float32[].add data.float32
-  of Float64: value.float64[].add data.float64
-  of Int8: value.int8[].add data.int8
-  of Int16: value.int16[].add data.int16
-  of Int32: value.int32[].add data.int32
-  of Int64: value.int64[].add data.int64
-  of UInt8: value.uint8[].add data.uint8
-  of UInt16: value.uint16[].add data.uint16
-  of UInt32: value.uint32[].add data.uint32
-  of UInt64: value.uint64[].add data.uint64
-  of Vec2I32: value.vec2i32[].add data.vec2i32
-  of Vec2I64: value.vec2i64[].add data.vec2i64
-  of Vec3I32: value.vec3i32[].add data.vec3i32
-  of Vec3I64: value.vec3i64[].add data.vec3i64
-  of Vec4I32: value.vec4i32[].add data.vec4i32
-  of Vec4I64: value.vec4i64[].add data.vec4i64
-  of Vec2U32: value.vec2u32[].add data.vec2u32
-  of Vec2U64: value.vec2u64[].add data.vec2u64
-  of Vec3U32: value.vec3u32[].add data.vec3u32
-  of Vec3U64: value.vec3u64[].add data.vec3u64
-  of Vec4U32: value.vec4u32[].add data.vec4u32
-  of Vec4U64: value.vec4u64[].add data.vec4u64
-  of Vec2F32: value.vec2f32[].add data.vec2f32
-  of Vec2F64: value.vec2f64[].add data.vec2f64
-  of Vec3F32: value.vec3f32[].add data.vec3f32
-  of Vec3F64: value.vec3f64[].add data.vec3f64
-  of Vec4F32: value.vec4f32[].add data.vec4f32
-  of Vec4F64: value.vec4f64[].add data.vec4f64
-  of Mat2F32: value.mat2f32[].add data.mat2f32
-  of Mat2F64: value.mat2f64[].add data.mat2f64
-  of Mat23F32: value.mat23f32[].add data.mat23f32
-  of Mat23F64: value.mat23f64[].add data.mat23f64
-  of Mat32F32: value.mat32f32[].add data.mat32f32
-  of Mat32F64: value.mat32f64[].add data.mat32f64
-  of Mat3F32: value.mat3f32[].add data.mat3f32
-  of Mat3F64: value.mat3f64[].add data.mat3f64
-  of Mat34F32: value.mat34f32[].add data.mat34f32
-  of Mat34F64: value.mat34f64[].add data.mat34f64
-  of Mat43F32: value.mat43f32[].add data.mat43f32
-  of Mat43F64: value.mat43f64[].add data.mat43f64
-  of Mat4F32: value.mat4f32[].add data.mat4f32
-  of Mat4F64: value.mat4f64[].add data.mat4f64
-  else: raise newException(Exception, &"Unsupported data type for GPU data:" )
-
-proc setValue*[T: GPUType|int|uint|float](value: var DataList, data: seq[T]) =
-  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
-  elif T is Texture: value.texture[] = data
-  else: {. error: "Virtual datatype has no values" .}
-
-proc setValue*[T: GPUType|int|uint|float](value: var DataList, i: int, 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
-  elif T is Texture: value.texture[i] = data
-  else: {. error: "Virtual datatype has no values" .}
-
-const TYPEMAP = {
-    Float32: VK_FORMAT_R32_SFLOAT,
-    Float64: VK_FORMAT_R64_SFLOAT,
-    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*(theType: DataType): VkFormat =
-  TYPEMAP[theType]
-
-# from https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap15.html
-func nLocationSlots*(theType: DataType): int =
-  #[
-  single location:
-    16-bit scalar and vector types, and
-    32-bit scalar and vector types, and
-    64-bit scalar and 2-component vector types.
-  two locations
-    64-bit three- and four-component vectors
-  ]#
-  case theType:
-    of Float32: 1
-    of Float64: 1
-    of Int8: 1
-    of Int16: 1
-    of Int32: 1
-    of Int64: 1
-    of UInt8: 1
-    of UInt16: 1
-    of UInt32: 1
-    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
-    of Sampler2D: 1
-
-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..
-  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"
-    of Sampler2D: "sampler2D"
-
-func glslInput*(group: openArray[ShaderAttribute]): seq[string] =
-  if group.len == 0:
-    return @[]
-  var i = 0
-  for attribute in group:
-    assert attribute.arrayCount == 0, "arrays not supported for shader vertex attributes"
-    let flat = if attribute.noInterpolation: "flat " else: ""
-    result.add &"layout(location = {i}) {flat}in {attribute.theType.glslType} {attribute.name};"
-    for j in 0 ..< attribute.theType.numberOfVertexInputAttributeDescriptors:
-      i += attribute.theType.nLocationSlots
-
-func glslUniforms*(group: openArray[ShaderAttribute], blockName="Uniforms", binding: int): seq[string] =
-  if group.len == 0:
-    return @[]
-  # currently only a single uniform block supported, therefore binding = 0
-  result.add(&"layout(std430, binding = {binding}) uniform T{blockName} {{")
-  for attribute in group:
-    var arrayDecl = ""
-    if attribute.arrayCount > 0:
-      arrayDecl = &"[{attribute.arrayCount}]"
-    result.add(&"    {attribute.theType.glslType} {attribute.name}{arrayDecl};")
-  result.add(&"}} {blockName};")
-
-func glslSamplers*(group: openArray[ShaderAttribute], basebinding: int): seq[string] =
-  if group.len == 0:
-    return @[]
-  var thebinding = basebinding
-  for attribute in group:
-    var arrayDecl = ""
-    if attribute.arrayCount > 0:
-      arrayDecl = &"[{attribute.arrayCount}]"
-    result.add(&"layout(binding = {thebinding}) uniform {attribute.theType.glslType} {attribute.name}{arrayDecl};")
-    inc thebinding
-
-func glslOutput*(group: openArray[ShaderAttribute]): seq[string] =
-  if group.len == 0:
-    return @[]
-  var i = 0
-  for attribute in group:
-    assert attribute.arrayCount == 0, "arrays not supported for outputs"
-    let flat = if attribute.noInterpolation: "flat " else: ""
-    result.add &"layout(location = {i}) {flat}out {attribute.theType.glslType} {attribute.name};"
-    i += 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/semicongine/core/gpu_types.nim	Thu Sep 14 23:59:10 2023 +0700
@@ -0,0 +1,400 @@
+import std/strformat
+import std/tables
+
+import ./vulkanapi
+import ./vector
+import ./matrix
+import ./imagetypes
+
+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] | Texture
+  DataType* = enum
+    Float32
+    Float64
+    Int8
+    Int16
+    Int32
+    Int64
+    UInt8
+    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
+    Sampler2D
+  MemoryPerformanceHint* = enum
+    PreferFastRead, PreferFastWrite
+  ShaderAttribute* = object
+    name*: string
+    theType*: DataType
+    arrayCount*: int
+    perInstance*: bool
+    noInterpolation: bool
+    memoryPerformanceHint*: MemoryPerformanceHint
+
+func vertexInputs*(attributes: seq[ShaderAttribute]): seq[ShaderAttribute] =
+  for attr in attributes:
+    if attr.perInstance == false:
+      result.add attr
+
+func instanceInputs*(attributes: seq[ShaderAttribute]): seq[ShaderAttribute] =
+  for attr in attributes:
+    if attr.perInstance == false:
+      result.add attr
+
+func numberOfVertexInputAttributeDescriptors*(theType: DataType): int =
+  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): int =
+  case theType:
+    of Float32: 4
+    of Float64: 8
+    of Int8: 1
+    of Int16: 2
+    of Int32: 4
+    of Int64: 8
+    of UInt8: 1
+    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
+    of Sampler2D: 0
+
+func size*(attribute: ShaderAttribute, perDescriptor=false): int =
+  if perDescriptor:
+    attribute.theType.size div attribute.theType.numberOfVertexInputAttributeDescriptors
+  else:
+    if attribute.arrayCount == 0:
+      attribute.theType.size
+    else:
+      attribute.theType.size * attribute.arrayCount
+
+func size*(theType: seq[ShaderAttribute]): int =
+  for attribute in theType:
+    result += attribute.size
+
+func getDataType*[T: GPUType|int|uint|float](): DataType =
+  when T is float32: Float32
+  elif T is float64: Float64
+  elif T is int8: Int8
+  elif T is int16: Int16
+  elif T is int32: Int32
+  elif T is int64: Int64
+  elif T is uint8: UInt8
+  elif T is uint16: UInt16
+  elif T is uint32: UInt32
+  elif T is uint64: UInt64
+  elif T is int and sizeof(int) == sizeof(int64): Int64
+  elif T is int and sizeof(int) == sizeof(int32): Int32
+  elif T is uint and sizeof(uint) == sizeof(uint64): UInt64
+  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
+  elif T is Texture: Sampler2D
+  else:
+    static:
+      raise newException(Exception, &"Unsupported data type for GPU data: {name(T)}" )
+
+func attr*[T: GPUType](
+  name: string,
+  perInstance=false,
+  arrayCount=0,
+  noInterpolation=false,
+  memoryPerformanceHint=PreferFastRead,
+): auto =
+  ShaderAttribute(
+    name: name,
+    theType: getDataType[T](),
+    perInstance: perInstance,
+    arrayCount: arrayCount,
+    noInterpolation: noInterpolation,
+    memoryPerformanceHint: memoryPerformanceHint,
+  )
+
+const TYPEMAP = {
+    Float32: VK_FORMAT_R32_SFLOAT,
+    Float64: VK_FORMAT_R64_SFLOAT,
+    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*(theType: DataType): VkFormat =
+  TYPEMAP[theType]
+
+# from https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap15.html
+func nLocationSlots*(theType: DataType): int =
+  #[
+  single location:
+    16-bit scalar and vector types, and
+    32-bit scalar and vector types, and
+    64-bit scalar and 2-component vector types.
+  two locations
+    64-bit three- and four-component vectors
+  ]#
+  case theType:
+    of Float32: 1
+    of Float64: 1
+    of Int8: 1
+    of Int16: 1
+    of Int32: 1
+    of Int64: 1
+    of UInt8: 1
+    of UInt16: 1
+    of UInt32: 1
+    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
+    of Sampler2D: 1
+
+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..
+  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"
+    of Sampler2D: "sampler2D"
+
+func glslInput*(group: openArray[ShaderAttribute]): seq[string] =
+  if group.len == 0:
+    return @[]
+  var i = 0
+  for attribute in group:
+    assert attribute.arrayCount == 0, "arrays not supported for shader vertex attributes"
+    let flat = if attribute.noInterpolation: "flat " else: ""
+    result.add &"layout(location = {i}) {flat}in {attribute.theType.glslType} {attribute.name};"
+    for j in 0 ..< attribute.theType.numberOfVertexInputAttributeDescriptors:
+      i += attribute.theType.nLocationSlots
+
+func glslUniforms*(group: openArray[ShaderAttribute], blockName="Uniforms", binding: int): seq[string] =
+  if group.len == 0:
+    return @[]
+  # currently only a single uniform block supported, therefore binding = 0
+  result.add(&"layout(std430, binding = {binding}) uniform T{blockName} {{")
+  for attribute in group:
+    var arrayDecl = ""
+    if attribute.arrayCount > 0:
+      arrayDecl = &"[{attribute.arrayCount}]"
+    result.add(&"    {attribute.theType.glslType} {attribute.name}{arrayDecl};")
+  result.add(&"}} {blockName};")
+
+func glslSamplers*(group: openArray[ShaderAttribute], basebinding: int): seq[string] =
+  if group.len == 0:
+    return @[]
+  var thebinding = basebinding
+  for attribute in group:
+    var arrayDecl = ""
+    if attribute.arrayCount > 0:
+      arrayDecl = &"[{attribute.arrayCount}]"
+    result.add(&"layout(binding = {thebinding}) uniform {attribute.theType.glslType} {attribute.name}{arrayDecl};")
+    inc thebinding
+
+func glslOutput*(group: openArray[ShaderAttribute]): seq[string] =
+  if group.len == 0:
+    return @[]
+  var i = 0
+  for attribute in group:
+    assert attribute.arrayCount == 0, "arrays not supported for outputs"
+    let flat = if attribute.noInterpolation: "flat " else: ""
+    result.add &"layout(location = {i}) {flat}out {attribute.theType.glslType} {attribute.name};"
+    i += 1
--- a/src/semicongine/core/materials.nim	Mon Sep 11 23:15:25 2023 +0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-import std/tables
-
-import ./imagetypes
-import ./gpu_data
-
-type
-  Material* = object
-    textures: Table[string, Image]
-    constants: Table[string, DataValue]
--- a/src/semicongine/core/matrix.nim	Mon Sep 11 23:15:25 2023 +0700
+++ b/src/semicongine/core/matrix.nim	Thu Sep 14 23:59:10 2023 +0700
@@ -449,3 +449,8 @@
     let space = 2 * (1 / windowAspect - 1) / 2
     ortho(-1 - space, 1 + space, -1, 1, -1, 1)
 
+func position*(mat: Mat4): Vec3f =
+  mat.col(3).toVec3
+
+func scaling*(mat: Mat4): Vec3f =
+  newVec3f(mat[0, 0], mat[1, 1], mat[2, 2])
--- a/src/semicongine/mesh.nim	Mon Sep 11 23:15:25 2023 +0700
+++ b/src/semicongine/mesh.nim	Thu Sep 14 23:59:10 2023 +0700
@@ -24,7 +24,7 @@
       of Small: smallIndices: seq[array[3, uint16]]
       of Big: bigIndices: seq[array[3, uint32]]
     material*: Material
-    transform*: Mat4 = Unit4F32
+    transform*: Mat4 = Unit4
     instanceTransforms*: seq[Mat4]
     visible*: bool = true
     transformCache: seq[Mat4]
@@ -93,7 +93,7 @@
 proc initVertexAttribute*[T](mesh: var MeshObject, attribute: string, value: seq[T]) =
   assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute)
   mesh.vertexData[attribute] = newDataList(thetype=getDataType[T]())
-  mesh.vertexData[attribute].initData(mesh.vertexCount)
+  mesh.vertexData[attribute].setLen(mesh.vertexCount)
   mesh.vertexData[attribute].setValues(value)
 proc initVertexAttribute*[T](mesh: var MeshObject, attribute: string, value: T) =
   initVertexAttribute(mesh, attribute, newSeqWith(mesh.vertexCount, value))
@@ -102,12 +102,12 @@
 proc initVertexAttribute*(mesh: var MeshObject, attribute: string, datatype: DataType) =
   assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute)
   mesh.vertexData[attribute] = newDataList(thetype=datatype)
-  mesh.vertexData[attribute].initData(mesh.vertexCount)
+  mesh.vertexData[attribute].setLen(mesh.vertexCount)
 
 proc initInstanceAttribute*[T](mesh: var MeshObject, attribute: string, value: seq[T]) =
   assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute)
   mesh.instanceData[attribute] = newDataList(thetype=getDataType[T]())
-  mesh.instanceData[attribute].initData(mesh.instanceCount)
+  mesh.instanceData[attribute].setLen(mesh.instanceCount)
   mesh.instanceData[attribute].setValues(value)
 proc initInstanceAttribute*[T](mesh: var MeshObject, attribute: string, value: T) =
   initInstanceAttribute(mesh, attribute, newSeqWith(mesh.instanceCount, value))
@@ -116,7 +116,7 @@
 proc initInstanceAttribute*(mesh: var MeshObject, attribute: string, datatype: DataType) =
   assert not mesh.vertexData.contains(attribute) and not mesh.instanceData.contains(attribute)
   mesh.instanceData[attribute] = newDataList(thetype=datatype)
-  mesh.instanceData[attribute].initData(mesh.instanceCount)
+  mesh.instanceData[attribute].setLen(mesh.instanceCount)
 
 proc newMesh*(
   positions: openArray[Vec3f],
@@ -346,6 +346,50 @@
   for p in mesh[positionAttribute, Vec3f][]:
     result.add mesh.transform * p
 
+proc asNonIndexedMesh*(mesh: MeshObject): MeshObject =
+  if mesh.indexType == None:
+    return mesh
+
+  result = MeshObject(
+    vertexCount: mesh.indicesCount,
+    indexType: None,
+    material: mesh.material,
+    transform: mesh.transform,
+    instanceTransforms: mesh.instanceTransforms,
+    visible: mesh.visible,
+  )
+  for attribute, datalist in mesh.vertexData.pairs:
+    result.initVertexAttribute(attribute, datalist.theType)
+  for attribute, datalist in mesh.instanceData.pairs:
+    result.instanceData[attribute] = datalist.copy()
+  var i = 0
+  case mesh.indexType
+  of Tiny:
+    for indices in mesh.tinyIndices:
+      for attribute, value in mesh.vertexData.pairs:
+        result.vertexData[attribute].appendFrom(i, mesh.vertexData[attribute], int(indices[0]))
+        result.vertexData[attribute].appendFrom(i + 1, mesh.vertexData[attribute], int(indices[1]))
+        result.vertexData[attribute].appendFrom(i + 2, mesh.vertexData[attribute], int(indices[2]))
+      i += 3
+  of Small:
+    for indices in mesh.smallIndices:
+      for attribute, value in mesh.vertexData.pairs:
+        result.vertexData[attribute].appendFrom(i, value, int(indices[0]))
+        result.vertexData[attribute].appendFrom(i + 1, value, int(indices[1]))
+        result.vertexData[attribute].appendFrom(i + 2, value, int(indices[2]))
+      i += 3
+  of Big:
+    for indices in mesh.bigIndices:
+      for attribute, value in mesh.vertexData.pairs:
+        result.vertexData[attribute].appendFrom(i, mesh.vertexData[attribute], int(indices[0]))
+        result.vertexData[attribute].appendFrom(i + 1, mesh.vertexData[attribute], int(indices[1]))
+        result.vertexData[attribute].appendFrom(i + 2, mesh.vertexData[attribute], int(indices[2]))
+      i += 3
+  else:
+    discard
+  return result
+
+
 # GENERATORS ============================================================================
 
 proc rect*(width=1'f32, height=1'f32, color="ffffffff"): Mesh =
--- a/src/semicongine/resources/mesh.nim	Mon Sep 11 23:15:25 2023 +0700
+++ b/src/semicongine/resources/mesh.nim	Thu Sep 14 23:59:10 2023 +0700
@@ -94,7 +94,7 @@
 
 proc getAccessorData(root: JsonNode, accessor: JsonNode, mainBuffer: seq[uint8]): DataList =
   result = newDataList(thetype=accessor.getGPUType())
-  result.initData(accessor["count"].getInt())
+  result.setLen(accessor["count"].getInt())
 
   let bufferView = root["bufferViews"][accessor["bufferView"].getInt()]
   assert bufferView["buffer"].getInt() == 0, "Currently no external buffers supported"