Mercurial > games > semicongine
diff src/zamikongine/mesh.nim @ 480:14e5151f68d1
did: introduce scene graph, meshs and generic vertex buffers
author | Sam <sam@basx.dev> |
---|---|
date | Mon, 09 Jan 2023 11:04:19 +0700 |
parents | |
children | beb86492b178 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/zamikongine/mesh.nim Mon Jan 09 11:04:19 2023 +0700 @@ -0,0 +1,81 @@ +import std/typetraits + +import ./vulkan +import ./thing +import ./buffer +import ./vertex + +type + Mesh*[T] = object of Part + vertexData*: T + IndexedMesh*[T: object, U: uint16|uint32] = object of Part + vertexData*: T + indices*: seq[array[3, U]] + +func getVkIndexType[T: object, U: uint16|uint32](m: IndexedMesh[T, U]): VkIndexType = + when U is uint16: VK_INDEX_TYPE_UINT16 + elif U is uint32: VK_INDEX_TYPE_UINT32 + +proc createVertexBuffers*[M: Mesh|IndexedMesh]( + mesh: var M, + device: VkDevice, + physicalDevice: VkPhysicalDevice, + commandPool: VkCommandPool, + queue: VkQueue, + useDeviceLocalBuffer: bool = true # decides if data is transfered to the fast device-local memory or not +): (seq[Buffer], uint32) = + result[1] = mesh.vertexData.VertexCount + for name, value in mesh.vertexData.fieldPairs: + when typeof(value) is VertexAttribute: + assert value.data.len > 0 + var flags = if useDeviceLocalBuffer: {TransferSrc} else: {VertexBuffer} + var stagingBuffer = device.InitBuffer(physicalDevice, value.datasize, flags, {VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT}) + var d: pointer + stagingBuffer.withMapping(d): + copyMem(d, addr(value.data[0]), value.datasize) + + if useDeviceLocalBuffer: + var finalBuffer = device.InitBuffer(physicalDevice, value.datasize, {TransferDst, VertexBuffer}, {VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT}) + copyBuffer(commandPool, queue, stagingBuffer, finalBuffer, value.datasize) + stagingBuffer.trash() + result[0].add(finalBuffer) + else: + result[0].add(stagingBuffer) + +proc createIndexBuffer*( + mesh: var IndexedMesh, + device: VkDevice, + physicalDevice: VkPhysicalDevice, + commandPool: VkCommandPool, + queue: VkQueue, + useDeviceLocalBuffer: bool = true # decides if data is transfered to the fast device-local memory or not +): Buffer = + let bufferSize = uint64(mesh.indices.len * sizeof(get(genericParams(typeof(mesh.indices)), 0))) + let flags = if useDeviceLocalBuffer: {TransferSrc} else: {IndexBuffer} + + var stagingBuffer = device.InitBuffer(physicalDevice, bufferSize, flags, {VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT}) + var d: pointer + stagingBuffer.withMapping(d): + copyMem(d, addr(mesh.indices[0]), bufferSize) + + if useDeviceLocalBuffer: + var finalBuffer = device.InitBuffer(physicalDevice, bufferSize, {TransferDst, IndexBuffer}, {VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT}) + copyBuffer(commandPool, queue, stagingBuffer, finalBuffer, bufferSize) + stagingBuffer.trash() + return finalBuffer + else: + return stagingBuffer + +proc createIndexedVertexBuffers*( + mesh: var IndexedMesh, + device: VkDevice, + physicalDevice: VkPhysicalDevice, + commandPool: VkCommandPool, + queue: VkQueue, + useDeviceLocalBuffer: bool = true # decides if data is transfered to the fast device-local memory or not +): (seq[Buffer], Buffer, uint32, VkIndexType) = + result[0] = createVertexBuffers(mesh, device, physicalDevice, commandPool, queue, useDeviceLocalBuffer)[0] + result[1] = createIndexBuffer(mesh, device, physicalDevice, commandPool, queue, useDeviceLocalBuffer) + result[2] = uint32(mesh.indices.len * mesh.indices[0].len) + + result[3] = getVkIndexType(mesh)