Mercurial > games > semicongine
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 1217:f819a874058f | 1218:56781cc0fc7c |
|---|---|
| 1 import std/strformat | |
| 2 import std/typetraits | |
| 3 import std/sequtils | |
| 4 import std/tables | |
| 5 import std/logging | |
| 6 | |
| 7 import ../core | |
| 8 import ./device | |
| 9 import ./memory | |
| 10 import ./physicaldevice | |
| 11 import ./commandbuffer | |
| 12 | |
| 13 type | |
| 14 Buffer* = object | |
| 15 device*: Device | |
| 16 vk*: VkBuffer | |
| 17 size*: uint64 | |
| 18 usage*: seq[VkBufferUsageFlagBits] | |
| 19 case memoryAllocated*: bool | |
| 20 of false: discard | |
| 21 of true: | |
| 22 memory*: DeviceMemory | |
| 23 | |
| 24 | |
| 25 proc `==`*(a, b: Buffer): bool = | |
| 26 a.vk == b.vk | |
| 27 | |
| 28 func `$`*(buffer: Buffer): string = | |
| 29 &"Buffer(vk: {buffer.vk}, size: {buffer.size}, usage: {buffer.usage})" | |
| 30 | |
| 31 proc requirements(buffer: Buffer): MemoryRequirements = | |
| 32 assert buffer.vk.Valid | |
| 33 assert buffer.device.vk.Valid | |
| 34 var req: VkMemoryRequirements | |
| 35 buffer.device.vk.vkGetBufferMemoryRequirements(buffer.vk, addr req) | |
| 36 result.size = req.size | |
| 37 result.alignment = req.alignment | |
| 38 let memorytypes = buffer.device.physicaldevice.vk.GetMemoryProperties().types | |
| 39 for i in 0 ..< sizeof(req.memoryTypeBits) * 8: | |
| 40 if ((req.memoryTypeBits shr i) and 1) == 1: | |
| 41 result.memoryTypes.add memorytypes[i] | |
| 42 | |
| 43 proc allocateMemory(buffer: var Buffer, requireMappable: bool, preferVRAM: bool, preferAutoFlush: bool) = | |
| 44 assert buffer.device.vk.Valid | |
| 45 assert buffer.memoryAllocated == false | |
| 46 | |
| 47 let requirements = buffer.requirements() | |
| 48 let memoryType = requirements.memoryTypes.SelectBestMemoryType( | |
| 49 requireMappable = requireMappable, | |
| 50 preferVRAM = preferVRAM, | |
| 51 preferAutoFlush = preferAutoFlush | |
| 52 ) | |
| 53 | |
| 54 debug "Allocating memory for buffer: ", buffer.size, " bytes of type ", memoryType | |
| 55 # need to replace the whole buffer object, due to case statement | |
| 56 buffer = Buffer( | |
| 57 device: buffer.device, | |
| 58 vk: buffer.vk, | |
| 59 size: buffer.size, | |
| 60 usage: buffer.usage, | |
| 61 memoryAllocated: true, | |
| 62 memory: buffer.device.Allocate(requirements.size, memoryType) | |
| 63 ) | |
| 64 checkVkResult buffer.device.vk.vkBindBufferMemory(buffer.vk, buffer.memory.vk, VkDeviceSize(0)) | |
| 65 | |
| 66 # currently no support for extended structure and concurrent/shared use | |
| 67 # (shardingMode = VK_SHARING_MODE_CONCURRENT not supported) | |
| 68 proc CreateBuffer*( | |
| 69 device: Device, | |
| 70 size: uint64, | |
| 71 usage: openArray[VkBufferUsageFlagBits], | |
| 72 requireMappable: bool, | |
| 73 preferVRAM: bool, | |
| 74 preferAutoFlush = true, | |
| 75 ): Buffer = | |
| 76 assert device.vk.Valid | |
| 77 assert size > 0 | |
| 78 | |
| 79 result.device = device | |
| 80 result.size = size | |
| 81 result.usage = usage.toSeq | |
| 82 if not requireMappable: | |
| 83 result.usage.add VK_BUFFER_USAGE_TRANSFER_DST_BIT | |
| 84 var createInfo = VkBufferCreateInfo( | |
| 85 sType: VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | |
| 86 flags: VkBufferCreateFlags(0), | |
| 87 size: size, | |
| 88 usage: toBits(result.usage), | |
| 89 sharingMode: VK_SHARING_MODE_EXCLUSIVE, | |
| 90 ) | |
| 91 | |
| 92 checkVkResult vkCreateBuffer( | |
| 93 device = device.vk, | |
| 94 pCreateInfo = addr createInfo, | |
| 95 pAllocator = nil, | |
| 96 pBuffer = addr result.vk | |
| 97 ) | |
| 98 result.allocateMemory(requireMappable = requireMappable, preferVRAM = preferVRAM, preferAutoFlush = preferAutoFlush) | |
| 99 | |
| 100 | |
| 101 proc Copy*(src, dst: Buffer, queue: Queue, dstOffset = 0'u64) = | |
| 102 assert src.device.vk.Valid | |
| 103 assert dst.device.vk.Valid | |
| 104 assert src.device == dst.device | |
| 105 assert src.size + dstOffset <= dst.size | |
| 106 assert VK_BUFFER_USAGE_TRANSFER_SRC_BIT in src.usage | |
| 107 assert VK_BUFFER_USAGE_TRANSFER_DST_BIT in dst.usage | |
| 108 | |
| 109 var copyRegion = VkBufferCopy(size: VkDeviceSize(src.size), dstOffset: VkDeviceSize(dstOffset)) | |
| 110 WithSingleUseCommandBuffer(src.device, queue, commandBuffer): | |
| 111 commandBuffer.vkCmdCopyBuffer(src.vk, dst.vk, 1, addr(copyRegion)) | |
| 112 | |
| 113 proc Destroy*(buffer: var Buffer) = | |
| 114 assert buffer.device.vk.Valid | |
| 115 assert buffer.vk.Valid | |
| 116 buffer.device.vk.vkDestroyBuffer(buffer.vk, nil) | |
| 117 if buffer.memoryAllocated: | |
| 118 assert buffer.memory.vk.Valid | |
| 119 buffer.memory.Free() | |
| 120 buffer = Buffer( | |
| 121 device: buffer.device, | |
| 122 vk: buffer.vk, | |
| 123 size: buffer.size, | |
| 124 usage: buffer.usage, | |
| 125 memoryAllocated: false, | |
| 126 ) | |
| 127 buffer.vk.Reset | |
| 128 | |
| 129 template CanMap*(buffer: Buffer): bool = | |
| 130 buffer.memory.canMap | |
| 131 | |
| 132 proc SetData*(dst: Buffer, queue: Queue, src: pointer, size: uint64, bufferOffset = 0'u64) = | |
| 133 assert bufferOffset + size <= dst.size | |
| 134 if dst.CanMap: | |
| 135 copyMem(cast[pointer](cast[uint](dst.memory.data) + bufferOffset), src, size) | |
| 136 if dst.memory.needsFlushing: | |
| 137 dst.memory.Flush() | |
| 138 else: # use staging buffer, slower but required if memory is not host visible | |
| 139 var stagingBuffer = dst.device.CreateBuffer(size, [VK_BUFFER_USAGE_TRANSFER_SRC_BIT], requireMappable = true, preferVRAM = false, preferAutoFlush = true) | |
| 140 SetData(stagingBuffer, queue, src, size, 0) | |
| 141 stagingBuffer.Copy(dst, queue, bufferOffset) | |
| 142 stagingBuffer.Destroy() | |
| 143 | |
| 144 proc SetData*[T: seq](dst: Buffer, queue: Queue, src: ptr T, offset = 0'u64) = | |
| 145 dst.setData(queue, src, sizeof(get(genericParams(T), 0)) * src[].len, offset = offset) | |
| 146 | |
| 147 proc SetData*[T](dst: Buffer, queue: Queue, src: ptr T, offset = 0'u64) = | |
| 148 dst.setData(queue, src, sizeof(T), offset = offset) | |
| 149 |
