# HG changeset patch # User Sam # Date 1680107739 -25200 # Node ID 1cf928eb0a1051cb4e193051d1ff8605b2025372 # Parent f4d8f0018670edf35fe4f2ce003a9b06cbc5e555 did: refactor rendering/scene concept diff -r f4d8f0018670 -r 1cf928eb0a10 src/semicongine/entity.nim --- a/src/semicongine/entity.nim Tue Mar 28 00:20:49 2023 +0700 +++ b/src/semicongine/entity.nim Wed Mar 29 23:35:39 2023 +0700 @@ -5,46 +5,46 @@ type Component* = ref object of RootObj - thing*: Entity + entity*: Entity Entity* = ref object of RootObj name*: string transform*: Mat44 # todo: cache transform + only update VBO when transform changed parent*: Entity children*: seq[Entity] - parts*: seq[Component] + components*: seq[Component] -func `$`*(thing: Entity): string = thing.name +func `$`*(entity: Entity): string = entity.name method `$`*(part: Component): string {.base.} = - if part.thing != nil: - &"{part.thing} -> Component" + if part.entity != nil: + &"{part.entity} -> Component" else: &"Standalone Component" -proc add*(thing: Entity, child: Entity) = - child.parent = thing - thing.children.add child -proc add*(thing: Entity, part: Component) = - part.thing = thing - thing.parts.add part -proc add*(thing: Entity, children: seq[Entity]) = +proc add*(entity: Entity, child: Entity) = + child.parent = entity + entity.children.add child +proc add*(entity: Entity, part: Component) = + part.entity = entity + entity.components.add part +proc add*(entity: Entity, children: seq[Entity]) = for child in children: - child.parent = thing - thing.children.add child -proc add*(thing: Entity, parts: seq[Component]) = - for part in parts: - part.thing = thing - thing.parts.add part + child.parent = entity + entity.children.add child +proc add*(entity: Entity, components: seq[Component]) = + for part in components: + part.entity = entity + entity.components.add part -func newThing*(name: string = ""): Entity = +func newEntity*(name: string = ""): Entity = result = new Entity result.name = name result.transform = Unit44 if result.name == "": result.name = &"Entity[{$(cast[ByteAddress](result))}]" -func newThing*(name: string, firstChild: Entity, children: varargs[ +func newEntity*(name: string, firstChild: Entity, children: varargs[ Entity]): Entity = result = new Entity result.add firstChild @@ -55,32 +55,32 @@ if result.name == "": result.name = &"Entity[{$(cast[ByteAddress](result))}]" -proc newThing*(name: string, firstPart: Component, parts: varargs[Component]): Entity = +proc newEntity*(name: string, firstPart: Component, components: varargs[Component]): Entity = result = new Entity result.name = name result.add firstPart - for part in parts: + for part in components: result.add part if result.name == "": result.name = &"Entity[{$(cast[ByteAddress](result))}]" result.transform = Unit44 -func getModelTransform*(thing: Entity): Mat44 = +func getModelTransform*(entity: Entity): Mat44 = result = Unit44 - var currentThing = thing - while currentThing != nil: - result = currentThing.transform * result - currentThing = currentThing.parent + var currentEntity = entity + while currentEntity != nil: + result = currentEntity.transform * result + currentEntity = currentEntity.parent iterator allPartsOfType*[T: Component](root: Entity): T = var queue = @[root] while queue.len > 0: - let thing = queue.pop - for part in thing.parts: + let entity = queue.pop + for part in entity.components: if part of T: yield T(part) - for i in countdown(thing.children.len - 1, 0): - queue.add thing.children[i] + for i in countdown(entity.children.len - 1, 0): + queue.add entity.children[i] func firstWithName*(root: Entity, name: string): Entity = var queue = @[root] @@ -97,7 +97,7 @@ let next = queue.pop for child in next.children: if child.name == name: - for part in child.parts: + for part in child.components: if part of T: return T(part) queue.add child @@ -117,12 +117,12 @@ let next = queue.pop for child in next.children: if child.name == name: - for part in child.parts: + for part in child.components: if part of T: result.add T(part) queue.add child -iterator allThings*(root: Entity): Entity = +iterator allEntities*(root: Entity): Entity = var queue = @[root] while queue.len > 0: let next = queue.pop diff -r f4d8f0018670 -r 1cf928eb0a10 src/semicongine/mesh.nim --- a/src/semicongine/mesh.nim Tue Mar 28 00:20:49 2023 +0700 +++ b/src/semicongine/mesh.nim Wed Mar 29 23:35:39 2023 +0700 @@ -8,7 +8,6 @@ import ./math/vector type - # TODO: make single mesh type, with case-of attribute for indices Mesh*[T: object, U: uint16|uint32] = ref object of Part vertexData*: T case indexed*: bool diff -r f4d8f0018670 -r 1cf928eb0a10 src/semicongine/scene.nim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/semicongine/scene.nim Wed Mar 29 23:35:39 2023 +0700 @@ -0,0 +1,13 @@ +import std/options + +import ./vulkan/api +import ./entity +import ./vulkan/buffer + +type + Scene* = object + root*: Entity + +# attribute_buffers, number_of_vertices, number_of_instances, (indexbuffer, indextype) +proc getBufferSets*(scene: Scene): seq[(seq[Buffer], uint32, uint32, Option[(Buffer, VkIndexType)])] = + result diff -r f4d8f0018670 -r 1cf928eb0a10 src/semicongine/vulkan/instance.nim --- a/src/semicongine/vulkan/instance.nim Tue Mar 28 00:20:49 2023 +0700 +++ b/src/semicongine/vulkan/instance.nim Wed Mar 29 23:35:39 2023 +0700 @@ -1,5 +1,7 @@ import std/strformat +import std/tables import std/sequtils +import std/logging import ./api import ./utils @@ -89,13 +91,21 @@ instance.vk.vkDestroyInstance(nil) instance.vk.reset() +const LEVEL_MAPPING = { + VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: lvlDebug, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: lvlInfo, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: lvlWarn, + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: lvlError, +}.toTable + proc defaultDebugCallback( messageSeverity: VkDebugUtilsMessageSeverityFlagBitsEXT, messageTypes: VkDebugUtilsMessageTypeFlagsEXT, pCallbackData: ptr VkDebugUtilsMessengerCallbackDataEXT, userData: pointer ): VkBool32 {.cdecl.} = - echo &"{messageSeverity}: {toEnums messageTypes}: {pCallbackData.pMessage}" + + log LEVEL_MAPPING[messageSeverity], &"{toEnums messageTypes}: {pCallbackData.pMessage}" return false proc createDebugMessenger*( diff -r f4d8f0018670 -r 1cf928eb0a10 src/semicongine/vulkan/pipeline.nim --- a/src/semicongine/vulkan/pipeline.nim Tue Mar 28 00:20:49 2023 +0700 +++ b/src/semicongine/vulkan/pipeline.nim Wed Mar 29 23:35:39 2023 +0700 @@ -1,9 +1,12 @@ +import std/options + import ./api import ./utils import ./device -import ./shader import ./descriptor +import ../scene + type Pipeline* = object device*: Device @@ -13,9 +16,24 @@ descriptorPool*: DescriptorPool descriptorSets*: seq[DescriptorSet] -proc run*(pipeline: Pipeline, commandBuffer: VkCommandBuffer) = - # pipeline an descriptors bound - echo "Running pipeline" +proc run*(pipeline: Pipeline, commandBuffer: VkCommandBuffer, inFlightFrame: int, scene: Scene) = + var varPipeline = pipeline + commandBuffer.vkCmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.vk) + commandBuffer.vkCmdBindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.layout, 0, 1, addr(varPipeline.descriptorSets[inFlightFrame].vk), 0, nil) + for (bufferSet, count, instanceCount, indexBuffer) in scene.getBufferSets(): + var buffers: seq[VkBuffer] + var offsets: seq[VkDeviceSize] + for buffer in bufferSet: + buffers.add buffer.vk + offsets.add VkDeviceSize(0) + + commandBuffer.vkCmdBindVertexBuffers(firstBinding=0'u32, bindingCount=uint32(buffers.len), pBuffers=buffers.toCPointer(), pOffsets=offsets.toCPointer()) + if indexBuffer.isSome: + commandBuffer.vkCmdBindIndexBuffer(indexBuffer.get()[0].vk, VkDeviceSize(0), indexBuffer.get()[1]) + commandBuffer.vkCmdDrawIndexed(indexCount=count, instanceCount=instanceCount, firstIndex=0, vertexOffset=0, firstInstance=0) + + else: + commandBuffer.vkCmdDraw(vertexCount=count, instanceCount=instanceCount, firstVertex=0, firstInstance=0) proc destroy*(pipeline: var Pipeline) = assert pipeline.device.vk.valid diff -r f4d8f0018670 -r 1cf928eb0a10 src/semicongine/vulkan/renderpass.nim --- a/src/semicongine/vulkan/renderpass.nim Tue Mar 28 00:20:49 2023 +0700 +++ b/src/semicongine/vulkan/renderpass.nim Wed Mar 29 23:35:39 2023 +0700 @@ -218,7 +218,15 @@ clearColor: clearColor ) ] - dependencies: seq[VkSubpassDependency] + # dependencies seems to be optional, TODO: benchmark difference + dependencies = @[VkSubpassDependency( + srcSubpass: VK_SUBPASS_EXTERNAL, + dstSubpass: 0, + srcStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT], + srcAccessMask: VkAccessFlags(0), + dstStageMask: toBits [VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT], + dstAccessMask: toBits [VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT], + )] result = device.createRenderPass(attachments=attachments, subpasses=subpasses, dependencies=dependencies, inFlightFrames=inFlightFrames) result.attachPipeline(vertexShader, fragmentShader, 0) diff -r f4d8f0018670 -r 1cf928eb0a10 src/semicongine/vulkan/swapchain.nim --- a/src/semicongine/vulkan/swapchain.nim Tue Mar 28 00:20:49 2023 +0700 +++ b/src/semicongine/vulkan/swapchain.nim Wed Mar 29 23:35:39 2023 +0700 @@ -11,6 +11,7 @@ import ./pipeline import ./syncing +import ../scene import ../math type @@ -99,7 +100,7 @@ return (swapchain, createResult) -proc drawNextFrame*(swapchain: var Swapchain): bool = +proc drawNextFrame*(swapchain: var Swapchain, scene: Scene): bool = assert swapchain.device.vk.valid assert swapchain.vk.valid assert swapchain.device.firstGraphicsQueue().isSome @@ -131,11 +132,7 @@ ): for i in 0 ..< swapchain.renderpass.subpasses.len: var pipeline = swapchain.renderpass.pipelines[i] - commandBuffer.vkCmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.vk) - commandBuffer.vkCmdBindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.layout, 0, 1, addr(pipeline.descriptorSets[swapchain.currentInFlight].vk), 0, nil) - pipeline.run(commandBuffer) - - swapchain.renderpass.pipelines[i].run(commandBuffer) + pipeline.run(commandBuffer, swapchain.currentInFlight, scene) if i < swapchain.renderpass.subpasses.len - 1: commandBuffer.vkCmdNextSubpass(VK_SUBPASS_CONTENTS_INLINE) diff -r f4d8f0018670 -r 1cf928eb0a10 tests/test_vulkan_wrapper.nim --- a/tests/test_vulkan_wrapper.nim Tue Mar 28 00:20:49 2023 +0700 +++ b/tests/test_vulkan_wrapper.nim Wed Mar 29 23:35:39 2023 +0700 @@ -3,6 +3,8 @@ import semicongine/vulkan import semicongine/platform/window import semicongine/math +import semicongine/entity +import semicongine/scene type Vertex = object @@ -75,9 +77,11 @@ if res != VK_SUCCESS: raise newException(Exception, "Unable to create swapchain") + var thescene = Scene(root: newEntity("scene")) + echo "All successfull" for i in 0 ..< 2: - discard swapchain.drawNextFrame() + discard swapchain.drawNextFrame(thescene) echo "Rendered ", swapchain.framesRendered, " frames" echo "Start cleanup"