feat: Add Vulkan utility functions for buffer creation and memory management

This commit is contained in:
2026-01-04 14:07:13 +00:00
parent 11820a0c59
commit f1fe6dedfb
7 changed files with 154 additions and 79 deletions
+2 -73
View File
@@ -1,5 +1,6 @@
#include "buffer_service.hpp"
#include "../../logging/logger.hpp"
#include "../../core/vulkan_utils.hpp"
#include <cstring>
#include <stdexcept>
@@ -96,79 +97,7 @@ void BufferService::CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage,
auto device = deviceService_->GetDevice();
auto physicalDevice = deviceService_->GetPhysicalDevice();
logging::Logger::GetInstance().Debug("Creating buffer with size " + std::to_string(size) + " bytes");
// Validate buffer size
if (size == 0) {
logging::Logger::GetInstance().Error("Cannot create buffer with size 0");
throw std::runtime_error("Cannot create buffer with size 0");
}
// Check available memory before allocating
VkPhysicalDeviceMemoryProperties memProps;
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProps);
uint64_t totalAvailable = 0;
for (uint32_t i = 0; i < memProps.memoryHeapCount; ++i) {
if (memProps.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) {
totalAvailable += memProps.memoryHeaps[i].size;
}
}
if (size > totalAvailable) {
throw std::runtime_error("Requested buffer size (" +
std::to_string(size / (1024 * 1024)) + " MB) exceeds available GPU memory (" +
std::to_string(totalAvailable / (1024 * 1024)) + " MB)");
}
VkBufferCreateInfo bufferInfo{};
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = size;
bufferInfo.usage = usage;
bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VkResult createResult = vkCreateBuffer(device, &bufferInfo, nullptr, &buffer);
if (createResult != VK_SUCCESS) {
throw std::runtime_error("Failed to create buffer (error code: " +
std::to_string(createResult) + ", size: " +
std::to_string(size / 1024) + " KB)");
}
VkMemoryRequirements memRequirements;
vkGetBufferMemoryRequirements(device, buffer, &memRequirements);
VkMemoryAllocateInfo allocInfo{};
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
allocInfo.allocationSize = memRequirements.size;
try {
allocInfo.memoryTypeIndex =
deviceService_->FindMemoryType(memRequirements.memoryTypeBits, properties);
} catch (const std::exception& e) {
vkDestroyBuffer(device, buffer, nullptr);
throw std::runtime_error(std::string("Failed to find suitable memory type: ") + e.what());
}
VkResult allocResult = vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory);
if (allocResult != VK_SUCCESS) {
vkDestroyBuffer(device, buffer, nullptr);
std::string errorMsg = "Failed to allocate buffer memory.\n";
errorMsg += "Requested: " + std::to_string(memRequirements.size / (1024 * 1024)) + " MB\n";
errorMsg += "Error code: " + std::to_string(allocResult) + "\n";
if (allocResult == VK_ERROR_OUT_OF_DEVICE_MEMORY) {
errorMsg += "\nOut of GPU memory. Try:\n";
errorMsg += "- Closing other GPU-intensive applications\n";
errorMsg += "- Reducing window resolution\n";
errorMsg += "- Upgrading GPU or system memory";
} else if (allocResult == VK_ERROR_OUT_OF_HOST_MEMORY) {
errorMsg += "\nOut of system memory. Try:\n";
errorMsg += "- Closing other applications\n";
errorMsg += "- Adding more RAM to your system";
}
throw std::runtime_error(errorMsg);
}
vkBindBufferMemory(device, buffer, bufferMemory, 0);
vulkan::utils::CreateBuffer(device, physicalDevice, size, usage, properties, buffer, bufferMemory);
}
void BufferService::CleanupBuffers() {
+4 -3
View File
@@ -29,6 +29,10 @@ public:
size_t GetVertexCount() const override { return vertexCount_; }
size_t GetIndexCount() const override { return indexCount_; }
// Public buffer creation utility
void CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties,
VkBuffer& buffer, VkDeviceMemory& bufferMemory) override;
// IShutdownable interface
void Shutdown() noexcept override;
@@ -44,9 +48,6 @@ private:
size_t indexCount_ = 0;
// Helper methods
void CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage,
VkMemoryPropertyFlags properties,
VkBuffer& buffer, VkDeviceMemory& bufferMemory);
void CleanupBuffers();
};
@@ -65,6 +65,19 @@ public:
* @return Index count
*/
virtual size_t GetIndexCount() const = 0;
/**
* @brief Create a Vulkan buffer with memory allocation.
*
* @param size Buffer size in bytes
* @param usage Buffer usage flags
* @param properties Memory property flags
* @param[out] buffer Created buffer handle
* @param[out] bufferMemory Allocated memory handle
* @throws std::runtime_error if creation fails
*/
virtual void CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties,
VkBuffer& buffer, VkDeviceMemory& bufferMemory) = 0;
};
} // namespace sdl3cpp::services