# HG changeset patch # User Sam # Date 1681132177 -25200 # Node ID cb9e27a3016549e19912e6e4422b184599a75f9e # Parent 55be3579dc3078e6c59e97470d7287f847a7c56a fix: completely overhole buffer handling for drawing, fix shit diff -r 55be3579dc30 -r cb9e27a30165 src/semicongine/gpu_data.nim --- a/src/semicongine/gpu_data.nim Mon Apr 10 00:53:16 2023 +0700 +++ b/src/semicongine/gpu_data.nim Mon Apr 10 20:09:37 2023 +0700 @@ -777,14 +777,21 @@ of Mat4F32: "mat4" of Mat4F64: "dmat4" +func groupByMemoryLocation*(attributes: openArray[ShaderAttribute]): Table[MemoryLocation, seq[ShaderAttribute]] = + for attr in attributes: + if not (attr.memoryLocation in result): + result[attr.memoryLocation] = @[] + result[attr.memoryLocation].add attr + func glslInput*(group: seq[ShaderAttribute]): seq[string] = if group.len == 0: return @[] var i = 0'u32 - for attribute in group: - result.add &"layout(location = {i}) in {attribute.thetype.glslType} {attribute.name};" - for j in 0 ..< attribute.thetype.numberOfVertexInputAttributeDescriptors: - i += attribute.thetype.nLocationSlots + for attributes in group.groupByMemoryLocation().values: + for attribute in attributes: + result.add &"layout(location = {i}) in {attribute.thetype.glslType} {attribute.name};" + for j in 0 ..< attribute.thetype.numberOfVertexInputAttributeDescriptors: + i += attribute.thetype.nLocationSlots func glslUniforms*(group: seq[ShaderAttribute], blockName="Uniforms", binding=0): seq[string] = if group.len == 0: @@ -802,9 +809,3 @@ for attribute in group: result.add &"layout(location = {i}) out {attribute.thetype.glslType} {attribute.name};" i += 1 - -func groupByMemoryLocation*(attributes: openArray[ShaderAttribute]): Table[MemoryLocation, seq[ShaderAttribute]] = - for attr in attributes: - if not (attr.memoryLocation in result): - result[attr.memoryLocation] = @[] - result[attr.memoryLocation].add attr diff -r 55be3579dc30 -r cb9e27a30165 src/semicongine/mesh.nim --- a/src/semicongine/mesh.nim Mon Apr 10 00:53:16 2023 +0700 +++ b/src/semicongine/mesh.nim Mon Apr 10 20:09:37 2023 +0700 @@ -19,8 +19,7 @@ vertexCount*: uint32 indicesCount*: uint32 instanceCount*: uint32 - vertexdata: Table[string, DataList] - instancedata: Table[string, DataList] + data: Table[string, DataList] case indexType*: MeshIndexType of None: discard of Tiny: tinyIndices: seq[array[3, uint8]] @@ -51,11 +50,11 @@ result.vertexCount = uint32(positions.len) result.indicesCount = uint32(indices.len * 3) result.instanceCount = instances - result.vertexdata["position"] = DataList(thetype: Vec3F32) - setValues(result.vertexdata["position"], positions.toSeq) + result.data["position"] = DataList(thetype: Vec3F32) + setValues(result.data["position"], positions.toSeq) if colors.len > 0: - result.vertexdata["color"] = DataList(thetype: Vec3F32) - setValues(result.vertexdata["color"], colors.toSeq) + result.data["color"] = DataList(thetype: Vec3F32) + setValues(result.data["color"], colors.toSeq) for i in indices: assert uint32(i[0]) < result.vertexCount @@ -85,9 +84,8 @@ ): auto = newMesh(positions, newSeq[array[3, int]](), colors, instances) -func vertexDataSize*(mesh: Mesh): uint32 = - for d in mesh.vertexdata.values: - result += d.size +func dataSize*(mesh: Mesh, attribute: string): uint32 = + mesh.data[attribute].size func indexDataSize*(mesh: Mesh): uint32 = case mesh.indexType @@ -96,10 +94,6 @@ of Small: mesh.smallIndices.len * sizeof(get(genericParams(typeof(mesh.smallIndices)), 0)) of Big: mesh.bigIndices.len * sizeof(get(genericParams(typeof(mesh.bigIndices)), 0)) -func instanceDataSize*(mesh: Mesh): uint32 = - for d in mesh.instancedata.values: - result += d.size - func rawData[T: seq](value: var T): (pointer, uint32) = (pointer(addr(value[0])), uint32(sizeof(get(genericParams(typeof(value)), 0)) * value.len)) @@ -110,20 +104,14 @@ of Small: rawData(mesh.smallIndices) of Big: rawData(mesh.bigIndices) -func hasVertexDataFor*(mesh: Mesh, attribute: string): bool = - attribute in mesh.vertexdata +func hasDataFor*(mesh: Mesh, attribute: string): bool = + attribute in mesh.data -func hasInstanceDataFor*(mesh: Mesh, attribute: string): bool = - attribute in mesh.instancedata - -func getRawVertexData*(mesh: Mesh, attribute: string): (pointer, uint32) = - mesh.vertexdata[attribute].getRawData() +func getRawData*(mesh: Mesh, attribute: string): (pointer, uint32) = + mesh.data[attribute].getRawData() -func getRawInstanceData*(mesh: Mesh, attribute: string): (pointer, uint32) = - mesh.instancedata[attribute].getRawData() - -proc setInstanceData*[T: GPUType|int|uint|float](mesh: var Mesh, attribute: string, data: seq[T]) = +proc setMeshData*[T: GPUType|int|uint|float](mesh: var Mesh, attribute: string, data: seq[T]) = assert uint32(data.len) == mesh.instanceCount - assert not (attribute in mesh.instancedata) - mesh.instancedata[attribute] = DataList(thetype: getDataType[T]()) - setValues(mesh.instancedata[attribute], data) + assert not (attribute in mesh.data) + mesh.data[attribute] = DataList(thetype: getDataType[T]()) + setValues(mesh.data[attribute], data) diff -r 55be3579dc30 -r cb9e27a30165 src/semicongine/scene.nim --- a/src/semicongine/scene.nim Mon Apr 10 00:53:16 2023 +0700 +++ b/src/semicongine/scene.nim Mon Apr 10 20:09:37 2023 +0700 @@ -11,15 +11,13 @@ type Drawable* = object - buffer*: Buffer # buffer - offsets*: seq[uint64] # offsets from buffer elementCount*: uint32 # number of vertices or indices + bufferOffsets*: Table[MemoryLocation, seq[uint64]] # list of buffers and list of offset for each attribute in that buffer instanceCount*: uint32 # number of instance case indexed*: bool of true: - indexBuffer*: Buffer indexType*: VkIndexType - indexOffset*: uint64 + indexBufferOffset*: uint64 of false: discard @@ -31,12 +29,14 @@ name*: string root*: Entity drawables: Table[VkPipeline, seq[Drawable]] + vertexBuffers*: Table[MemoryLocation, Buffer] + indexBuffer*: Buffer func `$`*(drawable: Drawable): string = if drawable.indexed: - &"Drawable(elementCount: {drawable.elementCount}, instanceCount: {drawable.instanceCount}, buffer: {drawable.buffer}, offsets: {drawable.offsets}, indexType: {drawable.indexType}, indexOffset: {drawable.indexOffset}, indexBuffer: {drawable.indexBuffer})" + &"Drawable(elementCount: {drawable.elementCount}, instanceCount: {drawable.instanceCount}, bufferOffsets: {drawable.bufferOffsets}, indexType: {drawable.indexType}, indexBufferOffset: {drawable.indexBufferOffset})" else: - &"Drawable(elementCount: {drawable.elementCount}, instanceCount: {drawable.instanceCount}, buffer: {drawable.buffer}, offsets: {drawable.offsets})" + &"Drawable(elementCount: {drawable.elementCount}, instanceCount: {drawable.instanceCount}, bufferOffsets: {drawable.bufferOffsets})" func `$`*(global: ShaderGlobal): string = &"ShaderGlobal(name: {global.name}, {global.value})" @@ -46,20 +46,11 @@ value.setValue(data) ShaderGlobal(name: name, value: value) -func getBuffers*(scene: Scene, pipeline: VkPipeline): seq[Buffer] = - var counted: seq[VkBuffer] - for drawable in scene.drawables[pipeline]: - if not (drawable.buffer.vk in counted): - result.add drawable.buffer - counted.add drawable.buffer.vk - if drawable.indexed and not (drawable.indexBuffer.vk in counted): - result.add drawable.indexBuffer - counted.add drawable.indexBuffer.vk - proc destroy*(scene: var Scene, pipeline: VkPipeline) = - var buffers = scene.getBuffers(pipeline) - for buffer in buffers.mitems: - buffer.destroy() + for buffer in scene.vertexBuffers.mvalues: + buffer.destroy() + if scene.indexBuffer.vk.valid: + scene.indexBuffer.destroy proc destroy*(scene: var Scene) = for pipeline in scene.drawables.keys: @@ -67,101 +58,89 @@ proc setupDrawables(scene: var Scene, pipeline: Pipeline) = assert pipeline.device.vk.valid + if pipeline.vk in scene.drawables: for drawable in scene.drawables[pipeline.vk].mitems: scene.destroy(pipeline.vk) scene.drawables[pipeline.vk] = @[] - var - nonIndexedMeshes: seq[Mesh] - tinyIndexedMeshes: seq[Mesh] - smallIndexedMeshes: seq[Mesh] - bigIndexedMeshes: seq[Mesh] - allIndexedMeshes: seq[Mesh] + var allMeshes: seq[Mesh] for mesh in allComponentsOfType[Mesh](scene.root): - for inputAttr in pipeline.inputs.vertexInputs: - assert mesh.hasVertexDataFor(inputAttr.name), &"{mesh} missing data for {inputAttr}" - case mesh.indexType: - of None: nonIndexedMeshes.add mesh - of Tiny: tinyIndexedMeshes.add mesh - of Small: smallIndexedMeshes.add mesh - of Big: bigIndexedMeshes.add mesh - - # ordering meshes this way allows us to ignore value alignment (I think, needs more testing) - allIndexedMeshes = bigIndexedMeshes & smallIndexedMeshes & tinyIndexedMeshes + allMeshes.add mesh + for inputAttr in pipeline.inputs: + assert mesh.hasDataFor(inputAttr.name), &"{mesh} missing data for {inputAttr}" - var - indicesBufferSize = 0'u64 - indexOffset = 0'u64 - for mesh in allIndexedMeshes: - indicesBufferSize += mesh.indexDataSize - var indexBuffer: Buffer + var indicesBufferSize = 0'u64 + for mesh in allMeshes: + if mesh.indexType != None: + let indexAlignment = case mesh.indexType + of None: 0'u64 + of Tiny: 1'u64 + of Small: 2'u64 + of Big: 4'u64 + # index value alignment required by Vulkan + if indicesBufferSize mod indexAlignment != 0: + indicesBufferSize += indexAlignment - (indicesBufferSize mod indexAlignment) + indicesBufferSize += mesh.indexDataSize if indicesBufferSize > 0: - indexBuffer = pipeline.device.createBuffer( + scene.indexBuffer = pipeline.device.createBuffer( size=indicesBufferSize, usage=[VK_BUFFER_USAGE_INDEX_BUFFER_BIT], useVRAM=true, mappable=false, ) - for location, attributes in pipeline.inputs.vertexInputs.groupByMemoryLocation().pairs: + # one vertex data buffer per memory location + var perLocationOffsets: Table[MemoryLocation, uint64] + for location, attributes in pipeline.inputs.groupByMemoryLocation().pairs: # setup one buffer per attribute-location-type var bufferSize = 0'u64 - for mesh in nonIndexedMeshes & allIndexedMeshes: - bufferSize += mesh.vertexDataSize - if bufferSize == 0: - continue - var - bufferOffset = 0'u64 - buffer = pipeline.device.createBuffer( + for mesh in allMeshes: + for attribute in attributes: + bufferSize += mesh.dataSize(attribute.name) + if bufferSize > 0: + scene.vertexBuffers[location] = pipeline.device.createBuffer( size=bufferSize, usage=[VK_BUFFER_USAGE_VERTEX_BUFFER_BIT], useVRAM=location in [VRAM, VRAMVisible], mappable=location in [VRAMVisible, RAM], ) + perLocationOffsets[location] = 0 - # TODO: gather instance data/buffers - # non-indexed mesh drawable - if nonIndexedMeshes.len > 0: - var vertexCount = 0'u32 - for mesh in nonIndexedMeshes: - vertexCount += mesh.vertexCount - # remark: we merge all meshes into a single drawcall... smart?# - # I think bad for instancing... - var nonIndexedDrawable = Drawable( - elementCount: vertexCount, - buffer: buffer, - indexed: false, - instanceCount: 1 - ) - for inputAttr in attributes: - nonIndexedDrawable.offsets.add bufferOffset - for mesh in nonIndexedMeshes: - var (pdata, size) = mesh.getRawVertexData(inputAttr.name) - buffer.setData(pdata, size, bufferOffset) - bufferOffset += size - scene.drawables[pipeline.vk].add nonIndexedDrawable + var indexBufferOffset = 0'u64 + for mesh in allMeshes: + var offsets: Table[MemoryLocation, seq[uint64]] + for location, attributes in pipeline.inputs.groupByMemoryLocation().pairs: + for attribute in attributes: + if not (location in offsets): + offsets[location] = @[] + offsets[location].add perLocationOffsets[location] + var (pdata, size) = mesh.getRawData(attribute.name) + scene.vertexBuffers[location].setData(pdata, size, perLocationOffsets[location]) + perLocationOffsets[location] += size - # indexed mesh drawable - for mesh in allIndexedMeshes: - var drawable = Drawable( - elementCount: mesh.indicesCount, - buffer: buffer, - indexed: true, - indexBuffer: indexBuffer, - indexOffset: indexOffset, - indexType: mesh.indexType, - instanceCount: 1 - ) + let indexed = mesh.indexType != None + var drawable = Drawable( + elementCount: if indexed: mesh.indicesCount else: mesh.vertexCount, + bufferOffsets: offsets, + instanceCount: mesh.instanceCount, + indexed: indexed, + ) + if indexed: + let indexAlignment = case mesh.indexType + of None: 0'u64 + of Tiny: 1'u64 + of Small: 2'u64 + of Big: 4'u64 + # index value alignment required by Vulkan + if indexBufferOffset mod indexAlignment != 0: + indexBufferOffset += indexAlignment - (indexBufferOffset mod indexAlignment) + drawable.indexBufferOffset = indexBufferOffset + drawable.indexType = mesh.indexType var (pdata, size) = mesh.getRawIndexData() - indexBuffer.setData(pdata, size, indexOffset) - indexOffset += size - for inputAttr in attributes: - drawable.offsets.add bufferOffset - var (pdata, size) = mesh.getRawVertexData(inputAttr.name) - buffer.setData(pdata, size, bufferOffset) - bufferOffset += size - scene.drawables[pipeline.vk].add drawable + scene.indexBuffer.setData(pdata, size, indexBufferOffset) + indexBufferOffset += size + scene.drawables[pipeline.vk].add drawable proc setupDrawables*(scene: var Scene, renderPass: RenderPass) = for subpass in renderPass.subpasses: diff -r 55be3579dc30 -r cb9e27a30165 src/semicongine/vulkan/buffer.nim --- a/src/semicongine/vulkan/buffer.nim Mon Apr 10 00:53:16 2023 +0700 +++ b/src/semicongine/vulkan/buffer.nim Mon Apr 10 20:09:37 2023 +0700 @@ -20,6 +20,9 @@ of true: memory*: DeviceMemory +proc `==`*(a, b: Buffer): bool = + a.vk == b.vk + func `$`*(buffer: Buffer): string = &"Buffer(vk: {buffer.vk}, size: {buffer.size}, usage: {buffer.usage})" diff -r 55be3579dc30 -r cb9e27a30165 src/semicongine/vulkan/swapchain.nim --- a/src/semicongine/vulkan/swapchain.nim Mon Apr 10 00:53:16 2023 +0700 +++ b/src/semicongine/vulkan/swapchain.nim Mon Apr 10 20:09:37 2023 +0700 @@ -203,13 +203,23 @@ commandBuffer.endRenderCommands() proc draw*(commandBuffer: VkCommandBuffer, drawables: seq[Drawable], scene: Scene) = + + debug "Scene buffers:" + for (location, buffer) in scene.vertexBuffers.pairs: + echo " ", location, ": ", buffer + echo " Index buffer: ", scene.indexBuffer + for drawable in drawables: debug "Draw ", drawable + var buffers: seq[VkBuffer] var offsets: seq[VkDeviceSize] - for offset in drawable.offsets: - buffers.add drawable.buffer.vk - offsets.add VkDeviceSize(offset) + + for (location, bufferOffsets) in drawable.bufferOffsets.pairs: + for offset in bufferOffsets: + buffers.add scene.vertexBuffers[location].vk + offsets.add VkDeviceSize(offset) + commandBuffer.vkCmdBindVertexBuffers( firstBinding=0'u32, bindingCount=uint32(buffers.len), @@ -217,7 +227,7 @@ pOffsets=offsets.toCPointer() ) if drawable.indexed: - commandBuffer.vkCmdBindIndexBuffer(drawable.indexBuffer.vk, VkDeviceSize(drawable.indexOffset), drawable.indexType) + commandBuffer.vkCmdBindIndexBuffer(scene.indexBuffer.vk, VkDeviceSize(drawable.indexBufferOffset), drawable.indexType) commandBuffer.vkCmdDrawIndexed( indexCount=drawable.elementCount, instanceCount=drawable.instanceCount, diff -r 55be3579dc30 -r cb9e27a30165 tests/test_vulkan_wrapper.nim --- a/tests/test_vulkan_wrapper.nim Mon Apr 10 00:53:16 2023 +0700 +++ b/tests/test_vulkan_wrapper.nim Mon Apr 10 20:09:37 2023 +0700 @@ -33,65 +33,10 @@ for format in device.getSurfaceFormats(): echo " " & $format -when isMainModule: - # INIT ENGINE: - # create instance - var thewindow = createWindow("Test") - var instance = thewindow.createInstance( - vulkanVersion=VK_MAKE_API_VERSION(0, 1, 3, 0), - instanceExtensions= @["VK_EXT_debug_utils"], - layers= @["VK_LAYER_KHRONOS_validation", "VK_LAYER_MESA_overlay"] - ) - var debugger = instance.createDebugMessenger() - # create devices - let selectedPhysicalDevice = instance.getPhysicalDevices().filterBestGraphics() - var device = instance.createDevice( - selectedPhysicalDevice, - @[], - @["VK_EXT_index_type_uint8"], - selectedPhysicalDevice.filterForGraphicsPresentationQueues() - ) - - # INIT RENDERER: - const - vertexInput = @[ - attr[Vec3f]("position"), - attr[Vec3f]("color"), - attr[Vec3f]("translate", perInstance=true) - ] - vertexOutput = @[attr[Vec3f]("outcolor")] - uniforms = @[attr[float32]("time")] - fragOutput = @[attr[Vec4f]("color")] - vertexCode = compileGlslShader( - stage=VK_SHADER_STAGE_VERTEX_BIT, - inputs=vertexInput, - uniforms=uniforms, - outputs=vertexOutput, - body="""gl_Position = vec4(position, 1.0); outcolor = color * sin(Uniforms.time) * 0.5 + 0.5;""" - ) - fragmentCode = compileGlslShader( - stage=VK_SHADER_STAGE_FRAGMENT_BIT, - inputs=vertexOutput, - uniforms=uniforms, - outputs=fragOutput, - body="color = vec4(outcolor, 1);" - ) - var - vertexshader = device.createShaderModule(vertexCode) - fragmentshader = device.createShaderModule(fragmentCode) - surfaceFormat = device.physicalDevice.getSurfaceFormats().filterSurfaceFormat() - renderPass = device.simpleForwardRenderPass(surfaceFormat.format, vertexshader, fragmentshader, 2) - (swapchain, res) = device.createSwapchain(renderPass, surfaceFormat, device.firstGraphicsQueue().get().family, 2) - if res != VK_SUCCESS: - raise newException(Exception, "Unable to create swapchain") - - # INIT SCENE - var time = initShaderGlobal("time", 0.0'f32) - #[ - var thescene = Scene( +proc scene_different_mesh_types(): Scene = + result = Scene( name: "main", root: newEntity("root", - newEntity("stuff", time), 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)], @@ -124,27 +69,98 @@ )), ) ) - ]# - var mymesh = newMesh( + +proc scene_simple(): Scene = + 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)], + ) + 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)], ) - setInstanceData[Vec3f](mymesh, "translate", @[newVec3f(0.3, 0.3)]) - var thescene = Scene( + 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)], + 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)], + indices=[[0'u16, 1'u16, 2'u16]], + ) + setMeshData[Vec3f](mymesh1, "translate", @[newVec3f(0.3, 0.3)]) + result = Scene( name: "main", - root: newEntity("root", - newEntity("stuff", time), - newEntity("triangle", mymesh), + root: newEntity("root", newEntity("triangle", mymesh4, mymesh3, mymesh2, mymesh1),) + ) + + +when isMainModule: + # INIT ENGINE: + # create instance + var thewindow = createWindow("Test") + var instance = thewindow.createInstance( + vulkanVersion=VK_MAKE_API_VERSION(0, 1, 3, 0), + instanceExtensions= @["VK_EXT_debug_utils"], + layers= @["VK_LAYER_KHRONOS_validation", "VK_LAYER_MESA_overlay"] + ) + var debugger = instance.createDebugMessenger() + # create devices + let selectedPhysicalDevice = instance.getPhysicalDevices().filterBestGraphics() + var device = instance.createDevice( + selectedPhysicalDevice, + @[], + @["VK_EXT_index_type_uint8"], + selectedPhysicalDevice.filterForGraphicsPresentationQueues() + ) + + # INIT RENDERER: + const + vertexInput = @[ + attr[Vec3f]("position", memoryLocation=VRAM), + attr[Vec3f]("color", memoryLocation=VRAM), + # attr[Vec3f]("translate", perInstance=true) + ] + vertexOutput = @[attr[Vec3f]("outcolor")] + uniforms = @[attr[float32]("time")] + fragOutput = @[attr[Vec4f]("color")] + vertexCode = compileGlslShader( + stage=VK_SHADER_STAGE_VERTEX_BIT, + inputs=vertexInput, + uniforms=uniforms, + outputs=vertexOutput, + body="""gl_Position = vec4(position, 1.0); outcolor = color * sin(Uniforms.time) * 0.5 + 0.5;""" ) - ) + fragmentCode = compileGlslShader( + stage=VK_SHADER_STAGE_FRAGMENT_BIT, + inputs=vertexOutput, + uniforms=uniforms, + outputs=fragOutput, + body="color = vec4(outcolor, 1);" + ) + var + vertexshader = device.createShaderModule(vertexCode) + fragmentshader = device.createShaderModule(fragmentCode) + surfaceFormat = device.physicalDevice.getSurfaceFormats().filterSurfaceFormat() + renderPass = device.simpleForwardRenderPass(surfaceFormat.format, vertexshader, fragmentshader, 2) + (swapchain, res) = device.createSwapchain(renderPass, surfaceFormat, device.firstGraphicsQueue().get().family, 2) + if res != VK_SUCCESS: + raise newException(Exception, "Unable to create swapchain") + + # INIT SCENE + var time = initShaderGlobal("time", 0.0'f32) + + var thescene = scene_simple() + thescene.root.components.add time thescene.setupDrawables(renderPass) swapchain.setupUniforms(thescene) # MAINLOOP echo "Setup successfull, start rendering" - for i in 0 ..< 1: + for i in 0 ..< 10000: setValue[float32](time.value, get[float32](time.value) + 0.0005) - echo get[float32](time.value) discard swapchain.drawScene(thescene) echo "Rendered ", swapchain.framesRendered, " frames" checkVkResult device.vk.vkDeviceWaitIdle()