changeset 243:3b388986c7fd

did: refactor texture data structures, add more complete (untested) material import
author Sam <sam@basx.dev>
date Mon, 22 May 2023 00:50:41 +0700
parents 66205c67df6c
children f52fccedf5ab
files src/semicongine/core/imagetypes.nim src/semicongine/entity.nim src/semicongine/renderer.nim src/semicongine/resources/mesh.nim src/semicongine/vulkan/descriptor.nim src/semicongine/vulkan/image.nim src/semicongine/vulkan/pipeline.nim src/semicongine/vulkan/swapchain.nim
diffstat 8 files changed, 220 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/src/semicongine/core/imagetypes.nim	Sun May 21 01:04:55 2023 +0700
+++ b/src/semicongine/core/imagetypes.nim	Mon May 22 00:50:41 2023 +0700
@@ -1,10 +1,31 @@
+import ./vulkanapi
+
 type
   Pixel* = array[4, uint8]
   ImageObject* = object
     width*: uint32
     height*: uint32
     imagedata*: seq[Pixel]
+  Sampler* = object
+    magnification*: VkFilter
+    minification*: VkFilter
+    wrapModeS*: VkSamplerAddressMode
+    wrapModeT*: VkSamplerAddressMode
+    filter*: VkFilter # TODO: replace with mag/minification
+
   Image* = ref ImageObject
+  TextureObject = object
+    image*: Image
+    sampler*: Sampler
+  Texture* = ref TextureObject
+
+proc DefaultSampler*(): Sampler =
+  Sampler(
+    magnification: VK_FILTER_LINEAR,
+    minification: VK_FILTER_LINEAR,
+    wrapModeS: VK_SAMPLER_ADDRESS_MODE_REPEAT,
+    wrapModeT: VK_SAMPLER_ADDRESS_MODE_REPEAT,
+  )
 
 proc newImage*(width, height: uint32, imagedata: seq[Pixel] = @[]): Image =
   assert width > 0 and height > 0
--- a/src/semicongine/entity.nim	Sun May 21 01:04:55 2023 +0700
+++ b/src/semicongine/entity.nim	Mon May 22 00:50:41 2023 +0700
@@ -13,7 +13,7 @@
     name*: string
     root*: Entity
     shaderGlobals*: Table[string, DataList]
-    textures*: Table[string, (seq[Image], VkFilter)]
+    textures*: Table[string, seq[Texture]]
 
   Entity* = ref object of RootObj
     name*: string
@@ -42,11 +42,11 @@
 func setShaderGlobalArray*[T](scene: var Scene, name: string, value: seq[T]) =
   setValues[T](scene.shaderGlobals[name], value)
 
-func addTextures*(scene: var Scene, name: string, texture: seq[Image], interpolation=VK_FILTER_LINEAR) =
-  scene.textures[name] = (texture, interpolation)
+func addTextures*(scene: var Scene, name: string, textures: seq[Texture], interpolation=VK_FILTER_LINEAR) =
+  scene.textures[name] = textures
 
-func addTexture*(scene: var Scene, name: string, texture: Image, interpolation=VK_FILTER_LINEAR) =
-  scene.textures[name] = (@[texture], interpolation)
+func addTexture*(scene: var Scene, name: string, texture: Texture) =
+  scene.textures[name] = @[texture]
 
 func newScene*(name: string, root: Entity): Scene =
   Scene(name: name, root: root)
--- a/src/semicongine/renderer.nim	Sun May 21 01:04:55 2023 +0700
+++ b/src/semicongine/renderer.nim	Mon May 22 00:50:41 2023 +0700
@@ -24,7 +24,7 @@
     vertexBuffers*: Table[MemoryPerformanceHint, Buffer]
     indexBuffer*: Buffer
     uniformBuffers*: seq[Buffer] # one per frame-in-flight
-    textures*: Table[string, seq[Texture]] # per frame-in-flight
+    textures*: Table[string, seq[VulkanTexture]] # per frame-in-flight
     attributeLocation*: Table[string, MemoryPerformanceHint]
     attributeBindingNumber*: Table[string, int]
     transformAttribute: string # name of attribute that is used for per-instance mesh transformation
@@ -176,11 +176,10 @@
             requireMappable=true,
             preferVRAM=true,
           )
-      for name, images in scene.textures.pairs:
+      for name, textures in scene.textures.pairs:
         data.textures[name] = @[]
-        let interpolation = images[1]
-        for image in images[0]:
-          data.textures[name].add renderer.device.createTexture(image.width, image.height, 4, addr image.imagedata[0][0], interpolation)
+        for texture in textures:
+          data.textures[name].add renderer.device.uploadTexture(texture)
       data.descriptorSets[pipeline.vk] = pipeline.setupDescriptors(data.uniformBuffers, data.textures, inFlightFrames=renderer.swapchain.inFlightFrames)
       for frame_i in 0 ..< renderer.swapchain.inFlightFrames:
         data.descriptorSets[pipeline.vk][frame_i].writeDescriptorSet()
--- a/src/semicongine/resources/mesh.nim	Sun May 21 01:04:55 2023 +0700
+++ b/src/semicongine/resources/mesh.nim	Mon May 22 00:50:41 2023 +0700
@@ -10,6 +10,8 @@
 import ../mesh
 import ../core
 
+import ./image
+
 
 type
   glTFHeader = object
@@ -19,6 +21,21 @@
   glTFData = object
     structuredContent: JsonNode
     binaryBufferData: seq[uint8]
+  glTFMaterial = object
+    color: Vec4f
+    colorTexture: Texture
+    colorTextureIndex: uint32
+    metallic: float32
+    roughness: float32
+    metallicRoughnessTexture: Texture
+    metallicRoughnessTextureIndex: uint32
+    normalTexture: Texture
+    normalTextureIndex: uint32
+    occlusionTexture: Texture
+    occlusionTextureIndex: uint32
+    emissiveTexture: Texture
+    emissiveTextureIndex: uint32
+    emissiveFactor: Vec3f
 
 const
   JSON_CHUNK = 0x4E4F534A
@@ -31,6 +48,19 @@
     5125: UInt32,
     5126: Float32,
   }.toTable
+  SAMPLER_FILTER_MODE_MAP = {
+    9728: VK_FILTER_NEAREST,
+    9729: VK_FILTER_LINEAR,
+    9984: VK_FILTER_NEAREST,
+    9985: VK_FILTER_LINEAR,
+    9986: VK_FILTER_NEAREST,
+    9987: VK_FILTER_LINEAR,
+  }.toTable
+  SAMPLER_WRAP_MODE_MAP = {
+    33071: VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
+    33648: VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
+    10497: VK_SAMPLER_ADDRESS_MODE_REPEAT
+  }.toTable
 
 func getGPUType(accessor: JsonNode): DataType =
   # TODO: no full support for all datatypes that glTF may provide
@@ -68,6 +98,16 @@
     of Float32: return Vec4F32
     else: raise newException(Exception, &"Unsupported data type: {componentType} {theType}")
 
+proc getBufferViewData(bufferView: JsonNode, mainBuffer: var seq[uint8], baseBufferOffset=0): seq[uint8] =
+  assert bufferView["buffer"].getInt() == 0, "Currently no external buffers supported"
+
+  result = newSeq[uint8](bufferView["byteLength"].getInt())
+  let bufferOffset = bufferView["byteOffset"].getInt() + baseBufferOffset
+  var dstPointer = addr result[0]
+
+  if bufferView.hasKey("byteStride"):
+    raise newException(Exception, "Unsupported feature: byteStride in buffer view")
+  copyMem(dstPointer, addr mainBuffer[bufferOffset], result.len)
 
 proc getAccessorData(root: JsonNode, accessor: JsonNode, mainBuffer: var seq[uint8]): DataList =
   result = newDataList(thetype=accessor.getGPUType())
@@ -154,7 +194,6 @@
   # prepare mesh attributes
   for attribute, accessor in meshNode["primitives"][0]["attributes"].pairs:
     result.setMeshData(attribute.toLowerAscii, newDataList(thetype=root["accessors"][accessor.getInt()].getGPUType()))
-  # if meshNode["primitives"][0].hasKey("material"):
   result.setMeshData("material", newDataList(thetype=getDataType[uint8]()))
 
   # add all mesh data
@@ -215,24 +254,73 @@
 
   newScene(scenenode["name"].getStr(), rootEntity)
 
-proc getMaterialsData(root: JsonNode): seq[Vec4f] =
-  for materialNode in root["materials"]:
-    let pbr = materialNode["pbrMetallicRoughness"]
-    var baseColor = newVec4f(1, 1, 1, 1)
-    if pbr.hasKey("baseColorFactor"):
-      baseColor[0] = pbr["baseColorFactor"][0].getFloat()
-      baseColor[1] = pbr["baseColorFactor"][1].getFloat()
-      baseColor[2] = pbr["baseColorFactor"][2].getFloat()
-      baseColor[3] = pbr["baseColorFactor"][3].getFloat()
-    result.add baseColor
-    # TODO: pbr["baseColorTexture"]
-    # TODO: pbr["metallicRoughnessTexture"]
-    # TODO: pbr["metallicFactor"]
-    # TODO: pbr["roughnessFactor"]
-    # TODO: materialNode["normalTexture"]
-    # TODO: materialNode["occlusionTexture"]
-    # TODO: materialNode["emissiveTexture"]
-    # TODO: materialNode["emissiveFactor"]
+proc loadImage(root: JsonNode, imageIndex: int, mainBuffer: var seq[uint8]): Image =
+  if root["images"][imageIndex].hasKey("uri"):
+    raise newException(Exception, "Unsupported feature: Load images from external files")
+
+  let bufferView = root["bufferViews"][root["images"][imageIndex]["bufferView"].getInt()]
+  let imgData = newStringStream(cast[string](getBufferViewData(bufferView, mainBuffer)))
+
+  let imageType = root["images"][imageIndex]["mimeType"].getStr()
+  case imageType
+  of "image/bmp":
+    result = readBMP(imgData)
+  of "image/png":
+    result = readPNG(imgData)
+  else:
+    raise newException(Exception, "Unsupported feature: Load image of type " & imageType)
+
+proc loadTexture(root: JsonNode, textureIndex: int, mainBuffer: var seq[uint8]): Texture =
+  result = new Texture
+  let textureNode = root["textures"][textureIndex]
+  result.image = loadImage(root, textureNode["source"].getInt(), mainBuffer)
+  result.sampler = DefaultSampler()
+
+  if textureNode.hasKey("sampler"):
+    let sampler = root["samplers"][textureNode["sampler"].getInt()]
+    if sampler.hasKey("magFilter"):
+      result.sampler.magnification = SAMPLER_FILTER_MODE_MAP[sampler["magFilter"].getInt()]
+    if sampler.hasKey("minFilter"):
+      result.sampler.minification = SAMPLER_FILTER_MODE_MAP[sampler["minFilter"].getInt()]
+    if sampler.hasKey("wrapS"):
+      result.sampler.wrapModeS = SAMPLER_WRAP_MODE_MAP[sampler["wrapS"].getInt()]
+    if sampler.hasKey("wrapT"):
+      result.sampler.wrapModeT = SAMPLER_WRAP_MODE_MAP[sampler["wrapS"].getInt()]
+
+proc loadMaterial(root: JsonNode, materialNode: JsonNode, mainBuffer: var seq[uint8]): glTFMaterial =
+  let defaultMaterial = glTFMaterial(color: newVec4f(1, 1, 1, 1))
+  result = defaultMaterial
+  let pbr = materialNode["pbrMetallicRoughness"]
+  if pbr.hasKey("baseColorFactor"):
+    result.color[0] = pbr["baseColorFactor"][0].getFloat()
+    result.color[1] = pbr["baseColorFactor"][1].getFloat()
+    result.color[2] = pbr["baseColorFactor"][2].getFloat()
+    result.color[3] = pbr["baseColorFactor"][3].getFloat()
+  if pbr.hasKey("baseColorTexture"):
+    result.colorTexture = loadTexture(root, pbr["baseColorTexture"]["index"].getInt(), mainBuffer)
+    result.colorTextureIndex = pbr["baseColorTexture"].getOrDefault("texCoord").getInt(0).uint32
+  if pbr.hasKey("metallicRoughnessTexture"):
+    result.metallicRoughnessTexture = loadTexture(root, pbr["metallicRoughnessTexture"]["index"].getInt(), mainBuffer)
+    result.metallicRoughnessTextureIndex = pbr["metallicRoughnessTexture"].getOrDefault("texCoord").getInt().uint32
+  if pbr.hasKey("metallicFactor"):
+    result.metallic = pbr["metallicFactor"].getFloat()
+  if pbr.hasKey("roughnessFactor"):
+    result.roughness= pbr["roughnessFactor"].getFloat()
+
+  if materialNode.hasKey("normalTexture"):
+    result.normalTexture = loadTexture(root, materialNode["normalTexture"]["index"].getInt(), mainBuffer)
+    result.metallicRoughnessTextureIndex = materialNode["normalTexture"].getOrDefault("texCoord").getInt().uint32
+  if materialNode.hasKey("occlusionTexture"):
+    result.occlusionTexture = loadTexture(root, materialNode["occlusionTexture"]["index"].getInt(), mainBuffer)
+    result.occlusionTextureIndex = materialNode["occlusionTexture"].getOrDefault("texCoord").getInt().uint32
+  if materialNode.hasKey("emissiveTexture"):
+    result.emissiveTexture = loadTexture(root, materialNode["emissiveTexture"]["index"].getInt(), mainBuffer)
+    result.occlusionTextureIndex = materialNode["emissiveTexture"].getOrDefault("texCoord").getInt().uint32
+  if materialNode.hasKey("roughnessFactor"):
+    result.roughness = materialNode["roughnessFactor"].getFloat()
+  if materialNode.hasKey("emissiveFactor"):
+    let em = materialNode["emissiveFactor"]
+    result.emissiveFactor = newVec3f(em[0].getFloat(), em[1].getFloat(), em[2].getFloat())
 
 proc readglTF*(stream: Stream): seq[Scene] =
   var
@@ -265,6 +353,62 @@
 
   for scene in data.structuredContent["scenes"]:
     var scene = data.structuredContent.loadScene(scene, data.binaryBufferData)
-    scene.addShaderGlobalArray("material_colors", getMaterialsData(data.structuredContent))
+    var
+      color: seq[Vec4f]
+      colorTexture: seq[Texture]
+      colorTextureIndex: seq[uint32]
+      metallic: seq[float32]
+      roughness: seq[float32]
+      metallicRoughnessTexture: seq[Texture]
+      metallicRoughnessTextureIndex: seq[uint32]
+      normalTexture: seq[Texture]
+      normalTextureIndex: seq[uint32]
+      occlusionTexture: seq[Texture]
+      occlusionTextureIndex: seq[uint32]
+      emissiveTexture: seq[Texture]
+      emissiveTextureIndex: seq[uint32]
+      emissiveFactor: seq[Vec3f]
+    for materialNode in data.structuredContent["materials"]:
+      let m = loadMaterial(data.structuredContent, materialNode, data.binaryBufferData)
+      color.add m.color
+      if not m.colorTexture.isNil:
+        colorTexture.add m.colorTexture
+        colorTextureIndex.add m.colorTextureIndex
+      metallic.add m.metallic
+      roughness.add m.roughness
+      if not m.metallicRoughnessTexture.isNil:
+        metallicRoughnessTexture.add m.metallicRoughnessTexture
+        metallicRoughnessTextureIndex.add m.metallicRoughnessTextureIndex
+      if not m.normalTexture.isNil:
+        normalTexture.add m.normalTexture
+        normalTextureIndex.add m.normalTextureIndex
+      if not m.occlusionTexture.isNil:
+        occlusionTexture.add m.occlusionTexture
+        occlusionTextureIndex.add m.occlusionTextureIndex
+      if not m.emissiveTexture.isNil:
+        emissiveTexture.add m.emissiveTexture
+        emissiveTextureIndex.add m.emissiveTextureIndex
+      emissiveFactor.add m.emissiveFactor
+
+    # material constants
+    if color.len > 0: scene.addShaderGlobalArray("material_color", color)
+    if colorTextureIndex.len > 0: scene.addShaderGlobalArray("material_color_texture_index", colorTextureIndex)
+    if metallic.len > 0: scene.addShaderGlobalArray("material_metallic", metallic)
+    if roughness.len > 0: scene.addShaderGlobalArray("material_roughness", roughness)
+    if metallicRoughnessTextureIndex.len > 0: scene.addShaderGlobalArray("material_metallic_roughness_texture_index", metallicRoughnessTextureIndex)
+    if normalTextureIndex.len > 0: scene.addShaderGlobalArray("material_normal_texture_index", normalTextureIndex)
+    if occlusionTextureIndex.len > 0: scene.addShaderGlobalArray("material_occlusion_texture_index", occlusionTextureIndex)
+    if emissiveTextureIndex.len > 0: scene.addShaderGlobalArray("material_emissive_texture_index", emissiveTextureIndex)
+    if emissiveFactor.len > 0: scene.addShaderGlobalArray("material_emissive_factor", emissiveFactor)
+
+    # texture
+    #[
+    if colorTexture.len > 0: scene.addShaderGlobalArray("material_color_texture", colorTexture)
+    if metallicRoughnessTexture.len > 0: scene.addShaderGlobalArray("material_metallic_roughness_texture", metallicRoughnessTexture)
+    if normalTexture.len > 0: scene.addShaderGlobalArray("material_normal_texture", normalTexture)
+    if occlusionTexture.len > 0: scene.addShaderGlobalArray("material_occlusion_texture", occlusionTexture)
+    if emissiveTexture.len > 0: scene.addShaderGlobalArray("material_emissive_texture", emissiveTexture)
+    ]#
+
     result.add scene
 
--- a/src/semicongine/vulkan/descriptor.nim	Sun May 21 01:04:55 2023 +0700
+++ b/src/semicongine/vulkan/descriptor.nim	Mon May 22 00:50:41 2023 +0700
@@ -20,7 +20,7 @@
       size*: uint64
     of ImageSampler:
       imageviews*: seq[ImageView]
-      samplers*: seq[Sampler]
+      samplers*: seq[VulkanSampler]
   DescriptorSet* = object # "instance" of a DescriptorSetLayout
     vk*: VkDescriptorSet
     layout*: DescriptorSetLayout
--- a/src/semicongine/vulkan/image.nim	Sun May 21 01:04:55 2023 +0700
+++ b/src/semicongine/vulkan/image.nim	Mon May 22 00:50:41 2023 +0700
@@ -10,7 +10,7 @@
 
 type
   PixelDepth = 1'u32 .. 4'u32
-  GPUImage* = object
+  VulkanImage* = object
     device*: Device
     vk*: VkImage
     width*: uint32 # pixel
@@ -22,16 +22,16 @@
       of false: discard
       of true:
         memory*: DeviceMemory
-  Sampler* = object
+  VulkanSampler* = object
     device*: Device
     vk*: VkSampler
   ImageView* = object
     vk*: VkImageView
-    image*: GPUImage
-  Texture* = object
-    image*: GPUImage
+    image*: VulkanImage
+  VulkanTexture* = object
+    image*: VulkanImage
     imageView*: ImageView
-    sampler*: Sampler
+    sampler*: VulkanSampler
 
 const DEPTH_FORMAT_MAP = {
   PixelDepth(1): VK_FORMAT_R8_SRGB,
@@ -41,7 +41,7 @@
 }.toTable
 
 
-proc requirements(image: GPUImage): MemoryRequirements =
+proc requirements(image: VulkanImage): MemoryRequirements =
   assert image.vk.valid
   assert image.device.vk.valid
   var req: VkMemoryRequirements
@@ -53,7 +53,7 @@
     if ((req.memoryTypeBits shr i) and 1) == 1:
       result.memoryTypes.add memorytypes[i]
 
-proc allocateMemory(image: var GPUImage, requireMappable: bool, preferVRAM: bool, preferAutoFlush: bool) =
+proc allocateMemory(image: var VulkanImage, requireMappable: bool, preferVRAM: bool, preferAutoFlush: bool) =
   assert image.device.vk.valid
   assert image.memoryAllocated == false
 
@@ -68,7 +68,7 @@
   image.memory = image.device.allocate(requirements.size, memoryType)
   checkVkResult image.device.vk.vkBindImageMemory(image.vk, image.memory.vk, VkDeviceSize(0))
 
-proc transitionImageLayout*(image: GPUImage, oldLayout, newLayout: VkImageLayout) =
+proc transitionImageLayout*(image: VulkanImage, oldLayout, newLayout: VkImageLayout) =
   var barrier = VkImageMemoryBarrier(
     sType: VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
     oldLayout: oldLayout,
@@ -109,7 +109,7 @@
       1, addr barrier
     )
 
-proc copy*(src: Buffer, dst: GPUImage) =
+proc copy*(src: Buffer, dst: VulkanImage) =
   assert src.device.vk.valid
   assert dst.device.vk.valid
   assert src.device == dst.device
@@ -139,7 +139,7 @@
     )
 
 # currently only usable for texture access from shader
-proc createImage*(device: Device, width, height: uint32, depth: PixelDepth, data: pointer): GPUImage =
+proc createImage*(device: Device, width, height: uint32, depth: PixelDepth, data: pointer): VulkanImage =
   assert device.vk.valid
   assert width > 0
   assert height > 0
@@ -177,7 +177,7 @@
   result.transitionImageLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
   stagingBuffer.destroy()
 
-proc destroy*(image: var GPUImage) =
+proc destroy*(image: var VulkanImage) =
   assert image.device.vk.valid
   assert image.vk.valid
   image.device.vk.vkDestroyImage(image.vk, nil)
@@ -187,14 +187,14 @@
     image.memoryAllocated = false
   image.vk.reset
 
-proc createSampler*(device: Device, interpolation: VkFilter): Sampler =
+proc createSampler*(device: Device, sampler: Sampler): VulkanSampler =
   assert device.vk.valid
   var samplerInfo = VkSamplerCreateInfo(
     sType: VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
-    magFilter: interpolation,
-    minFilter: interpolation,
-    addressModeU: VK_SAMPLER_ADDRESS_MODE_REPEAT,
-    addressModeV: VK_SAMPLER_ADDRESS_MODE_REPEAT,
+    magFilter: sampler.magnification,
+    minFilter: sampler.minification,
+    addressModeU: sampler.wrapModeS,
+    addressModeV: sampler.wrapModeT,
     addressModeW: VK_SAMPLER_ADDRESS_MODE_REPEAT,
     anisotropyEnable: device.enabledFeatures.samplerAnisotropy,
     maxAnisotropy: device.physicalDevice.properties.limits.maxSamplerAnisotropy,
@@ -210,14 +210,14 @@
   result.device = device
   checkVkResult device.vk.vkCreateSampler(addr samplerInfo, nil, addr result.vk)
 
-proc destroy*(sampler: var Sampler) =
+proc destroy*(sampler: var VulkanSampler) =
   assert sampler.device.vk.valid
   assert sampler.vk.valid
   sampler.device.vk.vkDestroySampler(sampler.vk, nil)
   sampler.vk.reset
 
 proc createImageView*(
-  image: GPUImage,
+  image: VulkanImage,
   imageviewtype=VK_IMAGE_VIEW_TYPE_2D,
   baseMipLevel=0'u32,
   levelCount=1'u32,
@@ -255,14 +255,13 @@
   imageview.image.device.vk.vkDestroyImageView(imageview.vk, nil)
   imageview.vk.reset()
 
-proc createTexture*(device: Device, width, height: uint32, depth: PixelDepth, data: pointer, interpolation: VkFilter): Texture =
+proc uploadTexture*(device: Device, texture: Texture): VulkanTexture =
   assert device.vk.valid
-  
-  result.image = createImage(device=device, width=width, height=height, depth=depth, data=data)
+  result.image = createImage(device=device, width=texture.image.width, height=texture.image.height, depth=4, data=addr texture.image.imagedata[0][0])
   result.imageView = result.image.createImageView()
-  result.sampler = result.image.device.createSampler(interpolation)
+  result.sampler = result.image.device.createSampler(texture.sampler)
 
-proc destroy*(texture: var Texture) =
+proc destroy*(texture: var VulkanTexture) =
   texture.image.destroy()
   texture.imageView.destroy()
   texture.sampler.destroy()
--- a/src/semicongine/vulkan/pipeline.nim	Sun May 21 01:04:55 2023 +0700
+++ b/src/semicongine/vulkan/pipeline.nim	Mon May 22 00:50:41 2023 +0700
@@ -32,7 +32,7 @@
         result.add attribute
         visitedUniforms[attribute.name] = attribute
 
-proc setupDescriptors*(pipeline: var Pipeline, buffers: seq[Buffer], textures: Table[string, seq[Texture]], inFlightFrames: int): seq[DescriptorSet] =
+proc setupDescriptors*(pipeline: var Pipeline, buffers: seq[Buffer], textures: Table[string, seq[VulkanTexture]], inFlightFrames: int): seq[DescriptorSet] =
   assert pipeline.vk.valid
   assert buffers.len == 0 or buffers.len == inFlightFrames # need to guard against this in case we have no uniforms, then we also create no buffers
 
--- a/src/semicongine/vulkan/swapchain.nim	Sun May 21 01:04:55 2023 +0700
+++ b/src/semicongine/vulkan/swapchain.nim	Mon May 22 00:50:41 2023 +0700
@@ -112,7 +112,7 @@
     var images = newSeq[VkImage](nImages)
     checkVkResult device.vk.vkGetSwapchainImagesKHR(swapChain.vk, addr(nImages), images.toCPointer)
     for vkimage in images:
-      let image = GPUImage(vk: vkimage, format: surfaceFormat.format, device: device)
+      let image = VulkanImage(vk: vkimage, format: surfaceFormat.format, device: device)
       let imageview = image.createImageView()
       swapChain.imageviews.add imageview
       swapChain.framebuffers.add swapchain.device.createFramebuffer(renderPass, [imageview], swapchain.dimension)