SpiecsEngine
 
Loading...
Searching...
No Matches
VulkanBuffer.cpp
Go to the documentation of this file.
1/**
2* @file VulkanBuffer.cpp.
3* @brief The VulkanBuffer Class Implementation.
4* @author Spices.
5*/
6
7#include "Pchheader.h"
8#include "VulkanBuffer.h"
11
12namespace Spices {
13
15 VulkanState& vulkanState ,
16 const std::string& name ,
17 VkDeviceSize size ,
18 VkBufferUsageFlags usage ,
19 VkMemoryPropertyFlags properties
20 )
21 : VulkanObject(vulkanState)
22 , m_Name (name )
24 , m_Usage (usage )
26 {
28
29 /**
30 * @brief Create a buffer.
31 */
32 CreateBuffer(vulkanState, name, size, usage, properties);
33 }
34
36 {
38
40
41 /**
42 * @brief Destroy Vkbuffer.
43 */
44 vmaDestroyBuffer(m_VulkanState.m_VmaAllocator, m_Buffer, m_Alloc);
45
46#else
47
48 if (m_LocalMemory)
49 {
50 vkUnmapMemory(m_VulkanState.m_Device, m_BufferMemory);
51 }
52
53 /**
54 * @brief Destroy Vkbuffer.
55 */
56 vkDestroyBuffer(m_VulkanState.m_Device, m_Buffer, nullptr);
57 vkFreeMemory(m_VulkanState.m_Device, m_BufferMemory, nullptr);
58
59#endif
60
61 }
62
64 VkBuffer srcBuffer ,
65 VkBuffer dstBuffer ,
66 VkDeviceSize size
67 )
68 {
70
71 /**
72 * @brief Use CustomCmd.
73 */
74 VulkanCommandBuffer::CustomGraphicCmd(m_VulkanState, [&](auto& commandBuffer) {
75
76 /**
77 * @brief Instance a VkBufferCopy.
78 */
79 VkBufferCopy copyRegion{};
80 copyRegion.srcOffset = 0;
81 copyRegion.dstOffset = 0;
82 copyRegion.size = size;
83
84 /**
85 * @brief Copy Cmd.
86 */
87 vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, &copyRegion);
88 });
89 }
90
92 {
94
95 if (m_Usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
96 {
97 return m_BufferAddress;
98 }
99
100 SPICES_CORE_ERROR("This Buffer Cannot Get Address")
101 return m_BufferAddress;
102 }
103
104 void VulkanBuffer::Map(VkDeviceSize size, VkDeviceSize offset)
105 {
107
109
110 SPICES_CORE_ERROR("VMA cannot enter this function.")
111
112#else
113
114 /**
115 * @brief Map buffer's video memory to local memory.
116 */
117 VK_CHECK(vkMapMemory(m_VulkanState.m_Device, m_BufferMemory, offset, size, 0, &m_LocalMemory));
118
119#endif
120
121 }
122
124 {
126
127 m_BufferInfo.buffer = m_Buffer;
128 m_BufferInfo.offset = offset;
129 m_BufferInfo.range = size;
130
131 return &m_BufferInfo;
132 }
133
134 void VulkanBuffer::WriteToBuffer(const void* data, VkDeviceSize size, VkDeviceSize offset)
135 {
137
139
140 /**
141 * @brief Maped memory inside.
142 */
143 if (size == VK_WHOLE_SIZE)
144 {
145 VK_CHECK(vmaCopyMemoryToAllocation(m_VulkanState.m_VmaAllocator, data, m_Alloc, offset, m_DeviceSize))
146 }
147 else
148 {
149 VK_CHECK(vmaCopyMemoryToAllocation(m_VulkanState.m_VmaAllocator, data, m_Alloc, offset, size))
150 }
151
152#else
153
154 if (!m_LocalMemory){ Map(); }
155
156 /**
157 * @brief Use memcpy copy data.
158 */
159 if (size == VK_WHOLE_SIZE)
160 {
161 memcpy(m_LocalMemory, data, m_DeviceSize);
162 }
163 else
164 {
165 char* memOffset = static_cast<char*>(m_LocalMemory);
166 memOffset += offset;
167 memcpy(memOffset, data, size);
168 }
169
170#endif
171
172 }
173
174 void VulkanBuffer::WriteFromBuffer(void* data, VkDeviceSize size, VkDeviceSize offset)
175 {
177
179
180 /**
181 * @brief Maped memory inside.
182 */
183 if (size == VK_WHOLE_SIZE)
184 {
185 VK_CHECK(vmaCopyAllocationToMemory(m_VulkanState.m_VmaAllocator, m_Alloc, offset, data, m_DeviceSize))
186 }
187 else
188 {
189 VK_CHECK(vmaCopyAllocationToMemory(m_VulkanState.m_VmaAllocator, m_Alloc, offset, data, size))
190 }
191
192#else
193
194 if (!m_LocalMemory) { Map(); }
195
196 /**
197 * @brief Use memcpy copy data.
198 */
199 if (size == VK_WHOLE_SIZE)
200 {
201 memcpy(data, m_LocalMemory, m_DeviceSize);
202 }
203 else {
204 char* memOffset = static_cast<char*>(m_LocalMemory);
205 memOffset += offset;
206 memcpy(data, memOffset, size);
207 }
208
209#endif
210
211 }
212
213 void VulkanBuffer::Flush(VkDeviceSize size, VkDeviceSize offset) const
214 {
216
218
219 /**
220 * @brief Flush memory to update buffer's data.
221 */
222 VK_CHECK(vmaFlushAllocation(m_VulkanState.m_VmaAllocator, m_Alloc, offset, size))
223
224#else
225
226 /**
227 * @brief VkMappedMemoryRange.
228 */
229 VkMappedMemoryRange mappedRange {};
230 mappedRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
231 mappedRange.memory = m_BufferMemory;
232 mappedRange.offset = offset;
233 mappedRange.size = size;
234
235 /**
236 * @brief Flush memory to update buffer's data.
237 */
238 VK_CHECK(vkFlushMappedMemoryRanges(m_VulkanState.m_Device, 1, &mappedRange))
239
240#endif
241
242 }
243
245 VulkanState& vulkanState ,
246 const std::string& name ,
247 VkDeviceSize size ,
248 VkBufferUsageFlags usage ,
249 VkMemoryPropertyFlags properties
250 )
251 {
253
254 m_Name = name;
255 m_DeviceSize = size;
256 m_Usage = usage;
257 m_Flags = properties;
258
259 /**
260 * @brief Instance a VkBufferCreateInfo.
261 */
262 VkBufferCreateInfo bufferInfo{};
263 bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
264 bufferInfo.size = size;
265 bufferInfo.usage = usage;
266 bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
267
269
270 /**
271 * @brief Instance a VmaAllocationCreateInfo.
272 */
273 VmaAllocationCreateInfo allocInfo{};
274 allocInfo.usage = VMA_MEMORY_USAGE_AUTO;
275
276 if (properties & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
277 {
278 allocInfo.flags |= VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
279 }
280
281 if (properties & VMA_MEMORY_PROPERTY_DEDICATED_MEMORY_BIT)
282 {
283 allocInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
284 }
285
286 /**
287 * @brief Create a Buffer.
288 */
289 VK_CHECK(vmaCreateBuffer(vulkanState.m_VmaAllocator, &bufferInfo, &allocInfo, &m_Buffer, &m_Alloc, nullptr))
290 DEBUGUTILS_SETOBJECTNAME(VK_OBJECT_TYPE_BUFFER, (uint64_t)m_Buffer, vulkanState.m_Device, name)
291
292 if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
293 {
294 /**
295 * @brief Instance a VkBufferDeviceAddressInfo.
296 */
297 VkBufferDeviceAddressInfo info {};
298 info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
299 info.buffer = m_Buffer;
300
301 /**
302 * @brief Get Address and return it.
303 */
304 m_BufferAddress = vkGetBufferDeviceAddress(m_VulkanState.m_Device, &info);
305 }
306
307#else
308
309 /**
310 * @brief Create a Buffer.
311 */
312 VK_CHECK(vkCreateBuffer(vulkanState.m_Device, &bufferInfo, nullptr, &m_Buffer));
313 DEBUGUTILS_SETOBJECTNAME(VK_OBJECT_TYPE_BUFFER, (uint64_t)m_Buffer, vulkanState.m_Device, "Buffer")
314
315 /**
316 * @brief Get Buffer Memory Requirements.
317 */
318 VkMemoryDedicatedRequirements dedicatedRegs{};
319 dedicatedRegs.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
320
321 VkMemoryRequirements2 memReqs{};
322 memReqs.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
323 memReqs.pNext = &dedicatedRegs;
324
325 VkBufferMemoryRequirementsInfo2 bufferReqs{};
326 bufferReqs.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2;
327 bufferReqs.buffer = m_Buffer;
328
329 vkGetBufferMemoryRequirements2(m_VulkanState.m_Device, &bufferReqs, &memReqs);
330
331 /**
332 * @brief Instance a VkMemoryAllocateInfo.
333 */
334 VkMemoryAllocateInfo allocInfo{};
335 allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
336 allocInfo.allocationSize = memReqs.memoryRequirements.size;
337
338 /**
339 * @brief Allow Buffer Device Address
340 */
341 VkMemoryAllocateFlagsInfoKHR flagsInfo{};
342 flagsInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR;
343 flagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
344
345 if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
346 {
347 allocInfo.pNext = &flagsInfo;
348 }
349
350 /**
351 * @brief Get video memory Properties.
352 */
353 VkPhysicalDeviceMemoryProperties memProperties{};
354 vkGetPhysicalDeviceMemoryProperties(vulkanState.m_PhysicalDevice, &memProperties);
355
356 /**
357 * @brief Find a suitable memory block.
358 */
359 for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++)
360 {
361 if (memReqs.memoryRequirements.memoryTypeBits & (1 << i) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties)
362 {
363 allocInfo.memoryTypeIndex = i;
364 break;
365 }
366 }
367
368 /**
369 * @brief Allocate video memory and bind it.
370 */
371 VK_CHECK(vkAllocateMemory(vulkanState.m_Device, &allocInfo, nullptr, &m_BufferMemory));
372 VK_CHECK(vkBindBufferMemory(vulkanState.m_Device, m_Buffer, m_BufferMemory, 0));
373
374 if (usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
375 {
376 /**
377 * @brief Instance a VkBufferDeviceAddressInfo.
378 */
379 VkBufferDeviceAddressInfo info {};
380 info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
381 info.buffer = m_Buffer;
382
383 /**
384 * @brief Get Address and return it.
385 */
386 m_BufferAddress = vkGetBufferDeviceAddress(m_VulkanState.m_Device, &info);
387 }
388
389#endif
390
391 }
392}
#define SPICES_PROFILE_ZONE
#define VMA_ALLOCATOR
Use VMA for memory allocate.
Definition VulkanUtils.h:27
#define VK_CHECK(expr)
Vulkan Check macro. Verify Vulkan API Effectiveness.
Definition VulkanUtils.h:68
void CreateBuffer(VulkanState &vulkanState, const std::string &name, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties)
Create a buffer.
VulkanBuffer(VulkanState &vulkanState, const std::string &name, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties)
Constructor Function. Create VkBuffer.
void CopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size)
Copy data from a buffer to another.
void WriteToBuffer(const void *data, VkDeviceSize size=VK_WHOLE_SIZE, VkDeviceSize offset=0)
Write data to buffer.
VkDeviceAddress & GetAddress()
Get VkBuffer Address.
void Map(VkDeviceSize size=VK_WHOLE_SIZE, VkDeviceSize offset=0)
Map buffer video memory to a local memory.
void WriteFromBuffer(void *data, VkDeviceSize size=VK_WHOLE_SIZE, VkDeviceSize offset=0)
Write data from buffer.
VkDescriptorBufferInfo * GetBufferInfo(VkDeviceSize size=VK_WHOLE_SIZE, VkDeviceSize offset=0)
Get VkDescriptorBufferInfo.
virtual ~VulkanBuffer() override
Destructor Function.
std::string m_Name
Buffer Name.
void Flush(VkDeviceSize size=VK_WHOLE_SIZE, VkDeviceSize offset=0) const
Flush the buffer's video memory data.
This Class is a Wrapper of VulkanBuffer.
VulkanCommandBuffer Class. This class defines the VulkanCommandBuffer behaves. This class is just a w...
VulkanState & m_VulkanState
The global VulkanState Referenced from VulkanRenderBackend.
VulkanObject(VulkanState &vulkanState)
Constructor Function. Init member variables.
VulkanObject Class. This class defines the basic behaves of VulkanObject. When we create an new Vulka...
This struct contains all Vulkan object in used global.
Definition VulkanUtils.h:74