Mercurial > games > semicongine
diff semiconginev2/old/vulkan/buffer.nim @ 1218:56781cc0fc7c compiletime-tests
did: renamge main package
author | sam <sam@basx.dev> |
---|---|
date | Wed, 17 Jul 2024 21:01:37 +0700 |
parents | semicongine/old/vulkan/buffer.nim@a3eb305bcac2 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/semiconginev2/old/vulkan/buffer.nim Wed Jul 17 21:01:37 2024 +0700 @@ -0,0 +1,149 @@ +import std/strformat +import std/typetraits +import std/sequtils +import std/tables +import std/logging + +import ../core +import ./device +import ./memory +import ./physicaldevice +import ./commandbuffer + +type + Buffer* = object + device*: Device + vk*: VkBuffer + size*: uint64 + usage*: seq[VkBufferUsageFlagBits] + case memoryAllocated*: bool + of false: discard + 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})" + +proc requirements(buffer: Buffer): MemoryRequirements = + assert buffer.vk.Valid + assert buffer.device.vk.Valid + var req: VkMemoryRequirements + buffer.device.vk.vkGetBufferMemoryRequirements(buffer.vk, addr req) + result.size = req.size + result.alignment = req.alignment + let memorytypes = buffer.device.physicaldevice.vk.GetMemoryProperties().types + for i in 0 ..< sizeof(req.memoryTypeBits) * 8: + if ((req.memoryTypeBits shr i) and 1) == 1: + result.memoryTypes.add memorytypes[i] + +proc allocateMemory(buffer: var Buffer, requireMappable: bool, preferVRAM: bool, preferAutoFlush: bool) = + assert buffer.device.vk.Valid + assert buffer.memoryAllocated == false + + let requirements = buffer.requirements() + let memoryType = requirements.memoryTypes.SelectBestMemoryType( + requireMappable = requireMappable, + preferVRAM = preferVRAM, + preferAutoFlush = preferAutoFlush + ) + + debug "Allocating memory for buffer: ", buffer.size, " bytes of type ", memoryType + # need to replace the whole buffer object, due to case statement + buffer = Buffer( + device: buffer.device, + vk: buffer.vk, + size: buffer.size, + usage: buffer.usage, + memoryAllocated: true, + memory: buffer.device.Allocate(requirements.size, memoryType) + ) + checkVkResult buffer.device.vk.vkBindBufferMemory(buffer.vk, buffer.memory.vk, VkDeviceSize(0)) + +# currently no support for extended structure and concurrent/shared use +# (shardingMode = VK_SHARING_MODE_CONCURRENT not supported) +proc CreateBuffer*( + device: Device, + size: uint64, + usage: openArray[VkBufferUsageFlagBits], + requireMappable: bool, + preferVRAM: bool, + preferAutoFlush = true, +): Buffer = + assert device.vk.Valid + assert size > 0 + + result.device = device + result.size = size + result.usage = usage.toSeq + if not requireMappable: + result.usage.add VK_BUFFER_USAGE_TRANSFER_DST_BIT + var createInfo = VkBufferCreateInfo( + sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + flags: VkBufferCreateFlags(0), + size: size, + usage: toBits(result.usage), + sharingMode: VK_SHARING_MODE_EXCLUSIVE, + ) + + checkVkResult vkCreateBuffer( + device = device.vk, + pCreateInfo = addr createInfo, + pAllocator = nil, + pBuffer = addr result.vk + ) + result.allocateMemory(requireMappable = requireMappable, preferVRAM = preferVRAM, preferAutoFlush = preferAutoFlush) + + +proc Copy*(src, dst: Buffer, queue: Queue, dstOffset = 0'u64) = + assert src.device.vk.Valid + assert dst.device.vk.Valid + assert src.device == dst.device + assert src.size + dstOffset <= dst.size + assert VK_BUFFER_USAGE_TRANSFER_SRC_BIT in src.usage + assert VK_BUFFER_USAGE_TRANSFER_DST_BIT in dst.usage + + var copyRegion = VkBufferCopy(size: VkDeviceSize(src.size), dstOffset: VkDeviceSize(dstOffset)) + WithSingleUseCommandBuffer(src.device, queue, commandBuffer): + commandBuffer.vkCmdCopyBuffer(src.vk, dst.vk, 1, addr(copyRegion)) + +proc Destroy*(buffer: var Buffer) = + assert buffer.device.vk.Valid + assert buffer.vk.Valid + buffer.device.vk.vkDestroyBuffer(buffer.vk, nil) + if buffer.memoryAllocated: + assert buffer.memory.vk.Valid + buffer.memory.Free() + buffer = Buffer( + device: buffer.device, + vk: buffer.vk, + size: buffer.size, + usage: buffer.usage, + memoryAllocated: false, + ) + buffer.vk.Reset + +template CanMap*(buffer: Buffer): bool = + buffer.memory.canMap + +proc SetData*(dst: Buffer, queue: Queue, src: pointer, size: uint64, bufferOffset = 0'u64) = + assert bufferOffset + size <= dst.size + if dst.CanMap: + copyMem(cast[pointer](cast[uint](dst.memory.data) + bufferOffset), src, size) + if dst.memory.needsFlushing: + dst.memory.Flush() + else: # use staging buffer, slower but required if memory is not host visible + var stagingBuffer = dst.device.CreateBuffer(size, [VK_BUFFER_USAGE_TRANSFER_SRC_BIT], requireMappable = true, preferVRAM = false, preferAutoFlush = true) + SetData(stagingBuffer, queue, src, size, 0) + stagingBuffer.Copy(dst, queue, bufferOffset) + stagingBuffer.Destroy() + +proc SetData*[T: seq](dst: Buffer, queue: Queue, src: ptr T, offset = 0'u64) = + dst.setData(queue, src, sizeof(get(genericParams(T), 0)) * src[].len, offset = offset) + +proc SetData*[T](dst: Buffer, queue: Queue, src: ptr T, offset = 0'u64) = + dst.setData(queue, src, sizeof(T), offset = offset) +