diff --git a/include/vulkan/basalt_buffer.h b/include/vulkan/basalt_buffer.h new file mode 100644 index 0000000..79ac4b8 --- /dev/null +++ b/include/vulkan/basalt_buffer.h @@ -0,0 +1,23 @@ +#pragma once +#include "vulkan/basalt_pipeline.h" + +namespace basalt +{ + class Buffer + { + public: + Buffer(basalt::Device& device, u64 num_bytes, VkBufferUsageFlagBits usage_flags, + VkMemoryPropertyFlags props= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + VkSharingMode sharing_mode = VK_SHARING_MODE_EXCLUSIVE); + ~Buffer(); + + void* map (); + void unmap (); + + void* mapped_ptr; + VkBuffer buffer; + VkDeviceMemory memory; + basalt::Device* device; + size_t size = 0; + }; +} \ No newline at end of file diff --git a/src/vulkan/basalt_buffer.cpp b/src/vulkan/basalt_buffer.cpp new file mode 100644 index 0000000..d83eba9 --- /dev/null +++ b/src/vulkan/basalt_buffer.cpp @@ -0,0 +1,65 @@ +#include "vulkan/basalt_buffer.h" + +u32 find_memory_type(basalt::Device* device, u32 type_filter, VkMemoryPropertyFlags props); + +basalt::Buffer::Buffer(basalt::Device& device, u64 num_bytes, VkBufferUsageFlagBits usage_flags, VkMemoryPropertyFlags props, VkSharingMode sharing_mode) : + device(&device), mapped_ptr(nullptr), size(num_bytes) +{ + VkBufferCreateInfo buffer_info{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + buffer_info.pNext = VK_NULL_HANDLE; + buffer_info.flags = 0; + buffer_info.sharingMode = sharing_mode; + buffer_info.usage = usage_flags; + buffer_info.size = num_bytes; + + VkResult err = VK_SUCCESS; + VK_ASSERT(vkCreateBuffer(device, &buffer_info, device.ctx->vk_alloc, &buffer), "Failed to create buffer\n\tAt %s:%d\n\tError %s\n"); + + VkMemoryRequirements mem_reqs; + vkGetBufferMemoryRequirements(device, buffer, &mem_reqs); + // Determine best device allocation region + u32 mem_type = find_memory_type(&device, mem_reqs.memoryTypeBits, props); + BASSERT_FATAL(mem_type != -1, "Assertion %s failed at %s:%d\n\tFailed to find a memory region that supports the requested type and properties\n"); + + // Allocate the memory + VkMemoryAllocateInfo alloc_info{VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO}; + alloc_info.pNext = VK_NULL_HANDLE; + alloc_info.allocationSize = mem_reqs.size; + alloc_info.memoryTypeIndex = mem_type; + VK_ASSERT(vkAllocateMemory(device, &alloc_info, device.ctx->vk_alloc, &memory), "Failed to allocate memory for buffer\n\tAt %s:%d\n\tError %s\n"); + VK_ASSERT(vkBindBufferMemory(device, buffer, memory, 0), "Failed to bind memory for buffer\n\tAt %s:%d\n\tError %s\n"); +} + +basalt::Buffer::~Buffer() +{ + vkDestroyBuffer(device->logical, buffer, device->ctx->vk_alloc); + vkFreeMemory(device->logical, memory, device->ctx->vk_alloc); +} + +void* basalt::Buffer::map() +{ + if (this->mapped_ptr != nullptr) + return this->mapped_ptr; + VkResult err = vkMapMemory(device->logical, memory, 0, size, 0, &mapped_ptr); + BASSERT_ERROR(err == VK_SUCCESS, this->mapped_ptr = nullptr;, "Failed to map buffer to host memory\n\tAt %s:%d\n\tError %s\n"); + return this->mapped_ptr; +} + +void basalt::Buffer::unmap() +{ + vkUnmapMemory(device->logical, memory); + this->mapped_ptr = nullptr; +} + + +u32 find_memory_type(basalt::Device* device, u32 type_filter, VkMemoryPropertyFlags props) +{ + VkPhysicalDeviceMemoryProperties& dev_props = device->phys->memory_props; + for (u32 i = 0; i < dev_props.memoryTypeCount; ++i) + { + if ((type_filter & (1 << i))&& + (dev_props.memoryTypes[i].propertyFlags & props) == props) + return i; + } + return -1; +} \ No newline at end of file