Mercurial > games > semicongine
diff src/zamikongine/buffer.nim @ 19:b55d6ecde79d
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 | b1b05d4efb52 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/zamikongine/buffer.nim Mon Jan 09 11:04:19 2023 +0700 @@ -0,0 +1,103 @@ +import ./vulkan +import ./vulkan_helpers + +type + BufferType* = enum + None = 0 + TransferSrc = VK_BUFFER_USAGE_TRANSFER_SRC_BIT + TransferDst = VK_BUFFER_USAGE_TRANSFER_DST_BIT + IndexBuffer = VK_BUFFER_USAGE_INDEX_BUFFER_BIT + VertexBuffer = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT + Buffer* = object + device*: VkDevice + vkBuffer*: VkBuffer + size*: uint64 + memoryRequirements*: VkMemoryRequirements + memory*: VkDeviceMemory + bufferTypes*: set[BufferType] + +proc trash*(buffer: var Buffer) = + assert int64(buffer.vkBuffer) != 0 + assert int64(buffer.memory) != 0 + vkDestroyBuffer(buffer.device, buffer.vkBuffer, nil) + buffer.vkBuffer = VkBuffer(0) + vkFreeMemory(buffer.device, buffer.memory, nil) + buffer.memory = VkDeviceMemory(0) + +proc findMemoryType(buffer: Buffer, physicalDevice: VkPhysicalDevice, properties: VkMemoryPropertyFlags): uint32 = + var physicalProperties: VkPhysicalDeviceMemoryProperties + vkGetPhysicalDeviceMemoryProperties(physicalDevice, addr(physicalProperties)) + + for i in 0'u32 ..< physicalProperties.memoryTypeCount: + if bool(buffer.memoryRequirements.memoryTypeBits and (1'u32 shl i)) and (uint32(physicalProperties.memoryTypes[i].propertyFlags) and uint32(properties)) == uint32(properties): + return i + +proc InitBuffer*( + device: VkDevice, + physicalDevice: VkPhysicalDevice, + size: uint64, + bufferTypes: set[BufferType], + properties: set[VkMemoryPropertyFlagBits] +): Buffer = + result = Buffer(device: device, size: size, bufferTypes: bufferTypes) + var usageFlags = 0 + for usage in bufferTypes: + usageFlags = ord(usageFlags) or ord(usage) + var bufferInfo = VkBufferCreateInfo( + sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + size: VkDeviceSize(result.size), + usage: VkBufferUsageFlags(usageFlags), + sharingMode: VK_SHARING_MODE_EXCLUSIVE, + ) + checkVkResult vkCreateBuffer(result.device, addr(bufferInfo), nil, addr(result.vkBuffer)) + vkGetBufferMemoryRequirements(result.device, result.vkBuffer, addr(result.memoryRequirements)) + + var memoryProperties = 0'u32 + for prop in properties: + memoryProperties = memoryProperties or uint32(prop) + + var allocInfo = VkMemoryAllocateInfo( + sType: VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, + allocationSize: result.memoryRequirements.size, + memoryTypeIndex: result.findMemoryType(physicalDevice, VkMemoryPropertyFlags(memoryProperties)) + ) + checkVkResult result.device.vkAllocateMemory(addr(allocInfo), nil, addr(result.memory)) + checkVkResult result.device.vkBindBufferMemory(result.vkBuffer, result.memory, VkDeviceSize(0)) + + +template withMapping*(buffer: Buffer, data: pointer, body: untyped): untyped = + checkVkResult vkMapMemory(buffer.device, buffer.memory, offset=VkDeviceSize(0), VkDeviceSize(buffer.size), VkMemoryMapFlags(0), addr(data)) + body + vkUnmapMemory(buffer.device, buffer.memory) + + +proc copyBuffer*(commandPool: VkCommandPool, queue: VkQueue, src, dst: Buffer, size: uint64) = + assert uint64(src.device) == uint64(dst.device) + var + allocInfo = VkCommandBufferAllocateInfo( + sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + level: VK_COMMAND_BUFFER_LEVEL_PRIMARY, + commandPool: commandPool, + commandBufferCount: 1, + ) + commandBuffer: VkCommandBuffer + checkVkResult vkAllocateCommandBuffers(src.device, addr(allocInfo), addr(commandBuffer)) + + var beginInfo = VkCommandBufferBeginInfo( + sType: VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + flags: VkCommandBufferUsageFlags(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT), + ) + checkVkResult vkBeginCommandBuffer(commandBuffer, addr(beginInfo)) + var copyRegion = VkBufferCopy(size: VkDeviceSize(size)) + vkCmdCopyBuffer(commandBuffer, src.vkBuffer, dst.vkBuffer, 1, addr(copyRegion)) + checkVkResult vkEndCommandBuffer(commandBuffer) + + var submitInfo = VkSubmitInfo( + sType: VK_STRUCTURE_TYPE_SUBMIT_INFO, + commandBufferCount: 1, + pCommandBuffers: addr(commandBuffer), + ) + + checkVkResult vkQueueSubmit(queue, 1, addr(submitInfo), VkFence(0)) + checkVkResult vkQueueWaitIdle(queue) + vkFreeCommandBuffers(src.device, commandPool, 1, addr(commandBuffer))