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