changeset 1185:565fcfde427a compiletime-tests

did: first seemingly working version of texture/descriptor stuff
author sam <sam@basx.dev>
date Sat, 06 Jul 2024 15:05:28 +0700
parents 3f43c7163029
children 52e926efaac5
files semicongine/core/vector.nim static_utils.nim
diffstat 2 files changed, 116 insertions(+), 131 deletions(-) [+]
line wrap: on
line diff
--- a/semicongine/core/vector.nim	Sat Jul 06 00:31:17 2024 +0700
+++ b/semicongine/core/vector.nim	Sat Jul 06 15:05:28 2024 +0700
@@ -9,20 +9,26 @@
 import ./vulkanapi
 
 type
+  TVec1*[T: SomeNumber] = array[1, T]
   TVec2*[T: SomeNumber] = array[2, T]
   TVec3*[T: SomeNumber] = array[3, T]
   TVec4*[T: SomeNumber] = array[4, T]
-  TVec* = TVec2|TVec3|TVec4
+  TVec* = TVec1|TVec2|TVec3|TVec4
+  Vec1f* = TVec1[float32]
   Vec2f* = TVec2[float32]
   Vec3f* = TVec3[float32]
   Vec4f* = TVec4[float32]
+  Vec1i* = TVec1[int32]
   Vec2i* = TVec2[int32]
   Vec3i* = TVec3[int32]
   Vec4i* = TVec4[int32]
+  Vec1u* = TVec1[uint32]
   Vec2u* = TVec2[uint32]
   Vec3u* = TVec3[uint32]
   Vec4u* = TVec4[uint32]
 
+converter ToVec1*[T: SomeNumber](orig: TVec3[T]|TVec4[T]): TVec1[T] =
+  TVec1[T]([orig[0]])
 converter ToVec2*[T: SomeNumber](orig: TVec3[T]|TVec4[T]): TVec2[T] =
   TVec2[T]([orig[0], orig[1]])
 converter ToVec3*[T: SomeNumber](orig: TVec4[T]): TVec3[T] =
@@ -32,8 +38,11 @@
   TVec4[T]([orig[0], orig[1], orig[2], value])
 func ToVec3*[T: SomeNumber](orig: TVec2[T], value: T = default(T)): TVec3[T] =
   TVec3[T]([orig[0], orig[1], value])
+func ToVec2*[T: SomeNumber](orig: TVec1[T], value: T = default(T)): TVec2[T] =
+  TVec2[T]([orig[0], value])
 
 # define some often used constants
+func ConstOne1[T: SomeNumber](): auto {.compiletime.} = TVec1[T]([T(1)])
 func ConstOne2[T: SomeNumber](): auto {.compiletime.} = TVec2[T]([T(1), T(1)])
 func ConstOne3[T: SomeNumber](): auto {.compiletime.} = TVec3[T]([T(1), T(1), T(1)])
 func ConstOne4[T: SomeNumber](): auto {.compiletime.} = TVec4[T]([T(1), T(1), T(1), T(1)])
@@ -87,14 +96,17 @@
 const X* = ConstX[float32]()
 const Y* = ConstY[float32]()
 const Z* = ConstZ[float32]()
+const One1* = ConstOne1[float32]()
 const One2* = ConstOne2[float32]()
 const One3* = ConstOne3[float32]()
 const One4* = ConstOne4[float32]()
 
+func NewVec1*[T](x: T): auto = TVec1([x])
 func NewVec2*[T](x, y: T): auto = TVec2([x, y])
 func NewVec3*[T](x, y, z: T): auto = TVec3([x, y, z])
 func NewVec4*[T](x, y, z, w: T): auto = TVec4([x, y, z, w])
 
+func To*[T](v: TVec1): auto = TVec1([T(v[0])])
 func To*[T](v: TVec2): auto = TVec2([T(v[0]), T(v[1])])
 func To*[T](v: TVec3): auto = TVec3([T(v[0]), T(v[1]), T(v[2])])
 func To*[T](v: TVec4): auto = TVec4([T(v[0]), T(v[1]), T(v[2]), T(v[3])])
@@ -105,10 +117,12 @@
     items.add(&"{item.float:.5f}")
   & "(" & join(items, "  ") & ")"
 
+func `$`*(v: TVec1[SomeNumber]): string = toString[TVec1[SomeNumber]](v)
 func `$`*(v: TVec2[SomeNumber]): string = toString[TVec2[SomeNumber]](v)
 func `$`*(v: TVec3[SomeNumber]): string = toString[TVec3[SomeNumber]](v)
 func `$`*(v: TVec4[SomeNumber]): string = toString[TVec4[SomeNumber]](v)
 
+func Length*(vec: TVec1): auto = vec[0]
 func Length*(vec: TVec2[SomeFloat]): auto = sqrt(vec[0] * vec[0] + vec[1] * vec[1])
 func Length*(vec: TVec2[SomeInteger]): auto = sqrt(float(vec[0] * vec[0] + vec[1] * vec[1]))
 func Length*(vec: TVec3[SomeFloat]): auto = sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2])
@@ -119,6 +133,8 @@
 func Normal*[T: SomeFloat](vec: TVec2[T]): auto =
   TVec2[T]([vec[1], -vec[0]])
 
+func Normalized*[T: SomeFloat](vec: TVec1[T]): auto =
+  return T(1)
 func Normalized*[T: SomeFloat](vec: TVec2[T]): auto =
   let l = vec.Length
   if l == 0: vec
@@ -133,117 +149,124 @@
   else: TVec4[T]([vec[0] / l, vec[1] / l, vec[2] / l, vec[3] / l])
 
 # scalar operations
+func `+`*(a: TVec1, b: SomeNumber): auto = TVec1([a[0] + b])
 func `+`*(a: TVec2, b: SomeNumber): auto = TVec2([a[0] + b, a[1] + b])
 func `+`*(a: TVec3, b: SomeNumber): auto = TVec3([a[0] + b, a[1] + b, a[2] + b])
-func `+`*(a: TVec4, b: SomeNumber): auto = TVec4([a[0] + b, a[1] + b, a[2] + b,
-    a[3] + b])
+func `+`*(a: TVec4, b: SomeNumber): auto = TVec4([a[0] + b, a[1] + b, a[2] + b, a[3] + b])
+func `-`*(a: TVec1, b: SomeNumber): auto = TVec1([a[0] - b])
 func `-`*(a: TVec2, b: SomeNumber): auto = TVec2([a[0] - b, a[1] - b])
 func `-`*(a: TVec3, b: SomeNumber): auto = TVec3([a[0] - b, a[1] - b, a[2] - b])
 func `-`*(a: TVec4, b: SomeNumber): auto = TVec4([a[0] - b, a[1] - b, a[2] - b,
     a[3] - b])
+func `*`*(a: TVec1, b: SomeNumber): auto = TVec1([a[0] * b])
 func `*`*(a: TVec2, b: SomeNumber): auto = TVec2([a[0] * b, a[1] * b])
 func `*`*(a: TVec3, b: SomeNumber): auto = TVec3([a[0] * b, a[1] * b, a[2] * b])
 func `*`*(a: TVec4, b: SomeNumber): auto = TVec4([a[0] * b, a[1] * b, a[2] * b,
     a[3] * b])
-func `/`*[T: SomeInteger](a: TVec2[T], b: SomeInteger): auto = TVec2([a[
-    0] div b, a[1] div b])
+func `/`*[T: SomeInteger](a: TVec1[T], b: SomeInteger): auto = TVec1([a[0] div b])
+func `/`*[T: SomeFloat](a: TVec1[T], b: SomeFloat): auto = TVec1([a[0] / b])
+func `/`*[T: SomeInteger](a: TVec2[T], b: SomeInteger): auto = TVec2([a[0] div b, a[1] div b])
 func `/`*[T: SomeFloat](a: TVec2[T], b: SomeFloat): auto = TVec2([a[0] / b, a[1] / b])
-func `/`*[T: SomeInteger](a: TVec3[T], b: SomeInteger): auto = TVec3([a[
-    0] div b, a[1] div b, a[2] div b])
-func `/`*[T: SomeFloat](a: TVec3[T], b: SomeFloat): auto = TVec3([a[0] / b, a[
-    1] / b, a[2] / b])
-func `/`*[T: SomeInteger](a: TVec4[T], b: SomeInteger): auto = TVec4([a[
-    0] div b, a[1] div b, a[2] div b, a[3] div b])
-func `/`*[T: SomeFloat](a: TVec4[T], b: SomeFloat): auto = TVec4([a[0] / b, a[
-    1] / b, a[2] / b, a[3] / b])
+func `/`*[T: SomeInteger](a: TVec3[T], b: SomeInteger): auto = TVec3([a[0] div b, a[1] div b, a[2] div b])
+func `/`*[T: SomeFloat](a: TVec3[T], b: SomeFloat): auto = TVec3([a[0] / b, a[1] / b, a[2] / b])
+func `/`*[T: SomeInteger](a: TVec4[T], b: SomeInteger): auto = TVec4([a[0] div b, a[1] div b, a[2] div b, a[3] div b])
+func `/`*[T: SomeFloat](a: TVec4[T], b: SomeFloat): auto = TVec4([a[0] / b, a[1] / b, a[2] / b, a[3] / b])
 
+func `+`*(a: SomeNumber, b: TVec1): auto = TVec1([a + b[0]])
 func `+`*(a: SomeNumber, b: TVec2): auto = TVec2([a + b[0], a + b[1]])
 func `+`*(a: SomeNumber, b: TVec3): auto = TVec3([a + b[0], a + b[1], a + b[2]])
-func `+`*(a: SomeNumber, b: TVec4): auto = TVec4([a + b[0], a + b[1], a + b[2],
-    a + b[3]])
+func `+`*(a: SomeNumber, b: TVec4): auto = TVec4([a + b[0], a + b[1], a + b[2], a + b[3]])
+func `-`*(a: SomeNumber, b: TVec1): auto = TVec1([a - b[0]])
 func `-`*(a: SomeNumber, b: TVec2): auto = TVec2([a - b[0], a - b[1]])
 func `-`*(a: SomeNumber, b: TVec3): auto = TVec3([a - b[0], a - b[1], a - b[2]])
-func `-`*(a: SomeNumber, b: TVec4): auto = TVec4([a - b[0], a - b[1], a - b[2],
-    a - b[3]])
+func `-`*(a: SomeNumber, b: TVec4): auto = TVec4([a - b[0], a - b[1], a - b[2], a - b[3]])
+func `*`*(a: SomeNumber, b: TVec1): auto = TVec1([a * b[0]])
 func `*`*(a: SomeNumber, b: TVec2): auto = TVec2([a * b[0], a * b[1]])
 func `*`*(a: SomeNumber, b: TVec3): auto = TVec3([a * b[0], a * b[1], a * b[2]])
-func `*`*(a: SomeNumber, b: TVec4): auto = TVec4([a * b[0], a * b[1], a * b[2],
-    a * b[3]])
-func `/`*[T: SomeInteger](a: SomeInteger, b: TVec2[T]): auto = TVec2([a div b[
-    0], a div b[1]])
+func `*`*(a: SomeNumber, b: TVec4): auto = TVec4([a * b[0], a * b[1], a * b[2], a * b[3]])
+func `/`*[T: SomeInteger](a: SomeInteger, b: TVec1[T]): auto = TVec1([a div b[0]])
+func `/`*[T: SomeFloat](a: SomeFloat, b: TVec1[T]): auto = TVec1([a / b[0]])
+func `/`*[T: SomeInteger](a: SomeInteger, b: TVec2[T]): auto = TVec2([a div b[0], a div b[1]])
 func `/`*[T: SomeFloat](a: SomeFloat, b: TVec2[T]): auto = TVec2([a / b[0], a / b[1]])
-func `/`*[T: SomeInteger](a: SomeInteger, b: TVec3[T]): auto = TVec3([a div b[
-    0], a div b[1], a div b[2]])
-func `/`*[T: SomeFloat](a: SomeFloat, b: TVec3[T]): auto = TVec3([a / b[0], a /
-    b[1], a / b[2]])
+func `/`*[T: SomeInteger](a: SomeInteger, b: TVec3[T]): auto = TVec3([a div b[0], a div b[1], a div b[2]])
+func `/`*[T: SomeFloat](a: SomeFloat, b: TVec3[T]): auto = TVec3([a / b[0], a / b[1], a / b[2]])
 func `/`*[T: SomeInteger](a: SomeInteger, b: TVec4[T]): auto = TVec4([a div b[
     0], a div b[1], a div b[2], a div b[3]])
 func `/`*[T: SomeFloat](a: SomeFloat, b: TVec4[T]): auto = TVec4([a / b[0], a /
     b[1], a / b[2], a / b[3]])
 
 # compontent-wise operations
+func `+`*(a, b: TVec1): auto = TVec1([a[0] + b[0]])
 func `+`*(a, b: TVec2): auto = TVec2([a[0] + b[0], a[1] + b[1]])
 func `+`*(a, b: TVec3): auto = TVec3([a[0] + b[0], a[1] + b[1], a[2] + b[2]])
-func `+`*(a, b: TVec4): auto = TVec4([a[0] + b[0], a[1] + b[1], a[2] + b[2], a[
-    3] + b[3]])
+func `+`*(a, b: TVec4): auto = TVec4([a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]])
+func `-`*(a: TVec1): auto = TVec1([-a[0]])
 func `-`*(a: TVec2): auto = TVec2([-a[0], -a[1]])
 func `-`*(a: TVec3): auto = TVec3([-a[0], -a[1], -a[2]])
 func `-`*(a: TVec4): auto = TVec4([-a[0], -a[1], -a[2], -a[3]])
+func `-`*(a, b: TVec1): auto = TVec1([a[0] - b[0]])
 func `-`*(a, b: TVec2): auto = TVec2([a[0] - b[0], a[1] - b[1]])
 func `-`*(a, b: TVec3): auto = TVec3([a[0] - b[0], a[1] - b[1], a[2] - b[2]])
-func `-`*(a, b: TVec4): auto = TVec4([a[0] - b[0], a[1] - b[1], a[2] - b[2], a[
-    3] - b[3]])
+func `-`*(a, b: TVec4): auto = TVec4([a[0] - b[0], a[1] - b[1], a[2] - b[2], a[3] - b[3]])
+func `*`*(a, b: TVec1): auto = TVec1([a[0] * b[0]])
 func `*`*(a, b: TVec2): auto = TVec2([a[0] * b[0], a[1] * b[1]])
 func `*`*(a, b: TVec3): auto = TVec3([a[0] * b[0], a[1] * b[1], a[2] * b[2]])
-func `*`*(a, b: TVec4): auto = TVec4([a[0] * b[0], a[1] * b[1], a[2] * b[2], a[
-    3] * b[3]])
-func `/`*[T: SomeInteger](a, b: TVec2[T]): auto = TVec2([a[0] div b[0], a[
-    1] div b[1]])
+func `*`*(a, b: TVec4): auto = TVec4([a[0] * b[0], a[1] * b[1], a[2] * b[2], a[3] * b[3]])
+func `/`*[T: SomeInteger](a, b: TVec1[T]): auto = TVec1([a[0] div b[0]])
+func `/`*[T: SomeFloat](a, b: TVec1[T]): auto = TVec1([a[0] / b[0]])
+func `/`*[T: SomeInteger](a, b: TVec2[T]): auto = TVec2([a[0] div b[0], a[1] div b[1]])
 func `/`*[T: SomeFloat](a, b: TVec2[T]): auto = TVec2([a[0] / b[0], a[1] / b[1]])
-func `/`*[T: SomeInteger](a, b: TVec3[T]): auto = TVec3([a[0] div b[0], a[
-    1] div b[1], a[2] div b[2]])
-func `/`*[T: SomeFloat](a, b: TVec3[T]): auto = TVec3([a[0] / b[0], a[1] / b[1],
-    a[2] / b[2]])
-func `/`*[T: SomeInteger](a, b: TVec4[T]): auto = TVec4([a[0] div b[0], a[
-    1] div b[1], a[2] div b[2], a[3] div b[3]])
-func `/`*[T: SomeFloat](a, b: TVec4[T]): auto = TVec4([a[0] / b[0], a[1] / b[1],
-    a[2] / b[2], a[3] / b[3]])
+func `/`*[T: SomeInteger](a, b: TVec3[T]): auto = TVec3([a[0] div b[0], a[1] div b[1], a[2] div b[2]])
+func `/`*[T: SomeFloat](a, b: TVec3[T]): auto = TVec3([a[0] / b[0], a[1] / b[1], a[2] / b[2]])
+func `/`*[T: SomeInteger](a, b: TVec4[T]): auto = TVec4([a[0] div b[0], a[1] div b[1], a[2] div b[2], a[3] div b[3]])
+func `/`*[T: SomeFloat](a, b: TVec4[T]): auto = TVec4([a[0] / b[0], a[1] / b[1], a[2] / b[2], a[3] / b[3]])
 
 # assignment operations, scalar
+func `+=`*(a: var TVec1, b: SomeNumber) = a = a + b
 func `+=`*(a: var TVec2, b: SomeNumber) = a = a + b
 func `+=`*(a: var TVec3, b: SomeNumber) = a = a + b
 func `+=`*(a: var TVec4, b: SomeNumber) = a = a + b
+func `-=`*(a: var TVec1, b: SomeNumber) = a = a - b
 func `-=`*(a: var TVec2, b: SomeNumber) = a = a - b
 func `-=`*(a: var TVec3, b: SomeNumber) = a = a - b
 func `-=`*(a: var TVec4, b: SomeNumber) = a = a - b
+func `*=`*(a: var TVec1, b: SomeNumber) = a = a * b
 func `*=`*(a: var TVec2, b: SomeNumber) = a = a * b
 func `*=`*(a: var TVec3, b: SomeNumber) = a = a * b
 func `*=`*(a: var TVec4, b: SomeNumber) = a = a * b
+func `/=`*(a: var TVec1, b: SomeNumber) = a = a / b
 func `/=`*(a: var TVec2, b: SomeNumber) = a = a / b
 func `/=`*(a: var TVec3, b: SomeNumber) = a = a / b
 func `/=`*(a: var TVec4, b: SomeNumber) = a = a / b
 # assignment operations, vector
+func `+=`*(a: var TVec1, b: TVec1) = a = a + b
 func `+=`*(a: var TVec2, b: TVec2) = a = a + b
 func `+=`*(a: var TVec3, b: TVec3) = a = a + b
 func `+=`*(a: var TVec4, b: TVec4) = a = a + b
+func `-=`*(a: var TVec1, b: TVec1) = a = a - b
 func `-=`*(a: var TVec2, b: TVec2) = a = a - b
 func `-=`*(a: var TVec3, b: TVec3) = a = a - b
 func `-=`*(a: var TVec4, b: TVec4) = a = a - b
+func `*=`*(a: var TVec1, b: TVec1) = a = a * b
 func `*=`*(a: var TVec2, b: TVec2) = a = a * b
 func `*=`*(a: var TVec3, b: TVec3) = a = a * b
 func `*=`*(a: var TVec4, b: TVec4) = a = a * b
+func `/=`*(a: var TVec1, b: TVec1) = a = a / b
 func `/=`*(a: var TVec2, b: TVec2) = a = a / b
 func `/=`*(a: var TVec3, b: TVec3) = a = a / b
 func `/=`*(a: var TVec4, b: TVec4) = a = a / b
 
 
 # special operations
+func Pow*(a: TVec1, b: SomeNumber): auto =
+  TVec1([pow(a[0], b)])
 func Pow*(a: TVec2, b: SomeNumber): auto =
   TVec2([pow(a[0], b), pow(a[1], b)])
 func Pow*(a: TVec3, b: SomeNumber): auto =
   TVec3([pow(a[0], b), pow(a[1], b), pow(a[2], b)])
 func Pow*(a: TVec4, b: SomeNumber): auto =
   TVec4([pow(a[0], b), pow(a[1], b), pow(a[2], b), pow(a[3], b)])
+func Dot*(a, b: TVec1): auto = a[0] * b[0]
 func Dot*(a, b: TVec2): auto = a[0] * b[0] + a[1] * b[1]
 func Dot*(a, b: TVec3): auto = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]
 func Dot*(a, b: TVec4): auto = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]
@@ -342,6 +365,7 @@
     for i in 0 ..< result.len:
       result[i] = rand(1.0)
 
+makeRandomInit(TVec1)
 makeRandomInit(TVec2)
 makeRandomInit(TVec3)
 makeRandomInit(TVec4)
--- a/static_utils.nim	Sat Jul 06 00:31:17 2024 +0700
+++ b/static_utils.nim	Sat Jul 06 15:05:28 2024 +0700
@@ -44,18 +44,16 @@
   DirectGPUMemory = object
     vk: VkDeviceMemory
     size: uint64
-    data: pointer
-    needsFlush: bool # usually true
+    rawPointer: pointer
   GPUMemory = IndirectGPUMemory | DirectGPUMemory
 
   Buffer[TMemory: GPUMemory] = object
-    memory: TMemory
     vk: VkBuffer
-    offset: uint64
     size: uint64
+    rawPointer: pointer
   Texture[T: TextureType, TMemory: GPUMemory] = object
+    vk: VkImage
     memory: TMemory
-    vk: VkImage
     format: VkFormat
     imageview: VkImageView
     sampler: VkSampler
@@ -102,6 +100,10 @@
 func depth(texture: Texture): int =
   default(elementType(texture.data)).len
 
+func pointerOffset[T: SomeInteger](p: pointer, offset: T): pointer =
+  cast[pointer](cast[T](p) + offset)
+
+
 proc GetVkFormat(depth: int, usage: openArray[VkImageUsageFlagBits]): VkFormat =
   const DEPTH_FORMAT_MAP = [
     0: [VK_FORMAT_UNDEFINED, VK_FORMAT_UNDEFINED],
@@ -330,9 +332,9 @@
 template size(gpuValue: GPUValue): uint64 =
   sizeof(gpuValue.data).uint64
 
-template datapointer(gpuArray: GPUArray): pointer =
+template rawPointer(gpuArray: GPUArray): pointer =
   addr(gpuArray.data[0])
-template datapointer(gpuValue: GPUValue): pointer =
+template rawPointer(gpuValue: GPUValue): pointer =
   addr(gpuValue.data)
 
 proc RequiredMemorySize(buffer: VkBuffer): uint64 =
@@ -370,7 +372,7 @@
   assert score > 0, "Unable to find integrated or discrete GPU"
 
 
-proc GetDirectMemoryTypeIndex(): uint32 =
+proc GetDirectMemoryType(): uint32 =
   var physicalProperties: VkPhysicalDeviceMemoryProperties
   vkGetPhysicalDeviceMemoryProperties(vulkan.physicalDevice, addr(physicalProperties))
 
@@ -396,72 +398,18 @@
       return i
   assert false, &"Queue of type {qType} not found"
 
-proc GetQueue(device: VkDevice, queueFamilyIndex: uint32, qType: VkQueueFlagBits): VkQueue =
-  vkGetDeviceQueue(
-    device,
-    queueFamilyIndex,
-    0,
-    addr(result),
-  )
-
 proc GetSurfaceFormat(): VkFormat =
   # EVERY windows driver and almost every linux driver should support this
   VK_FORMAT_B8G8R8A8_SRGB
 
-template WithSingleUseCommandBuffer(cmd, body: untyped): untyped =
-  block:
-    var
-      commandBufferPool: VkCommandPool
-      createInfo = VkCommandPoolCreateInfo(
-        sType: VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
-        flags: toBits [VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT],
-        queueFamilyIndex: vulkan.queueFamilyIndex,
-      )
-    checkVkResult vkCreateCommandPool(vulkan.device, addr createInfo, nil, addr(commandBufferPool))
-    var
-      `cmd` {.inject.}: VkCommandBuffer
-      allocInfo = VkCommandBufferAllocateInfo(
-        sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
-        commandPool: commandBufferPool,
-        level: VK_COMMAND_BUFFER_LEVEL_PRIMARY,
-        commandBufferCount: 1,
-      )
-    checkVkResult vulkan.device.vkAllocateCommandBuffers(addr allocInfo, addr(`cmd`))
-    var beginInfo = VkCommandBufferBeginInfo(
-      sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
-      flags: VkCommandBufferUsageFlags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT),
-    )
-    checkVkResult `cmd`.vkBeginCommandBuffer(addr beginInfo)
-
-    body
-
-    checkVkResult `cmd`.vkEndCommandBuffer()
-    var submitInfo = VkSubmitInfo(
-      sType: VK_STRUCTURE_TYPE_SUBMIT_INFO,
-      commandBufferCount: 1,
-      pCommandBuffers: addr(`cmd`),
-    )
-
-    var
-      fence: VkFence
-      fenceInfo = VkFenceCreateInfo(
-        sType: VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
-        # flags: toBits [VK_FENCE_CREATE_SIGNALED_BIT]
-      )
-    checkVkResult vulkan.device.vkCreateFence(addr(fenceInfo), nil, addr(fence))
-    checkVkResult vkQueueSubmit(vulkan.queue, 1, addr(submitInfo), fence)
-    checkVkResult vkWaitForFences(vulkan.device, 1, addr fence, false, high(uint64))
-    vkDestroyCommandPool(vulkan.device, commandBufferPool, nil)
-
-
 proc UpdateGPUBuffer(gpuData: GPUData) =
   if gpuData.size == 0:
     return
   when UsesDirectMemory(gpuData):
-    copyMem(cast[pointer](cast[uint64](gpuData.buffer.memory.data) + gpuData.buffer.offset + gpuData.offset), gpuData.datapointer, gpuData.size)
+    copyMem(pointerOffset(gpuData.buffer.rawPointer, gpuData.offset), gpuData.rawPointer, gpuData.size)
   else:
-    WithStagingBuffer(gpuData.buffer.vk, gpuData.buffer.vk.RequiredMemorySize(), GetDirectMemoryTypeIndex(), stagingPtr):
-      copyMem(stagingPtr, gpuData.datapointer, gpuData.size)
+    WithStagingBuffer((gpuData.buffer.vk, gpuData.offset), gpuData.buffer.vk.RequiredMemorySize(), GetDirectMemoryType(), stagingPtr):
+      copyMem(stagingPtr, gpuData.rawPointer, gpuData.size)
 
 proc UpdateAllGPUBuffers[T](value: T) =
   for name, fieldvalue in value.fieldPairs():
@@ -481,6 +429,7 @@
     # when typeof(value) is Texture:
     # assert value.texture.vk.Valid
 
+  # TODO: missing stuff here? only for FiF, but not multiple different sets?
   # allocate
   var layouts = newSeqWith(descriptorSet.vk.len, layout)
   var allocInfo = VkDescriptorSetAllocateInfo(
@@ -491,7 +440,8 @@
   )
   checkVkResult vkAllocateDescriptorSets(vulkan.device, addr(allocInfo), descriptorSet.vk.ToCPointer)
 
-  # write
+  # allocate seq with high cap to prevent realocation while adding to set
+  # (which invalidates pointers that are passed to the vulkan api call)
   var descriptorSetWrites = newSeqOfCap[VkWriteDescriptorSet](1024)
   var imageWrites = newSeqOfCap[VkDescriptorImageInfo](1024)
   var bufferWrites = newSeqOfCap[VkDescriptorBufferInfo](1024)
@@ -501,8 +451,8 @@
       when typeof(fieldValue) is GPUValue:
         bufferWrites.add VkDescriptorBufferInfo(
           buffer: fieldValue.buffer.vk,
-          offset: fieldValue.buffer.offset,
-          range: fieldValue.buffer.size,
+          offset: fieldValue.offset,
+          range: fieldValue.size,
         )
         descriptorSetWrites.add VkWriteDescriptorSet(
           sType: VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
@@ -533,7 +483,6 @@
       elif typeof(fieldValue) is array:
         discard
         when elementType(fieldValue) is Texture:
-          echo "Add texture array descriptor set write for set " & $i & " " & fieldName
           for textureIndex in 0 ..< descriptorCount:
             imageWrites.add VkDescriptorImageInfo(
               sampler: fieldValue[textureIndex].sampler,
@@ -547,7 +496,7 @@
             dstArrayElement: 0,
             descriptorType: descriptorType,
             descriptorCount: descriptorCount,
-            pImageInfo: addr(imageWrites[^fieldValue.len]),
+            pImageInfo: addr(imageWrites[^descriptorCount.int]),
             pBufferInfo: nil,
           )
         else:
@@ -555,7 +504,13 @@
       else:
         {.error: "Unsupported descriptor type: " & tt.name(typeof(fieldValue)).}
 
-  vkUpdateDescriptorSets(vulkan.device, descriptorSetWrites.len.uint32, descriptorSetWrites.ToCPointer, 0, nil)
+  vkUpdateDescriptorSets(
+    device = vulkan.device,
+    descriptorWriteCount = descriptorSetWrites.len.uint32,
+    pDescriptorWrites = descriptorSetWrites.ToCPointer,
+    descriptorCopyCount = 0,
+    pDescriptorCopies = nil,
+  )
 
 converter toVkIndexType(indexType: IndexType): VkIndexType =
   case indexType:
@@ -974,7 +929,6 @@
 
 proc AllocateDirectMemory(size: uint64): DirectGPUMemory =
   result.size = size
-  result.needsFlush = true
 
   # find a good memory type
   var physicalProperties: VkPhysicalDeviceMemoryProperties
@@ -990,23 +944,22 @@
       if size > biggestHeap:
         biggestHeap = size
         memoryTypeIndex = i
-        result.needsFlush = not (VK_MEMORY_PROPERTY_HOST_COHERENT_BIT in flags)
 
   assert memoryTypeIndex != high(uint32), "Unable to find indirect memory type"
-  result.vk = svkAllocateMemory(result.size, GetDirectMemoryTypeIndex())
+  result.vk = svkAllocateMemory(result.size, GetDirectMemoryType())
   checkVkResult vkMapMemory(
     device = vulkan.device,
     memory = result.vk,
     offset = 0'u64,
     size = result.size,
     flags = VkMemoryMapFlags(0),
-    ppData = addr(result.data)
+    ppData = addr(result.rawPointer)
   )
 
 proc AllocateIndirectBuffer(renderData: var RenderData, size: uint64, btype: BufferType) =
   if size == 0:
     return
-  var buffer = Buffer[IndirectGPUMemory](size: size)
+  var buffer = Buffer[IndirectGPUMemory](size: size, rawPointer: nil)
 
   let usageFlags = case btype:
     of VertexBuffer: [VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_DST_BIT]
@@ -1018,10 +971,9 @@
   # TODO: use RequiredMemorySize()
   for (memory, usedOffset) in renderData.indirectMemory.mitems:
     if memory.size - usedOffset >= size:
-      buffer.offset = usedOffset
       # create buffer
       buffer.vk = svkCreateBuffer(buffer.size, usageFlags)
-      checkVkResult vkBindBufferMemory(vulkan.device, buffer.vk, memory.vk, buffer.offset)
+      checkVkResult vkBindBufferMemory(vulkan.device, buffer.vk, memory.vk, usedOffset)
       renderData.indirectBuffers.add (buffer, btype, 0'u64)
       # update memory area offset
       usedOffset = alignedTo(usedOffset + size, MEMORY_ALIGNMENT)
@@ -1045,9 +997,9 @@
   # TODO: use RequiredMemorySize()
   for (memory, usedOffset) in renderData.directMemory.mitems:
     if memory.size - usedOffset >= size:
-      buffer.offset = usedOffset
       buffer.vk = svkCreateBuffer(buffer.size, usageFlags)
-      checkVkResult vkBindBufferMemory(vulkan.device, buffer.vk, memory.vk, buffer.offset)
+      checkVkResult vkBindBufferMemory(vulkan.device, buffer.vk, memory.vk, usedOffset)
+      buffer.rawPointer = pointerOffset(memory.rawPointer, usedOffset)
       renderData.directBuffers.add (buffer, btype, 0'u64)
       # update memory area offset
       usedOffset = alignedTo(usedOffset + size, MEMORY_ALIGNMENT)
@@ -1289,7 +1241,7 @@
 
   # data transfer and layout transition
   TransitionImageLayout(texture.vk, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
-  WithStagingBuffer((texture.vk, texture.imageview, texture.width, texture.height), size, GetDirectMemoryTypeIndex(), stagingPtr):
+  WithStagingBuffer((texture.vk, texture.imageview, texture.width, texture.height), size, GetDirectMemoryType(), stagingPtr):
     copyMem(stagingPtr, texture.data.ToCPointer, size)
     TransitionImageLayout(texture.vk, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
 
@@ -1299,7 +1251,13 @@
 proc UploadTextures(renderdata: var RenderData, descriptorSet: var DescriptorSet) =
   for name, value in fieldPairs(descriptorSet.data):
     when typeof(value) is Texture:
+      echo "Upload texture '", name, "'"
       renderdata.createTextureImage(value)
+    elif typeof(value) is array:
+      when elementType(value) is Texture:
+        echo "Upload texture ARRAY '", name, "'"
+        for texture in value.mitems:
+          renderdata.createTextureImage(texture)
 
 proc HasGPUValueField[T](name: static string): bool {.compileTime.} =
   for fieldname, value in default(T).fieldPairs():
@@ -1480,7 +1438,7 @@
     device: dev,
     physicalDevice: pDevice,
     queueFamilyIndex: qfi,
-    queue: dev.GetQueue(qfi, VK_QUEUE_GRAPHICS_BIT)
+    queue: svkGetDeviceQueue(dev, qfi, VK_QUEUE_GRAPHICS_BIT)
   )
 
   var myMesh1 = MeshA(
@@ -1488,15 +1446,16 @@
   )
   var uniforms1 = DescriptorSet[UniformsA, MaterialSet](
     data: UniformsA(
+      defaultTexture: Texture[TVec3[uint8], IndirectGPUMemory](width: 1, height: 1, data: @[TVec3[uint8]([0'u8, 0'u8, 0'u8])]),
       materials: GPUValue[array[3, MaterialA], IndirectGPUMemory](data: [
         MaterialA(reflection: 0, baseColor: NewVec3f(1, 0, 0)),
         MaterialA(reflection: 0.1, baseColor: NewVec3f(0, 1, 0)),
         MaterialA(reflection: 0.5, baseColor: NewVec3f(0, 0, 1)),
     ]),
     materialTextures: [
-      Texture[TVec3[uint8], IndirectGPUMemory](),
-      Texture[TVec3[uint8], IndirectGPUMemory](),
-      Texture[TVec3[uint8], IndirectGPUMemory](),
+      Texture[TVec3[uint8], IndirectGPUMemory](width: 1, height: 1, data: @[TVec3[uint8]([0'u8, 0'u8, 0'u8])]),
+      Texture[TVec3[uint8], IndirectGPUMemory](width: 1, height: 1, data: @[TVec3[uint8]([0'u8, 0'u8, 0'u8])]),
+      Texture[TVec3[uint8], IndirectGPUMemory](width: 1, height: 1, data: @[TVec3[uint8]([0'u8, 0'u8, 0'u8])]),
     ]
   )
   )
@@ -1504,7 +1463,12 @@
     rotation: GPUArray[Vec4f, IndirectGPUMemory](data: @[NewVec4f(1, 0, 0, 0.1), NewVec4f(0, 1, 0, 0.1)]),
     objPosition: GPUArray[Vec3f, IndirectGPUMemory](data: @[NewVec3f(0, 0, 0), NewVec3f(1, 1, 1)]),
   )
-  var myGlobals = DescriptorSet[GlobalsA, GlobalSet]()
+  var myGlobals = DescriptorSet[GlobalsA, GlobalSet](
+    data: GlobalsA(
+      fontAtlas: Texture[TVec3[uint8], IndirectGPUMemory](width: 1, height: 1, data: @[TVec3[uint8]([0'u8, 0'u8, 0'u8])]),
+      settings: GPUValue[ShaderSettings, IndirectGPUMemory](data: ShaderSettings(gamma: 1.0))
+    )
+  )
 
   # setup for rendering (TODO: swapchain & framebuffers)
   let renderpass = CreateRenderPass(GetSurfaceFormat())
@@ -1567,11 +1531,8 @@
   renderdata.AssignIndirectBuffers(UniformBuffer, myGlobals)
   renderdata.AssignDirectBuffers(UniformBuffer, myGlobals)
 
+  renderdata.UploadTextures(myGlobals)
   renderdata.UploadTextures(uniforms1)
-  renderdata.UploadTextures(myGlobals)
-
-  echo uniforms1.data.materialTextures
-
 
   # copy everything to GPU
   echo "Copying all data to GPU memory"