kiba-engine
buffer.c
1 #include <kiba/renderer/vulkan/buffer.h>
2 
3 #include <kiba/renderer/vulkan/command_buffer.h>
4 
5 b8 vulkan_buffer_create(vulkan_context *context,
6  VkDeviceSize size,
7  VkBufferUsageFlags usage_flags,
8  VkMemoryPropertyFlags property_flags,
9  vulkan_buffer *buffer) {
10  VkBufferCreateInfo create_info = {
11  .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
12  .size = size,
13  .usage = usage_flags,
14  .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
15  };
16  VK_CALL_B8(
17  vkCreateBuffer(context->device.logical, &create_info, &context->alloc.vulkan_callbacks, &buffer->buffer));
18  VkMemoryRequirements memory_requirements;
19  vkGetBufferMemoryRequirements(context->device.logical, buffer->buffer, &memory_requirements);
20 
21  // coherent flag is used to ensure data is actually copied when we say so, alternative:
22  // call vkFlushMappedMemoryRanges before writing to mapped data
23  // call vkInvalidateMappedMemoryRanges before reading to mapped data
24  u32 type_index = vulkan_get_memory_type(context, memory_requirements.memoryTypeBits, property_flags);
25  if (type_index == U32_MAX) {
26  KB_ERROR("could not find memory type matching the buffers requirements");
27  return false;
28  }
29  VkMemoryAllocateInfo alloc_info = {
30  .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
31  .allocationSize = memory_requirements.size,
32  .memoryTypeIndex = type_index,
33  };
34  VK_CALL_B8(
35  vkAllocateMemory(context->device.logical, &alloc_info, &context->alloc.vulkan_callbacks, &buffer->memory));
36  VK_CALL_B8(vkBindBufferMemory(context->device.logical, buffer->buffer, buffer->memory, 0));
37  return true;
38 }
39 
40 b8 vulkan_buffer_copy(vulkan_context *context, vulkan_buffer *src, vulkan_buffer *dst, VkDeviceSize size) {
41  VkCommandBuffer command_buffer;
42  if (!vulkan_command_buffer_start_single_time_command(context, &command_buffer)) {
43  return false;
44  }
45  VkBufferCopy copy_info = {
46  .srcOffset = 0,
47  .dstOffset = 0,
48  .size = size,
49  };
50  vkCmdCopyBuffer(command_buffer, src->buffer, dst->buffer, 1, &copy_info);
51 
52  return vulkan_command_buffer_end_single_time_command(context, &command_buffer);
53 }
54 
55 void vulkan_buffer_destroy(vulkan_context *context, vulkan_buffer *buffer) {
56  vkDestroyBuffer(context->device.logical, buffer->buffer, &context->alloc.vulkan_callbacks);
57  vkFreeMemory(context->device.logical, buffer->memory, &context->alloc.vulkan_callbacks);
58 }
59 
60 u32 vulkan_get_memory_type(vulkan_context *context, u32 type_filter, VkMemoryPropertyFlags flags) {
61  VkPhysicalDeviceMemoryProperties memory_properties;
62  vkGetPhysicalDeviceMemoryProperties(context->device.physical, &memory_properties);
63  for (u32 i = 0; i < memory_properties.memoryTypeCount; ++i) {
64  if (type_filter & KB_UBIT(i) && KB_FLAGS_ALL_SET(memory_properties.memoryTypes[i].propertyFlags, flags)) {
65  return i;
66  }
67  }
68  return U32_MAX;
69 }
#define KB_UBIT(n)
Get unsigned value with the n-th bit set to 1. All other bits are 0.
Definition: defines.h:72
#define KB_FLAGS_ALL_SET(value, flags)
Check if all flags are set inside value.
Definition: defines.h:62
#define KB_ERROR(...)
Log entry with error log level.
Definition: log.h:142