# HG changeset patch # User Sam # Date 1683636753 -25200 # Node ID d7c61e6580ea58ceec4da3aa08072223cbbc7b47 # Parent d84b2e88776a7c49f93fd9845ccd0bb609afdca3 did: refactor image handling diff -r d84b2e88776a -r d7c61e6580ea src/semicongine/core.nim --- a/src/semicongine/core.nim Tue May 09 18:19:17 2023 +0700 +++ b/src/semicongine/core.nim Tue May 09 19:52:33 2023 +0700 @@ -6,6 +6,7 @@ import ./core/buildconfig import ./core/color import ./core/gpu_data +import ./core/imagetypes import ./core/matrix import ./core/vector import ./core/utils @@ -15,6 +16,7 @@ export buildconfig export color export gpu_data +export imagetypes export matrix export vector export utils diff -r d84b2e88776a -r d7c61e6580ea src/semicongine/core/imagetypes.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/semicongine/core/imagetypes.nim Tue May 09 19:52:33 2023 +0700 @@ -0,0 +1,16 @@ +type + Pixel* = array[4, uint8] + ImageObject* = object + width*: uint32 + height*: uint32 + imagedata*: seq[Pixel] + Image* = ref ImageObject + +proc newImage*(width, height: uint32, imagedata: seq[Pixel] = @[]): Image = + assert width > 0 and height > 0 + result.imagedata = (if imagedata.len == 0: newSeq[Pixel](width * height) else: imagedata) + assert width * height == uint32(result.imagedata.len) + + result = new Image + result.width = width + result.height = height diff -r d84b2e88776a -r d7c61e6580ea src/semicongine/engine.nim --- a/src/semicongine/engine.nim Tue May 09 18:19:17 2023 +0700 +++ b/src/semicongine/engine.nim Tue May 09 19:52:33 2023 +0700 @@ -82,8 +82,8 @@ enabledLayers.add "VK_LAYER_KHRONOS_validation" putEnv("VK_LAYER_ENABLES", "VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT") - if defined(linux): - enabledLayers.add "VK_LAYER_MESA_overlay" + if defined(linux): + enabledLayers.add "VK_LAYER_MESA_overlay" result.instance = result.window.createInstance( vulkanVersion=VK_MAKE_API_VERSION(0, 1, 3, 0), instanceExtensions=instanceExtensions, diff -r d84b2e88776a -r d7c61e6580ea src/semicongine/entity.nim --- a/src/semicongine/entity.nim Tue May 09 18:19:17 2023 +0700 +++ b/src/semicongine/entity.nim Tue May 09 19:52:33 2023 +0700 @@ -13,7 +13,7 @@ name*: string root*: Entity shaderGlobals*: Table[string, DataValue] - textures*: Table[string, seq[TextureImage]] + textures*: Table[string, (seq[Image], VkFilter)] Entity* = ref object of RootObj name*: string @@ -22,13 +22,6 @@ children*: seq[Entity] components*: seq[Component] - Pixel* = array[4, uint8] - TextureImage* = ref object of RootObj - width*: uint32 - height*: uint32 - imagedata*: seq[Pixel] - interpolation*: VkFilter - func addShaderGlobal*[T](scene: var Scene, name: string, data: T) = var value = DataValue(thetype: getDataType[T]()) value.setValue(data) @@ -40,11 +33,11 @@ func setShaderGlobal*[T](scene: var Scene, name: string, value: T) = setValue[T](scene.shaderGlobals[name], value) -func addTextures*(scene: var Scene, name: string, texture: seq[TextureImage]) = - scene.textures[name] = texture +func addTextures*(scene: var Scene, name: string, texture: seq[Image], interpolation=VK_FILTER_LINEAR) = + scene.textures[name] = (texture, interpolation) -func addTexture*(scene: var Scene, name: string, texture: TextureImage) = - scene.textures[name] = @[texture] +func addTexture*(scene: var Scene, name: string, texture: Image, interpolation=VK_FILTER_LINEAR) = + scene.textures[name] = (@[texture], interpolation) func newScene*(name: string, root: Entity): Scene = Scene(name: name, root: root) diff -r d84b2e88776a -r d7c61e6580ea src/semicongine/renderer.nim --- a/src/semicongine/renderer.nim Tue May 09 18:19:17 2023 +0700 +++ b/src/semicongine/renderer.nim Tue May 09 19:52:33 2023 +0700 @@ -24,7 +24,6 @@ vertexBuffers*: Table[MemoryPerformanceHint, Buffer] indexBuffer*: Buffer uniformBuffers*: seq[Buffer] # one per frame-in-flight - images*: seq[Image] # used to back texturees textures*: Table[string, seq[Texture]] # per frame-in-flight attributeLocation*: Table[string, MemoryPerformanceHint] attributeBindingNumber*: Table[string, int] @@ -172,8 +171,9 @@ for name, images in scene.textures.pairs: data.textures[name] = @[] - for image in images: - data.textures[name].add renderer.device.createTexture(image.width, image.height, 4, addr image.imagedata[0][0], image.interpolation) + 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) pipeline.setupDescriptors(data.uniformBuffers, data.textures, inFlightFrames=renderer.swapchain.inFlightFrames) for frame_i in 0 ..< renderer.swapchain.inFlightFrames: pipeline.descriptorSets[frame_i].writeDescriptorSet() diff -r d84b2e88776a -r d7c61e6580ea src/semicongine/vulkan/image.nim --- a/src/semicongine/vulkan/image.nim Tue May 09 18:19:17 2023 +0700 +++ b/src/semicongine/vulkan/image.nim Tue May 09 19:52:33 2023 +0700 @@ -10,7 +10,7 @@ type PixelDepth = 1'u32 .. 4'u32 - Image* = object + GPUImage* = object device*: Device vk*: VkImage width*: uint32 # pixel @@ -27,9 +27,9 @@ vk*: VkSampler ImageView* = object vk*: VkImageView - image*: Image + image*: GPUImage Texture* = object - image*: Image + image*: GPUImage imageView*: ImageView sampler*: Sampler @@ -41,7 +41,7 @@ }.toTable -proc requirements(image: Image): MemoryRequirements = +proc requirements(image: GPUImage): 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 Image, requireMappable: bool, preferVRAM: bool, preferAutoFlush: bool) = +proc allocateMemory(image: var GPUImage, 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: Image, oldLayout, newLayout: VkImageLayout) = +proc transitionImageLayout*(image: GPUImage, 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: Image) = +proc copy*(src: Buffer, dst: GPUImage) = 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): Image = +proc createImage*(device: Device, width, height: uint32, depth: PixelDepth, data: pointer): GPUImage = 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 Image) = +proc destroy*(image: var GPUImage) = assert image.device.vk.valid assert image.vk.valid image.device.vk.vkDestroyImage(image.vk, nil) @@ -217,7 +217,7 @@ sampler.vk.reset proc createImageView*( - image: Image, + image: GPUImage, imageviewtype=VK_IMAGE_VIEW_TYPE_2D, baseMipLevel=0'u32, levelCount=1'u32, diff -r d84b2e88776a -r d7c61e6580ea src/semicongine/vulkan/renderpass.nim --- a/src/semicongine/vulkan/renderpass.nim Tue May 09 18:19:17 2023 +0700 +++ b/src/semicongine/vulkan/renderpass.nim Tue May 09 19:52:33 2023 +0700 @@ -1,5 +1,4 @@ import std/options -import std/logging import ../core import ./device diff -r d84b2e88776a -r d7c61e6580ea src/semicongine/vulkan/swapchain.nim --- a/src/semicongine/vulkan/swapchain.nim Tue May 09 18:19:17 2023 +0700 +++ b/src/semicongine/vulkan/swapchain.nim Tue May 09 19:52:33 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 = Image(vk: vkimage, format: surfaceFormat.format, device: device) + let image = GPUImage(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) diff -r d84b2e88776a -r d7c61e6580ea tests/test_materials.nim --- a/tests/test_materials.nim Tue May 09 18:19:17 2023 +0700 +++ b/tests/test_materials.nim Tue May 09 19:52:33 2023 +0700 @@ -7,21 +7,21 @@ let (R, W) = ([255'u8, 0'u8, 0'u8, 255'u8], [255'u8, 255'u8, 255'u8, 255'u8]) let (RT, WT, PT) = (hexToColorAlpha("A51931").asPixel, hexToColorAlpha("F4F5F8").asPixel, hexToColorAlpha("2D2A4A").asPixel) let - t1 = TextureImage(width: 5, height: 5, imagedata: @[ + t1 = Image(width: 5, height: 5, imagedata: @[ R, R, R, R, R, R, R, W, R, R, R, W, W, W, R, R, R, W, R, R, R, R, R, R, R, ]) - t2 = TextureImage(width: 7, height: 5, imagedata: @[ + t2 = Image(width: 7, height: 5, imagedata: @[ RT, RT, RT, RT, RT, RT, RT, WT, WT, WT, WT, WT, WT, WT, PT, PT, PT, PT, PT, PT, PT, WT, WT, WT, WT, WT, WT, WT, RT, RT, RT, RT, RT, RT, RT, ]) - scene.addTextures("my_texture", @[t1, t2]) + scene.addTextures("my_texture", @[t1, t2], interpolation=VK_FILTER_NEAREST) scene.addShaderGlobal("time", 0'f32) var m: Mesh = Mesh(scene.root.components[0]) diff -r d84b2e88776a -r d7c61e6580ea tests/test_vulkan_wrapper.nim --- a/tests/test_vulkan_wrapper.nim Tue May 09 18:19:17 2023 +0700 +++ b/tests/test_vulkan_wrapper.nim Tue May 09 19:52:33 2023 +0700 @@ -37,31 +37,31 @@ result = newEntity("root", newEntity("triangle1", newMesh( positions=[newVec3f(0.0, -0.5), newVec3f(0.5, 0.5), newVec3f(-0.5, 0.5)], - colors=[newVec3f(1.0, 0.0, 0.0), newVec3f(0.0, 1.0, 0.0), newVec3f(0.0, 0.0, 1.0)], + colors=[newVec4f(1.0, 0.0, 0.0, 1), newVec4f(0.0, 1.0, 0.0, 1), newVec4f(0.0, 0.0, 1.0, 1)], )), newEntity("triangle1b", newMesh( positions=[newVec3f(0.0, -0.4), newVec3f(0.4, 0.4), newVec3f(-0.4, 0.5)], - colors=[newVec3f(1.0, 0.0, 0.0), newVec3f(0.0, 1.0, 0.0), newVec3f(0.0, 0.0, 1.0)], + colors=[newVec4f(1.0, 0.0, 0.0, 1), newVec4f(0.0, 1.0, 0.0, 1), newVec4f(0.0, 0.0, 1.0, 1)], )), newEntity("triangle2a", newMesh( positions=[newVec3f(0.0, 0.5), newVec3f(0.5, -0.5), newVec3f(-0.5, -0.5)], - colors=[newVec3f(1.0, 0.0, 0.0), newVec3f(0.0, 1.0, 0.0), newVec3f(0.0, 0.0, 1.0)], + colors=[newVec4f(1.0, 0.0, 0.0, 1), newVec4f(0.0, 1.0, 0.0, 1), newVec4f(0.0, 0.0, 1.0, 1)], indices=[[0'u16, 2'u16, 1'u16]] )), newEntity("triangle2b", newMesh( positions=[newVec3f(0.0, 0.4), newVec3f(0.4, -0.4), newVec3f(-0.4, -0.4)], - colors=[newVec3f(1.0, 0.0, 0.0), newVec3f(0.0, 1.0, 0.0), newVec3f(0.0, 0.0, 1.0)], + colors=[newVec4f(1.0, 0.0, 0.0, 1), newVec4f(0.0, 1.0, 0.0, 1), newVec4f(0.0, 0.0, 1.0, 1)], indices=[[0'u16, 2'u16, 1'u16]] )), newEntity("triangle3a", newMesh( positions=[newVec3f(0.4, 0.5), newVec3f(0.9, -0.3), newVec3f(0.0, -0.3)], - colors=[newVec3f(1.0, 1.0, 0.0), newVec3f(1.0, 1.0, 0.0), newVec3f(1.0, 1.0, 0.0)], + colors=[newVec4f(1.0, 1.0, 0.0, 1), newVec4f(1.0, 1.0, 0.0, 1), newVec4f(1.0, 1.0, 0.0, 1)], indices=[[0'u32, 2'u32, 1'u32]], autoResize=false )), newEntity("triangle3b", newMesh( positions=[newVec3f(0.4, 0.5), newVec3f(0.9, -0.3), newVec3f(0.0, -0.3)], - colors=[newVec3f(1.0, 1.0, 0.0), newVec3f(1.0, 1.0, 0.0), newVec3f(1.0, 1.0, 0.0)], + colors=[newVec4f(1.0, 1.0, 0.0, 1), newVec4f(1.0, 1.0, 0.0, 1), newVec4f(1.0, 1.0, 0.0, 1)], indices=[[0'u32, 2'u32, 1'u32]], autoResize=false )), @@ -72,21 +72,21 @@ proc scene_simple(): Entity = var mymesh1 = newMesh( positions=[newVec3f(0.0, -0.3), newVec3f(0.3, 0.3), newVec3f(-0.3, 0.3)], - colors=[newVec3f(1.0, 0.0, 0.0), newVec3f(0.0, 1.0, 0.0), newVec3f(0.0, 0.0, 1.0)], + colors=[newVec4f(1.0, 0.0, 0.0, 1), newVec4f(0.0, 1.0, 0.0, 1), newVec4f(0.0, 0.0, 1.0, 1)], ) var mymesh2 = newMesh( positions=[newVec3f(0.0, -0.5), newVec3f(0.5, 0.5), newVec3f(-0.5, 0.5)], - colors=[newVec3f(1.0, 0.0, 0.0), newVec3f(0.0, 1.0, 0.0), newVec3f(0.0, 0.0, 1.0)], + colors=[newVec4f(1.0, 0.0, 0.0, 1), newVec4f(0.0, 1.0, 0.0, 1), newVec4f(0.0, 0.0, 1.0, 1)], ) var mymesh3 = newMesh( positions=[newVec3f(0.0, -0.6), newVec3f(0.6, 0.6), newVec3f(-0.6, 0.6)], - colors=[newVec3f(1.0, 1.0, 0.0), newVec3f(1.0, 1.0, 0.0), newVec3f(1.0, 1.0, 0.0)], + colors=[newVec4f(1.0, 1.0, 0.0, 1), newVec4f(1.0, 1.0, 0.0, 1), newVec4f(1.0, 1.0, 0.0, 1)], indices=[[0'u32, 1'u32, 2'u32]], autoResize=false ) var mymesh4 = newMesh( positions=[newVec3f(0.0, -0.8), newVec3f(0.8, 0.8), newVec3f(-0.8, 0.8)], - colors=[newVec3f(0.0, 0.0, 1.0), newVec3f(0.0, 0.0, 1.0), newVec3f(0.0, 0.0, 1.0)], + colors=[newVec4f(0.0, 0.0, 1.0, 1), newVec4f(0.0, 0.0, 1.0, 1), newVec4f(0.0, 0.0, 1.0, 1)], indices=[[0'u16, 1'u16, 2'u16]], instanceCount=2 ) @@ -107,7 +107,7 @@ proc scene_flag(): Entity = var r = rect(color="ff0000") - r.updateMeshData("color", @[newVec3f(0, 0), newVec3f(1, 0), newVec3f(1, 1), newVec3f(0, 1)]) + r.updateMeshData("color", @[newVec4f(0, 0), newVec4f(1, 0), newVec4f(1, 1), newVec4f(0, 1)]) result = newEntity("root", r) proc main() = @@ -117,10 +117,10 @@ const vertexInput = @[ attr[Vec3f]("position", memoryPerformanceHint=PreferFastRead), - attr[Vec3f]("color", memoryPerformanceHint=PreferFastWrite), + attr[Vec4f]("color", memoryPerformanceHint=PreferFastWrite), attr[Vec3f]("translate", perInstance=true) ] - vertexOutput = @[attr[Vec3f]("outcolor")] + vertexOutput = @[attr[Vec4f]("outcolor")] uniforms = @[attr[float32]("time")] samplers = @[attr[Sampler2DType]("my_little_texture")] fragOutput = @[attr[Vec4f]("color")] @@ -138,7 +138,7 @@ uniforms=uniforms, samplers=samplers, outputs=fragOutput, - main="color = texture(my_little_texture, outcolor.xy) * 0.5 + vec4(outcolor, 1) * 0.5;" + main="color = texture(my_little_texture, outcolor.xy) * 0.5 + outcolor * 0.5;" ) var renderPass = engine.gpuDevice.simpleForwardRenderPass(vertexCode, fragmentCode) engine.setRenderer(renderPass) @@ -153,13 +153,13 @@ for scene in scenes.mitems: scene.addShaderGlobal("time", 0.0'f32) let (R, W) = ([255'u8, 0'u8, 0'u8, 255'u8], [255'u8, 255'u8, 255'u8, 255'u8]) - scene.addTexture("my_little_texture", TextureImage(width: 5, height: 5, imagedata: @[ + scene.addTexture("my_little_texture", Image(width: 5, height: 5, imagedata: @[ R, R, R, R, R, R, R, W, R, R, R, W, W, W, R, R, R, W, R, R, R, R, R, R, R, - ])) + ]), VK_FILTER_NEAREST) engine.addScene(scene, vertexInput) # MAINLOOP