Добавил UniformBuffer. Это умный указатель на память в GPU, но он так же берёт на себя задачу выделения памяти

This commit is contained in:
Jiga228
2026-07-11 17:59:50 +07:00
parent c95aa557c2
commit 506776b6d6
6 changed files with 132 additions and 39 deletions
@@ -0,0 +1,81 @@
#pragma once
#include <memory>
#include <stdexcept>
#include <vulkan/vulkan_core.h>
#include "GPU_GarbageCollector.h"
#include "DeviceFunctions/DeviceFunctions.hpp"
#include "VkObjects/Device.hpp"
#include "VkObjects/PhysicalDevice.hpp"
template <typename T>
class UniformBuffer
{
const VkObjects::Device& device_;
const VkObjects::PhysicalDevice& physical_device_;
size_t count_;
std::shared_ptr<GPU_GarbageCollector> gc_;
VkBuffer buffer_ = nullptr;
VkDeviceMemory device_memory_ = nullptr;
void* map_ = nullptr;
public:
explicit UniformBuffer( const VkObjects::Device& device,
const VkObjects::PhysicalDevice& physical_device,
const std::shared_ptr<GPU_GarbageCollector>& gc,
size_t count):
device_(device), physical_device_(physical_device), count_(count), gc_(gc)
{
const VkDeviceSize size = sizeof(T) * count;
buffer_ = DeviceFunctions::create_buffer(
device.get_native(),
size,
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
physical_device.get_unique_family_indices()
);
device_memory_ = DeviceFunctions::allocate_device_memory(
physical_device.get_native(),
device.get_native(),
buffer_,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
);
vkBindBufferMemory(device.get_native(), buffer_, device_memory_, 0);
vkMapMemory(device.get_native(), device_memory_, 0, size, 0, &map_);
}
virtual ~UniformBuffer()
{
if (device_memory_ != nullptr && map_ != nullptr)
{
vkUnmapMemory(device_.get_native(), device_memory_);
map_ = nullptr;
}
gc_->AddGarbage({buffer_, device_memory_});
}
operator T*() const
{
return map_;
}
operator void*() const
{
return map_;
}
operator VkBuffer() const
{
return buffer_;
}
T& operator[](size_t index)
{
if (index < count_)
return map_[index];
throw std::runtime_error("Index out of range!");
}
};
@@ -19,18 +19,10 @@ RENDER_ENGINE_FACTORY_GENERATE(UwURenderEngine)
void UwURenderEngine::create_uniform_buffers()
{
uniform_buffers_.resize(swapchain_.get_images().size());
uniform_buffers_memory_.resize(swapchain_.get_images().size());
uniform_buffers_mapped_.resize(swapchain_.get_images().size());
std::vector<uint32_t> arr_indices = physical_device_.get_unique_family_indices();
for (size_t i = 0; i < swapchain_.get_images().size(); ++i)
{
constexpr VkDeviceSize size = sizeof(UniformBufferObject);
uniform_buffers_[i] = DeviceFunctions::create_buffer(device_.get_native(), size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, arr_indices);
uniform_buffers_memory_[i] = DeviceFunctions::allocate_device_memory(physical_device_.get_native(), device_.get_native(), uniform_buffers_[i], VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
vkBindBufferMemory(device_.get_native(), uniform_buffers_[i], uniform_buffers_memory_[i], 0);
vkMapMemory(device_.get_native(), uniform_buffers_memory_[i], 0, size, 0, &uniform_buffers_mapped_[i]);
for (auto & i : uniform_buffers_)
{
i.reset(new UniformBuffer<UniformBufferObject>(device_, physical_device_, garbage_collector_, 1));
}
}
@@ -64,7 +56,7 @@ void UwURenderEngine::create_descriptor_sets()
for (size_t i = 0; i < swapchain_.get_images().size(); ++i)
{
VkDescriptorBufferInfo buffer_info{};
buffer_info.buffer = uniform_buffers_[i];
buffer_info.buffer = *uniform_buffers_[i];
buffer_info.offset = 0;
buffer_info.range = sizeof(UniformBufferObject);
@@ -282,7 +274,7 @@ void UwURenderEngine::update_uniform_buffer(uint32_t current_frame) const
ubo.view = glm::lookAt(eye, center, up);
ubo.proj = glm::perspective(glm::radians(45.0f), static_cast<float>(swapchain_.get_extent().width) / static_cast<float>(swapchain_.get_extent().height), 0.1f, 256.0f);
ubo.proj[1][1] *= -1;
memcpy(uniform_buffers_mapped_[current_frame], &ubo, sizeof(ubo));
memcpy(*uniform_buffers_[current_frame], &ubo, sizeof(ubo));
}
void UwURenderEngine::draw_frame()
@@ -341,6 +333,9 @@ render_pass_(device_, swapchain_),
layout_binding_(device_),
pipeline_(device_, swapchain_, render_pass_, layout_binding_)
{
garbage_collector_.reset(new GPU_GarbageCollector(device_.get_native()));
model_manager_.reset(new ModelManager(physical_device_.get_native(), device_.get_native()));
create_uniform_buffers();
create_descriptor_pool();
create_descriptor_sets();
@@ -350,9 +345,6 @@ pipeline_(device_, swapchain_, render_pass_, layout_binding_)
allocate_command_buffers();
allocate_index_buffer();
create_sync_objects();
garbage_collector_.reset(new GPU_GarbageCollector(device_.get_native()));
model_manager_.reset(new ModelManager(physical_device_.get_native(), device_.get_native()));
}
UwURenderEngine::~UwURenderEngine()
@@ -389,17 +381,11 @@ UwURenderEngine::~UwURenderEngine()
for (auto& i : framebuffers_)
vkDestroyFramebuffer(device_.get_native(), i, nullptr);
for (size_t i = 0; i < uniform_buffers_.size(); ++i)
{
vkUnmapMemory(device_.get_native(), uniform_buffers_memory_[i]);
vkFreeMemory(device_.get_native(), uniform_buffers_memory_[i], nullptr);
vkDestroyBuffer(device_.get_native(), uniform_buffers_[i], nullptr);
}
uniform_buffers_.clear();
uniform_buffers_memory_.clear();
uniform_buffers_mapped_.clear();
vkDestroyDescriptorPool(device_.get_native(), descriptor_pool_, nullptr);
garbage_collector_->FreeHeap();
}
void UwURenderEngine::start()
@@ -10,6 +10,7 @@
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include "UniformBuffer.hpp"
#include "VkObjects/DescriptorSetLayout.hpp"
#include "VkObjects/Device.hpp"
#include "VkObjects/Instance.hpp"
@@ -81,9 +82,7 @@ class UwURenderEngine final : public RenderEngineBase
VkDeviceMemory vertex_buffer_memory_ = VK_NULL_HANDLE;
VkBuffer index_buffer_ = VK_NULL_HANDLE;
VkDeviceMemory index_buffer_memory_ = VK_NULL_HANDLE;
std::vector<VkBuffer> uniform_buffers_;
std::vector<VkDeviceMemory> uniform_buffers_memory_;
std::vector<void*> uniform_buffers_mapped_;
std::vector<std::unique_ptr<UniformBuffer<UniformBufferObject>>> uniform_buffers_;
// Sync objects
std::vector<VkSemaphore> image_available_semaphores_, render_finished_semaphores_;