From c2603b7cb75a07eb097c9752244c4e09aaa717a0 Mon Sep 17 00:00:00 2001 From: Varnill Date: Sun, 28 Sep 2025 23:51:03 +0300 Subject: [PATCH 1/4] refactor: Instance --- src/graphics/vulkan/vk_engine.cpp | 84 ++++++++++++------------- src/include/graphics/vulkan/vk_engine.h | 42 +++++++++++++ 2 files changed, 84 insertions(+), 42 deletions(-) diff --git a/src/graphics/vulkan/vk_engine.cpp b/src/graphics/vulkan/vk_engine.cpp index 99b94292..8ebaf0ee 100644 --- a/src/graphics/vulkan/vk_engine.cpp +++ b/src/graphics/vulkan/vk_engine.cpp @@ -35,7 +35,6 @@ #include "graphics/vulkan/vk_loader.h" #include "graphics/vulkan/vk_pipelines.h" #include "graphics/vulkan/vk_types.h" -#include "graphics/vulkan/vk_command_buffers.h" VulkanEngine* loadedEngine = nullptr; @@ -49,6 +48,28 @@ constexpr bool bUseValidationLayers = false; constexpr bool bUseValidationLayers = true; #endif +void VulkanEngine::Instance::init() { + vkb::InstanceBuilder builder; + auto inst_ret = builder.set_app_name("TODO: PUT APP NAME HERE") + .set_engine_name("rainsystem") + .request_validation_layers(bUseValidationLayers) + .set_debug_callback(debugCallback) + .require_api_version(1, 3, 0) + .build(); + if (!inst_ret) { + LOGE("Failed to create Vulkan instance. Error: {}", + inst_ret.error().message()); + } + _instance = inst_ret.value(); +} + +VulkanEngine::Instance::~Instance() { + vkb::destroy_instance(_instance); +} + +VulkanEngine::Instance::operator VkInstance() const { return _instance; } +VulkanEngine::Instance::operator vkb::Instance() const { return _instance; } + VKAPI_ATTR VkBool32 VKAPI_CALL VulkanEngine::debugCallback( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, @@ -217,6 +238,11 @@ void VulkanEngine::init_imgui() { VkDescriptorPool imguiPool; VK_CHECK(vkCreateDescriptorPool(_device, &pool_info, nullptr, &imguiPool)); + void VulkanEngine::Imgui::init(const VkDevice& dev, SDL_Window* w, + const VkInstance& pInstance, const VkPhysicalDevice& physicalDevice, + const VkQueue& queue, const VkFormat* format) { + _device = dev; + initImguiPool(); // 2: initialize imgui library // this initializes the core structures of imgui @@ -226,15 +252,14 @@ void VulkanEngine::init_imgui() { ImGui_ImplSDL2_InitForVulkan(_window); // this initializes imgui for Vulkan - ImGui_ImplVulkan_InitInfo init_info = {}; - init_info.Instance = _instance; - init_info.PhysicalDevice = _chosenGPU; - init_info.Device = _device; - init_info.Queue = _graphicsQueue; - init_info.DescriptorPool = imguiPool; - init_info.MinImageCount = 3; - init_info.ImageCount = 3; - init_info.UseDynamicRendering = true; + ImGui_ImplVulkan_InitInfo init_info = {.Instance = pInstance, + .PhysicalDevice = physicalDevice, + .Device = _device, + .Queue = queue, + .DescriptorPool = _imguiPool, + .MinImageCount = 3, + .ImageCount = 3, + .UseDynamicRendering = true}; // dynamic rendering parameters for imgui to use init_info.PipelineRenderingCreateInfo = { @@ -332,7 +357,7 @@ void VulkanEngine::init(SDL_Window* window) { command_buffers_container.init_sync_structures(this); init_descriptors(); init_pipelines(); - init_imgui(); + _imgui.init(getRawDevice(), _window.ptr, static_cast(instance), _chosenGPU, _graphicsQueue, &_swapchainImageFormat); init_default_data(); mainCamera->velocity = glm::vec3(0.f); @@ -371,28 +396,10 @@ void VulkanEngine::init_vulkan() { for (auto& [extensionName, _] : system_info.available_extensions) { LOGI(extensionName); } - - vkb::InstanceBuilder builder; - - auto inst_ret = builder.set_app_name("TODO: PUT APP NAME HERE") - .set_engine_name("rainsystem") - .request_validation_layers(bUseValidationLayers) - .set_debug_callback(debugCallback) - .require_api_version(1, 3, 0) - .build(); - - if (!inst_ret) { - LOGE("Failed to create Vulkan instance. Error: {}", - inst_ret.error().message()); - } - - vkb::Instance vkb_inst = inst_ret.value(); - // grab the instance - _instance = vkb_inst.instance; - _debug_messenger = vkb_inst.debug_messenger; + instance.init(); - SDL_bool err = SDL_Vulkan_CreateSurface(_window, _instance, &_surface); + SDL_bool err = SDL_Vulkan_CreateSurface(_window.ptr, static_cast(instance), &_surface); if (!err) { LOGE("Failed to create Vulkan surface. Error: {}", SDL_GetError()); } @@ -410,7 +417,7 @@ void VulkanEngine::init_vulkan() { // use vkbootstrap to select a gpu. // We want a gpu that can write to the SDL surface and supports vulkan 1.3 // with the correct features - vkb::PhysicalDeviceSelector selector{vkb_inst}; + vkb::PhysicalDeviceSelector selector{static_cast(instance)}; auto physical_device_ret = selector.set_minimum_version(1, 3) .set_required_features_13(features) @@ -458,8 +465,8 @@ void VulkanEngine::init_vulkan() { // initialize the memory allocator VmaAllocatorCreateInfo allocatorInfo = {}; allocatorInfo.physicalDevice = _chosenGPU; - allocatorInfo.device = _device; - allocatorInfo.instance = _instance; + allocatorInfo.device = getRawDevice(); + allocatorInfo.instance = static_cast(instance); allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; vmaCreateAllocator(&allocatorInfo, &_allocator); @@ -611,14 +618,7 @@ void VulkanEngine::cleanup() { destroy_swapchain(); - vkDestroySurfaceKHR(_instance, _surface, nullptr); - vkDestroyDevice(_device, nullptr); - - vkb::destroy_debug_utils_messenger(_instance, _debug_messenger); - vkDestroyInstance(_instance, nullptr); - - // VMA allocator cleanup - vmaDestroyAllocator(_allocator); + vkDestroySurfaceKHR(static_cast(instance), _surface, nullptr); } // clear engine pointer diff --git a/src/include/graphics/vulkan/vk_engine.h b/src/include/graphics/vulkan/vk_engine.h index 40db0c65..c6e48c28 100644 --- a/src/include/graphics/vulkan/vk_engine.h +++ b/src/include/graphics/vulkan/vk_engine.h @@ -64,6 +64,37 @@ struct DrawContext { class VulkanEngine { public: + struct Instance { + explicit operator VkInstance() const; + explicit operator vkb::Instance() const; + void init(); + ~Instance(); + private: + vkb::Instance _instance; + }; + Instance instance; + + struct Device { + vkb::Device device; + void init(const vkb::PhysicalDevice& physical_device) { + const vkb::DeviceBuilder device_builder{physical_device}; + auto dev_ret = device_builder.build(); + if (!dev_ret) { + LOGE("Failed to create logical device. Error: {}", + dev_ret.error().message()); + } + device = dev_ret.value(); + } + ~Device() {vkb::destroy_device(device);} + }; + Device _device; + VkDevice getRawDevice() const { return _device.device; } + struct Allocator { + VmaAllocator _allocator{nullptr}; + void init(VmaAllocatorCreateInfo info) {vmaCreateAllocator(&info, &_allocator);} // move info inside + ~Allocator() {vmaDestroyAllocator(_allocator);} + }; + Allocator _a; // todo: rename Pipelines pipelines; @@ -181,6 +212,17 @@ class VulkanEngine { VmaMemoryUsage memoryUsage) const; private: + struct Imgui { + void init(const VkDevice& dev, SDL_Window* w, + const VkInstance& pInstance, const VkPhysicalDevice& physicalDevice, + const VkQueue& queue, const VkFormat* format); + ~Imgui(); + private: + void initImguiPool(); + VkDevice _device{nullptr}; + VkDescriptorPool _imguiPool{nullptr}; + }; + Imgui _imgui; // Smart pointer collections for automatic cleanup std::vector> _managedBuffers; std::vector> _managedImages; From 7d725639b50e363a1c96bde1297f847bc01219dc Mon Sep 17 00:00:00 2001 From: Varnill Date: Sun, 28 Sep 2025 23:52:50 +0300 Subject: [PATCH 2/4] refactor: Device --- src/graphics/vulkan/pipelines.cpp | 27 ++-- src/graphics/vulkan/vk_command_buffers.cpp | 16 +-- .../vulkan/vk_command_buffers_container.cpp | 18 +-- src/graphics/vulkan/vk_engine.cpp | 120 +++++++++--------- src/graphics/vulkan/vk_loader.cpp | 26 +++- src/include/graphics/vulkan/vk_engine.h | 21 ++- 6 files changed, 121 insertions(+), 107 deletions(-) diff --git a/src/graphics/vulkan/pipelines.cpp b/src/graphics/vulkan/pipelines.cpp index 5926226b..e1c44df7 100644 --- a/src/graphics/vulkan/pipelines.cpp +++ b/src/graphics/vulkan/pipelines.cpp @@ -9,7 +9,7 @@ void GLTFMetallic_Roughness::build_pipelines(VulkanEngine* engine) { create_material_layout(engine); VkPipelineLayout newLayout = create_pipeline_layout(engine); - + device = static_cast(engine->device); opaquePipeline.layout = newLayout; transparentPipeline.layout = newLayout; @@ -17,15 +17,15 @@ void GLTFMetallic_Roughness::build_pipelines(VulkanEngine* engine) { build_transparent_pipeline(engine, meshVertexShader, meshFragShader, newLayout); - vkDestroyShaderModule(engine->_device, meshFragShader, nullptr); - vkDestroyShaderModule(engine->_device, meshVertexShader, nullptr); + vkDestroyShaderModule(static_cast(engine->device), meshFragShader, nullptr); + vkDestroyShaderModule(static_cast(engine->device), meshVertexShader, nullptr); } VkShaderModule GLTFMetallic_Roughness::load_shader(VulkanEngine* engine, const char* relative_path, const char* type) { VkShaderModule shaderModule; - if (!vkutil::load_shader_module(relative_path, engine->_device, + if (!vkutil::load_shader_module(relative_path, static_cast(engine->device), &shaderModule)) { fmt::println("Error when building the {} shader module", type); } @@ -33,14 +33,11 @@ VkShaderModule GLTFMetallic_Roughness::load_shader(VulkanEngine* engine, } void GLTFMetallic_Roughness::create_material_layout(VulkanEngine* engine) { - DescriptorLayoutBuilder layoutBuilder; - layoutBuilder.add_binding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - layoutBuilder.add_binding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); - layoutBuilder.add_binding(2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); - - materialLayout = layoutBuilder.build( - engine->_device, - VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); + materialLayout.create(static_cast(engine->device), + VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, + {{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER}, + {1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}, + {2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}}); } VkPipelineLayout GLTFMetallic_Roughness::create_pipeline_layout( @@ -60,7 +57,7 @@ VkPipelineLayout GLTFMetallic_Roughness::create_pipeline_layout( mesh_layout_info.pushConstantRangeCount = 1; VkPipelineLayout newLayout; - VK_CHECK(vkCreatePipelineLayout(engine->_device, &mesh_layout_info, nullptr, + VK_CHECK(vkCreatePipelineLayout(static_cast(engine->device), &mesh_layout_info, nullptr, &newLayout)); return newLayout; @@ -82,7 +79,7 @@ void GLTFMetallic_Roughness::build_opaque_pipeline(VulkanEngine* engine, pipelineBuilder.set_depth_format(engine->_depthImage->get().imageFormat); pipelineBuilder._pipelineLayout = layout; - opaquePipeline.pipeline = pipelineBuilder.build_pipeline(engine->_device); + opaquePipeline.pipeline = pipelineBuilder.build_pipeline(static_cast(engine->device)); } void GLTFMetallic_Roughness::build_transparent_pipeline( @@ -95,7 +92,7 @@ void GLTFMetallic_Roughness::build_transparent_pipeline( pipelineBuilder._pipelineLayout = layout; transparentPipeline.pipeline = - pipelineBuilder.build_pipeline(engine->_device); + pipelineBuilder.build_pipeline(static_cast(engine->device)); } MaterialInstance GLTFMetallic_Roughness::write_material( diff --git a/src/graphics/vulkan/vk_command_buffers.cpp b/src/graphics/vulkan/vk_command_buffers.cpp index 9114b9ed..cee68e8e 100644 --- a/src/graphics/vulkan/vk_command_buffers.cpp +++ b/src/graphics/vulkan/vk_command_buffers.cpp @@ -13,31 +13,31 @@ void CommandBuffers::init_commands(VulkanEngine* vk_engine) { for (auto& _frame : vk_engine->command_buffers_container._frames) { VkCommandPool commandPool; - VK_CHECK(vkCreateCommandPool(vk_engine->_device, &commandPoolInfo, + VK_CHECK(vkCreateCommandPool(static_cast(vk_engine->device), &commandPoolInfo, nullptr, &commandPool)); - _frame._commandPool = std::make_unique(vk_engine->_device, commandPool); + _frame._commandPool = std::make_unique(static_cast(vk_engine->device), commandPool); // allocate the default command buffer that we will use for rendering VkCommandBufferAllocateInfo cmdAllocInfo = vkinit::command_buffer_allocate_info(_frame._commandPool->get(), 1); - VK_CHECK(vkAllocateCommandBuffers(vk_engine->_device, &cmdAllocInfo, + VK_CHECK(vkAllocateCommandBuffers(static_cast(vk_engine->device), &cmdAllocInfo, &_frame._mainCommandBuffer)); } VkCommandPool immCommandPool; - VK_CHECK(vkCreateCommandPool(vk_engine->_device, &commandPoolInfo, nullptr, + VK_CHECK(vkCreateCommandPool(static_cast(vk_engine->device), &commandPoolInfo, nullptr, &immCommandPool)); - vk_engine->command_buffers_container._immCommandPool = std::make_unique(vk_engine->_device, immCommandPool); + vk_engine->command_buffers_container._immCommandPool = std::make_unique(static_cast(vk_engine->device), immCommandPool); // allocate the command buffer for immediate submits const VkCommandBufferAllocateInfo cmdAllocInfo = vkinit::command_buffer_allocate_info(vk_engine->command_buffers_container._immCommandPool->get(), 1); - VK_CHECK(vkAllocateCommandBuffers(vk_engine->_device, &cmdAllocInfo, + VK_CHECK(vkAllocateCommandBuffers(static_cast(vk_engine->device), &cmdAllocInfo, &(vk_engine->command_buffers_container._immCommandBuffer))); // Smart pointer will automatically handle cleanup - no need for deletion queue @@ -46,7 +46,7 @@ void CommandBuffers::init_commands(VulkanEngine* vk_engine) { void CommandBuffers::immediate_submit( std::function&& function, VulkanEngine* vk_engine) const { - VK_CHECK(vkResetFences(vk_engine->_device, 1, vk_engine->command_buffers_container._immFence->getPtr())); + VK_CHECK(vkResetFences(static_cast(vk_engine->device), 1, vk_engine->command_buffers_container._immFence->getPtr())); VK_CHECK(vkResetCommandBuffer(vk_engine->command_buffers_container._immCommandBuffer, 0)); const VkCommandBuffer cmd = vk_engine->command_buffers_container._immCommandBuffer; @@ -71,6 +71,6 @@ void CommandBuffers::immediate_submit( VK_CHECK(vkQueueSubmit2(vk_engine->_graphicsQueue, 1, &submit, vk_engine->command_buffers_container._immFence->get())); - VK_CHECK(vkWaitForFences(vk_engine->_device, 1, vk_engine->command_buffers_container._immFence->getPtr(), true, + VK_CHECK(vkWaitForFences(static_cast(vk_engine->device), 1, vk_engine->command_buffers_container._immFence->getPtr(), true, 9999999999)); } diff --git a/src/graphics/vulkan/vk_command_buffers_container.cpp b/src/graphics/vulkan/vk_command_buffers_container.cpp index c1abcc6c..85137f11 100644 --- a/src/graphics/vulkan/vk_command_buffers_container.cpp +++ b/src/graphics/vulkan/vk_command_buffers_container.cpp @@ -15,18 +15,18 @@ void CommandBuffersContainer::init_sync_structures(VulkanEngine* vk_engine) { for (auto& _frame : _frames) { VkFence renderFence; - VK_CHECK(vkCreateFence(vk_engine->_device, &fenceCreateInfo, nullptr, &renderFence)); - _frame._renderFence = std::make_unique(vk_engine->_device, renderFence); + VK_CHECK(vkCreateFence(static_cast(vk_engine->device), &fenceCreateInfo, nullptr, &renderFence)); + _frame._renderFence = std::make_unique(static_cast(vk_engine->device), renderFence); VkSemaphore swapchainSemaphore, renderSemaphore; - VK_CHECK(vkCreateSemaphore(vk_engine->_device, &semaphoreCreateInfo, nullptr, &swapchainSemaphore)); - VK_CHECK(vkCreateSemaphore(vk_engine->_device, &semaphoreCreateInfo, nullptr, &renderSemaphore)); - - _frame._swapchainSemaphore = std::make_unique(vk_engine->_device, swapchainSemaphore); - _frame._renderSemaphore = std::make_unique(vk_engine->_device, renderSemaphore); + VK_CHECK(vkCreateSemaphore(static_cast(vk_engine->device), &semaphoreCreateInfo, nullptr, &swapchainSemaphore)); + VK_CHECK(vkCreateSemaphore(static_cast(vk_engine->device), &semaphoreCreateInfo, nullptr, &renderSemaphore)); + + _frame._swapchainSemaphore = std::make_unique(static_cast(vk_engine->device), swapchainSemaphore); + _frame._renderSemaphore = std::make_unique(static_cast(vk_engine->device), renderSemaphore); } VkFence immFence; - VK_CHECK(vkCreateFence(vk_engine->_device, &fenceCreateInfo, nullptr, &immFence)); - _immFence = std::make_unique(vk_engine->_device, immFence); + VK_CHECK(vkCreateFence(static_cast(vk_engine->device), &fenceCreateInfo, nullptr, &immFence)); + _immFence = std::make_unique(static_cast(vk_engine->device), immFence); } \ No newline at end of file diff --git a/src/graphics/vulkan/vk_engine.cpp b/src/graphics/vulkan/vk_engine.cpp index 8ebaf0ee..aa2b728c 100644 --- a/src/graphics/vulkan/vk_engine.cpp +++ b/src/graphics/vulkan/vk_engine.cpp @@ -70,6 +70,21 @@ VulkanEngine::Instance::~Instance() { VulkanEngine::Instance::operator VkInstance() const { return _instance; } VulkanEngine::Instance::operator vkb::Instance() const { return _instance; } +void VulkanEngine::Device::init(const vkb::PhysicalDevice& physical_device) { + const vkb::DeviceBuilder device_builder{physical_device}; + auto dev_ret = device_builder.build(); + if (!dev_ret) { + LOGE("Failed to create logical device. Error: {}", + dev_ret.error().message()); + } + _device = dev_ret.value(); +} + +VulkanEngine::Device::~Device() {vkb::destroy_device(_device);} + +VulkanEngine::Device::operator VkDevice() const { return _device; } +VulkanEngine::Device::operator vkb::Device() const { return _device; } + VKAPI_ATTR VkBool32 VKAPI_CALL VulkanEngine::debugCallback( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, @@ -119,6 +134,11 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanEngine::debugCallback( return VK_FALSE; } +void VulkanEngine::destroy_image(const AllocatedImage& img) const { + vkDestroyImageView(static_cast(device), img.imageView, nullptr); + vmaDestroyImage(_a._allocator, img.image, img.allocation); +} + void VulkanEngine::init_default_data() { std::array rect_vertices{}; @@ -145,17 +165,17 @@ void VulkanEngine::init_default_data() { const uint32_t white = glm::packUnorm4x8(glm::vec4(1, 1, 1, 1)); AllocatedImage whiteImageData = create_image(&white, VkExtent3D{1, 1, 1}, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT); - _whiteImage = std::make_unique(_allocator, _device, whiteImageData); + _whiteImage = std::make_unique(_a._allocator, static_cast(device), whiteImageData); const uint32_t grey = glm::packUnorm4x8(glm::vec4(0.66f, 0.66f, 0.66f, 1)); AllocatedImage greyImageData = create_image(&grey, VkExtent3D{1, 1, 1}, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT); - _greyImage = std::make_unique(_allocator, _device, greyImageData); + _greyImage = std::make_unique(_a._allocator, static_cast(device), greyImageData); const uint32_t black = glm::packUnorm4x8(glm::vec4(0, 0, 0, 0)); AllocatedImage blackImageData = create_image(&black, VkExtent3D{1, 1, 1}, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT); - _blackImage = std::make_unique(_allocator, _device, blackImageData); + _blackImage = std::make_unique(_a._allocator, static_cast(device), blackImageData); // checkerboard image const uint32_t magenta = glm::packUnorm4x8(glm::vec4(1, 0, 1, 1)); @@ -167,19 +187,18 @@ void VulkanEngine::init_default_data() { } AllocatedImage errorImageData = create_image(pixels.data(), VkExtent3D{16, 16, 1}, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT); - _errorCheckerboardImage = std::make_unique(_allocator, _device, errorImageData); + _errorCheckerboardImage = std::make_unique(_a._allocator, static_cast(device), errorImageData); VkSamplerCreateInfo sampl = {.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO}; sampl.magFilter = VK_FILTER_NEAREST; sampl.minFilter = VK_FILTER_NEAREST; - - vkCreateSampler(_device, &sampl, nullptr, &_defaultSamplerNearest); + _defaultSamplerNearest.create(static_cast(device), &sampl, nullptr); sampl.magFilter = VK_FILTER_LINEAR; sampl.minFilter = VK_FILTER_LINEAR; - vkCreateSampler(_device, &sampl, nullptr, &_defaultSamplerLinear); + _defaultSamplerLinear.create(static_cast(device), &sampl, nullptr); GLTFMetallic_Roughness::MaterialResources materialResources{}; // default the material textures @@ -285,41 +304,23 @@ void VulkanEngine::init_descriptors() { {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1}, {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1}}; - globalDescriptorAllocator.init(_device, 10, sizes); + globalDescriptorAllocator.init(static_cast(device), 10, sizes); // make the descriptor set layout for our compute draw - { - DescriptorLayoutBuilder builder; - builder.add_binding(0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); - _drawImageDescriptorLayout = - builder.build(_device, VK_SHADER_STAGE_COMPUTE_BIT); - } - - { - DescriptorLayoutBuilder builder; - builder.add_binding(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - _gpuSceneDataDescriptorLayout = - builder.build(_device, VK_SHADER_STAGE_VERTEX_BIT | - VK_SHADER_STAGE_FRAGMENT_BIT); - } - - { - DescriptorLayoutBuilder builder; - builder.add_binding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); - _singleImageDescriptorLayout = - builder.build(_device, VK_SHADER_STAGE_FRAGMENT_BIT); - } + _drawImageDescriptorLayout.create(static_cast(device), VK_SHADER_STAGE_COMPUTE_BIT, {{0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE}}); + _gpuSceneDataDescriptorLayout.create(static_cast(device), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, {{0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER}}); + _singleImageDescriptorLayout.create(static_cast(device), VK_SHADER_STAGE_FRAGMENT_BIT, {{0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER}}); // allocate a descriptor set for our draw image _drawImageDescriptors = globalDescriptorAllocator.allocate( - _device, _drawImageDescriptorLayout); + static_cast(device), _drawImageDescriptorLayout.set); DescriptorWriter writer; writer.write_image(0, _drawImage->imageView(), VK_NULL_HANDLE, VK_IMAGE_LAYOUT_GENERAL, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE); - writer.update_set(_device, _drawImageDescriptors); + writer.update_set(static_cast(device), _drawImageDescriptors); for (auto& _frame : command_buffers_container._frames) { // create a descriptor pool @@ -331,14 +332,14 @@ void VulkanEngine::init_descriptors() { }; _frame._frameDescriptors = DescriptorAllocatorGrowable{}; - _frame._frameDescriptors.init(_device, 1000, frame_sizes); + _frame._frameDescriptors.init(static_cast(device), 1000, frame_sizes); // No need for deletion queue - frame descriptors will be cleaned up in cleanup() } } void VulkanEngine::init_pipelines() { - pipelines.init(_device, _singleImageDescriptorLayout, _drawImageDescriptorLayout, _drawImage->get()); + pipelines.init(static_cast(device), _singleImageDescriptorLayout.set, _drawImageDescriptorLayout.set, _drawImage->get()); // Pipeline cleanup is handled automatically by the Pipelines object metalRoughMaterial.build_pipelines(this); } @@ -357,7 +358,7 @@ void VulkanEngine::init(SDL_Window* window) { command_buffers_container.init_sync_structures(this); init_descriptors(); init_pipelines(); - _imgui.init(getRawDevice(), _window.ptr, static_cast(instance), _chosenGPU, _graphicsQueue, &_swapchainImageFormat); + _imgui.init(static_cast(device), _window.ptr, static_cast(instance), _chosenGPU, _graphicsQueue, &_swapchainImageFormat); init_default_data(); mainCamera->velocity = glm::vec3(0.f); @@ -443,10 +444,10 @@ void VulkanEngine::init_vulkan() { const vkb::Device& vkbDevice = dev_ret.value(); // Get the VkDevice handle used in the rest of a vulkan application - _device = vkbDevice.device; - _chosenGPU = physicalDevice.physical_device; + device.init(physical_device); + _chosenGPU = physical_device.physical_device; - auto queue_ret = vkbDevice.get_queue(vkb::QueueType::graphics); + auto queue_ret = static_cast(device).get_queue(vkb::QueueType::graphics); if (!queue_ret) { LOGE("Failed to retrieve graphics queue. Error: {}", queue_ret.error().message()); @@ -454,7 +455,7 @@ void VulkanEngine::init_vulkan() { _graphicsQueue = queue_ret.value(); - auto queue_family_ret = vkbDevice.get_queue_index(vkb::QueueType::graphics); + auto queue_family_ret = static_cast(device).get_queue_index(vkb::QueueType::graphics); if (!queue_family_ret) { LOGE("Failed to retrieve graphics queue family. Error: {}", queue_family_ret.error().message()); @@ -465,7 +466,7 @@ void VulkanEngine::init_vulkan() { // initialize the memory allocator VmaAllocatorCreateInfo allocatorInfo = {}; allocatorInfo.physicalDevice = _chosenGPU; - allocatorInfo.device = getRawDevice(); + allocatorInfo.device = static_cast(device); allocatorInfo.instance = static_cast(instance); allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; vmaCreateAllocator(&allocatorInfo, &_allocator); @@ -475,7 +476,7 @@ void VulkanEngine::init_vulkan() { void VulkanEngine::create_swapchain(uint32_t width, uint32_t height) { - vkb::SwapchainBuilder swapchainBuilder{_chosenGPU, _device, _surface}; + vkb::SwapchainBuilder swapchainBuilder{_chosenGPU, static_cast(device), _surface}; _swapchainImageFormat = VK_FORMAT_B8G8R8A8_UNORM; @@ -543,11 +544,11 @@ void VulkanEngine::init_swapchain() { drawImageFormat, drawImageData.image, VK_IMAGE_ASPECT_COLOR_BIT); - VK_CHECK(vkCreateImageView(_device, &rview_info, nullptr, + VK_CHECK(vkCreateImageView(static_cast(device), &rview_info, nullptr, &drawImageData.imageView)); // Create smart pointer for automatic cleanup - _drawImage = std::make_unique(_allocator, _device, drawImageData); + _drawImage = std::make_unique(_a._allocator, static_cast(device), drawImageData); // Create depth image VkExtent3D depthImageExtent = { @@ -580,26 +581,26 @@ void VulkanEngine::init_swapchain() { VkImageViewCreateInfo dview_info = vkinit::imageview_create_info( depthFormat, depthImageData.image, VK_IMAGE_ASPECT_DEPTH_BIT); - VK_CHECK(vkCreateImageView(_device, &dview_info, nullptr, + VK_CHECK(vkCreateImageView(static_cast(device), &dview_info, nullptr, &depthImageData.imageView)); // Create smart pointer for automatic cleanup - _depthImage = std::make_unique(_allocator, _device, depthImageData); + _depthImage = std::make_unique(_a._allocator, static_cast(device), depthImageData); } void VulkanEngine::destroy_swapchain() { - vkDestroySwapchainKHR(_device, _swapchain, nullptr); + vkDestroySwapchainKHR(static_cast(device), _swapchain, nullptr); // destroy swapchain resources for (const auto& _swapchainImageView : _swapchainImageViews) { - vkDestroyImageView(_device, _swapchainImageView, nullptr); + vkDestroyImageView(static_cast(device), _swapchainImageView, nullptr); } } void VulkanEngine::cleanup() { if (_isInitialized) { // make sure the gpu has stopped doing its things - vkDeviceWaitIdle(_device); + vkDeviceWaitIdle(static_cast(device)); loadedScenes.clear(); @@ -613,8 +614,9 @@ void VulkanEngine::cleanup() { } // Destroy frame descriptors manually - _frame._frameDescriptors.destroy_pools(_device); + _frame._frameDescriptors.destroy_pools(static_cast(device)); } + globalDescriptorAllocator.destroy_pools(static_cast(device)); destroy_swapchain(); @@ -673,7 +675,7 @@ GPUMeshBuffers VulkanEngine::uploadMesh(std::span indices, .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, .buffer = newSurface.vertexBuffer.buffer}; newSurface.vertexBufferAddress = - vkGetBufferDeviceAddress(_device, &deviceAddressInfo); + vkGetBufferDeviceAddress(static_cast(device), &deviceAddressInfo); // create index buffer newSurface.indexBuffer = create_buffer( @@ -766,12 +768,12 @@ void VulkanEngine::draw_geometry(VkCommandBuffer cmd) { // create a descriptor set that binds that buffer and update it VkDescriptorSet globalDescriptor = get_current_frame()._frameDescriptors.allocate( - _device, _gpuSceneDataDescriptorLayout); + static_cast(device), _gpuSceneDataDescriptorLayout.set); DescriptorWriter writer; writer.write_buffer(0, gpuSceneDataBuffer.buffer, sizeof(GPUSceneData), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER); - writer.update_set(_device, globalDescriptor); + writer.update_set(static_cast(device), globalDescriptor); VkRenderingAttachmentInfo colorAttachment = vkinit::attachment_info( _drawImage->imageView(), nullptr, VK_IMAGE_LAYOUT_GENERAL); @@ -803,13 +805,13 @@ void VulkanEngine::draw_geometry(VkCommandBuffer cmd) { // bind a texture VkDescriptorSet imageSet = get_current_frame()._frameDescriptors.allocate( - _device, _singleImageDescriptorLayout); + static_cast(device), _singleImageDescriptorLayout.set); DescriptorWriter single_image_writer; single_image_writer.write_image(0, _errorCheckerboardImage->imageView(), _defaultSamplerNearest, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); - single_image_writer.update_set(_device, imageSet); + single_image_writer.update_set(static_cast(device), imageSet); pipelines.meshPipeline->bindDescriptorSets(cmd, &imageSet, 1); @@ -844,19 +846,19 @@ void VulkanEngine::draw() { // wait until the gpu has finished rendering the last frame. Timeout of 1 // second - VK_CHECK(vkWaitForFences(_device, 1, get_current_frame()._renderFence->getPtr(), + VK_CHECK(vkWaitForFences(static_cast(device), 1, get_current_frame()._renderFence->getPtr(), true, 1000000000)); // Clear frame buffers instead of flushing deletion queue get_current_frame()._frameBuffers.clear(); - get_current_frame()._frameDescriptors.clear_pools(_device); + get_current_frame()._frameDescriptors.clear_pools(static_cast(device)); - VK_CHECK(vkResetFences(_device, 1, get_current_frame()._renderFence->getPtr())); + VK_CHECK(vkResetFences(static_cast(device), 1, get_current_frame()._renderFence->getPtr())); // request image from the swapchain uint32_t swapchainImageIndex; const VkResult e = - vkAcquireNextImageKHR(_device, _swapchain, 1000000000, + vkAcquireNextImageKHR(static_cast(device), _swapchain, 1000000000, get_current_frame()._swapchainSemaphore->get(), nullptr, &swapchainImageIndex); if (e == VK_ERROR_OUT_OF_DATE_KHR) { @@ -981,7 +983,7 @@ void VulkanEngine::draw() { } void VulkanEngine::resize_swapchain() { - vkDeviceWaitIdle(_device); + vkDeviceWaitIdle(static_cast(device)); destroy_swapchain(); @@ -1039,7 +1041,7 @@ AllocatedImage VulkanEngine::create_image(VkExtent3D size, VkFormat format, vkinit::imageview_create_info(format, newImage.image, aspectFlag); view_info.subresourceRange.levelCount = img_info.mipLevels; - VK_CHECK(vkCreateImageView(_device, &view_info, nullptr, + VK_CHECK(vkCreateImageView(static_cast(device), &view_info, nullptr, &newImage.imageView)); return newImage; diff --git a/src/graphics/vulkan/vk_loader.cpp b/src/graphics/vulkan/vk_loader.cpp index 5c00e7be..31ad66eb 100644 --- a/src/graphics/vulkan/vk_loader.cpp +++ b/src/graphics/vulkan/vk_loader.cpp @@ -251,7 +251,7 @@ std::optional> loadGltf(VulkanEngine* engine, {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 3}, {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1}}; file.descriptorPool.init( - engine->_device, + static_cast(engine->device), static_cast(std::max(gltf.materials.size(), size_t(1))), sizes); @@ -269,7 +269,7 @@ std::optional> loadGltf(VulkanEngine* engine, sampl.mipmapMode = extract_mipmap_mode( sampler.minFilter.value_or(fastgltf::Filter::Nearest)); VkSampler newSampler; - vkCreateSampler(engine->_device, &sampl, nullptr, &newSampler); + vkCreateSampler(static_cast(engine->device), &sampl, nullptr, &newSampler); file.samplers.push_back(newSampler); } @@ -523,4 +523,24 @@ void LoadedGLTF::Draw(const glm::mat4& topMatrix, DrawContext& ctx) { } } -void LoadedGLTF::clearAll() {} +void LoadedGLTF::clearAll() { + VkDevice dv = static_cast(creator->device); + descriptorPool.destroy_pools(dv); + creator->destroy_buffer(materialDataBuffer); + // for (auto& [k, v] : meshes) { + // creator->destroy_buffer(v->meshBuffers.indexBuffer); + // creator->destroy_buffer(v->meshBuffers.vertexBuffer); + // } + for (auto& [k, v] : images) { + + if (v.image == creator->_errorCheckerboardImage.get()->image()) { + //dont destroy the default images + continue; + } + creator->destroy_image(v); + } + + for (auto& sampler : samplers) { + vkDestroySampler(dv, sampler, nullptr); + } +} diff --git a/src/include/graphics/vulkan/vk_engine.h b/src/include/graphics/vulkan/vk_engine.h index c6e48c28..ccc63dad 100644 --- a/src/include/graphics/vulkan/vk_engine.h +++ b/src/include/graphics/vulkan/vk_engine.h @@ -75,20 +75,15 @@ class VulkanEngine { Instance instance; struct Device { - vkb::Device device; - void init(const vkb::PhysicalDevice& physical_device) { - const vkb::DeviceBuilder device_builder{physical_device}; - auto dev_ret = device_builder.build(); - if (!dev_ret) { - LOGE("Failed to create logical device. Error: {}", - dev_ret.error().message()); - } - device = dev_ret.value(); - } - ~Device() {vkb::destroy_device(device);} + explicit operator VkDevice() const; + explicit operator vkb::Device() const; + void init(const vkb::PhysicalDevice& physical_device); + ~Device(); + private: + vkb::Device _device; }; - Device _device; - VkDevice getRawDevice() const { return _device.device; } + Device device; + struct Allocator { VmaAllocator _allocator{nullptr}; void init(VmaAllocatorCreateInfo info) {vmaCreateAllocator(&info, &_allocator);} // move info inside From 04a2f1d27f54ad0e50b00259dae7a21d6a32dc79 Mon Sep 17 00:00:00 2001 From: Varnill Date: Sun, 28 Sep 2025 23:53:56 +0300 Subject: [PATCH 3/4] refactor: Allocator --- src/graphics/vulkan/vk_engine.cpp | 59 +++++++++++++++---------- src/include/graphics/vulkan/vk_engine.h | 10 +++-- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/src/graphics/vulkan/vk_engine.cpp b/src/graphics/vulkan/vk_engine.cpp index aa2b728c..ed205137 100644 --- a/src/graphics/vulkan/vk_engine.cpp +++ b/src/graphics/vulkan/vk_engine.cpp @@ -85,6 +85,24 @@ VulkanEngine::Device::~Device() {vkb::destroy_device(_device);} VulkanEngine::Device::operator VkDevice() const { return _device; } VulkanEngine::Device::operator vkb::Device() const { return _device; } +void VulkanEngine::Allocator::init(const VkPhysicalDevice& pGpu, + const VkDevice& pDevice, + const VkInstance& pInstance) { + const VmaAllocatorCreateInfo info = { + .flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT, + .physicalDevice = pGpu, + .device = pDevice, + .instance = pInstance + }; + vmaCreateAllocator(&info, &_allocator); +} + +VulkanEngine::Allocator::~Allocator() { + vmaDestroyAllocator(_allocator); +} + +VulkanEngine::Allocator::operator VmaAllocator() const { return _allocator; } + VKAPI_ATTR VkBool32 VKAPI_CALL VulkanEngine::debugCallback( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, @@ -136,7 +154,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanEngine::debugCallback( void VulkanEngine::destroy_image(const AllocatedImage& img) const { vkDestroyImageView(static_cast(device), img.imageView, nullptr); - vmaDestroyImage(_a._allocator, img.image, img.allocation); + vmaDestroyImage(static_cast(allocator), img.image, img.allocation); } void VulkanEngine::init_default_data() { @@ -165,17 +183,17 @@ void VulkanEngine::init_default_data() { const uint32_t white = glm::packUnorm4x8(glm::vec4(1, 1, 1, 1)); AllocatedImage whiteImageData = create_image(&white, VkExtent3D{1, 1, 1}, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT); - _whiteImage = std::make_unique(_a._allocator, static_cast(device), whiteImageData); + _whiteImage = std::make_unique(static_cast(allocator), static_cast(device), whiteImageData); const uint32_t grey = glm::packUnorm4x8(glm::vec4(0.66f, 0.66f, 0.66f, 1)); AllocatedImage greyImageData = create_image(&grey, VkExtent3D{1, 1, 1}, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT); - _greyImage = std::make_unique(_a._allocator, static_cast(device), greyImageData); + _greyImage = std::make_unique(static_cast(allocator), static_cast(device), greyImageData); const uint32_t black = glm::packUnorm4x8(glm::vec4(0, 0, 0, 0)); AllocatedImage blackImageData = create_image(&black, VkExtent3D{1, 1, 1}, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT); - _blackImage = std::make_unique(_a._allocator, static_cast(device), blackImageData); + _blackImage = std::make_unique(static_cast(allocator), static_cast(device), blackImageData); // checkerboard image const uint32_t magenta = glm::packUnorm4x8(glm::vec4(1, 0, 1, 1)); @@ -187,7 +205,7 @@ void VulkanEngine::init_default_data() { } AllocatedImage errorImageData = create_image(pixels.data(), VkExtent3D{16, 16, 1}, VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_USAGE_SAMPLED_BIT); - _errorCheckerboardImage = std::make_unique(_a._allocator, static_cast(device), errorImageData); + _errorCheckerboardImage = std::make_unique(static_cast(allocator), static_cast(device), errorImageData); VkSamplerCreateInfo sampl = {.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO}; @@ -220,7 +238,7 @@ void VulkanEngine::init_default_data() { sceneUniformData->metal_rough_factors = glm::vec4{1, 0.5, 0, 0}; // Store material constants buffer in managed buffers for automatic cleanup - _managedBuffers.push_back(std::make_unique(_allocator, materialConstants)); + _managedBuffers.push_back(std::make_unique(static_cast(allocator), materialConstants)); materialResources.dataBuffer = materialConstants.buffer; materialResources.dataBufferOffset = 0; @@ -462,14 +480,7 @@ void VulkanEngine::init_vulkan() { } _graphicsQueueFamily = queue_family_ret.value(); - - // initialize the memory allocator - VmaAllocatorCreateInfo allocatorInfo = {}; - allocatorInfo.physicalDevice = _chosenGPU; - allocatorInfo.device = static_cast(device); - allocatorInfo.instance = static_cast(instance); - allocatorInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; - vmaCreateAllocator(&allocatorInfo, &_allocator); + allocator.init(_chosenGPU, static_cast(device), static_cast(instance)); // VMA allocator will be destroyed in cleanup() - no need for deletion queue } @@ -536,7 +547,7 @@ void VulkanEngine::init_swapchain() { drawImageData.imageExtent = drawImageExtent; // allocate and create the image - vmaCreateImage(_allocator, &rimg_info, &rimg_allocinfo, &drawImageData.image, + vmaCreateImage(static_cast(allocator), &rimg_info, &rimg_allocinfo, &drawImageData.image, &drawImageData.allocation, nullptr); // build an image-view for the draw image to use for rendering @@ -548,7 +559,7 @@ void VulkanEngine::init_swapchain() { &drawImageData.imageView)); // Create smart pointer for automatic cleanup - _drawImage = std::make_unique(_a._allocator, static_cast(device), drawImageData); + _drawImage = std::make_unique(static_cast(allocator), static_cast(device), drawImageData); // Create depth image VkExtent3D depthImageExtent = { @@ -574,7 +585,7 @@ void VulkanEngine::init_swapchain() { depthImageData.imageExtent = depthImageExtent; // allocate and create the depth image - vmaCreateImage(_allocator, &dimg_info, &dimg_allocinfo, &depthImageData.image, + vmaCreateImage(static_cast(allocator), &dimg_info, &dimg_allocinfo, &depthImageData.image, &depthImageData.allocation, nullptr); // build an image-view for the depth image @@ -585,7 +596,7 @@ void VulkanEngine::init_swapchain() { &depthImageData.imageView)); // Create smart pointer for automatic cleanup - _depthImage = std::make_unique(_a._allocator, static_cast(device), depthImageData); + _depthImage = std::make_unique(static_cast(allocator), static_cast(device), depthImageData); } void VulkanEngine::destroy_swapchain() { @@ -644,7 +655,7 @@ AllocatedBuffer VulkanEngine::create_buffer(size_t allocSize, AllocatedBuffer newBuffer{}; // allocate the buffer - VK_CHECK(vmaCreateBuffer(_allocator, &bufferInfo, &vmallocinfo, + VK_CHECK(vmaCreateBuffer(static_cast(allocator), &bufferInfo, &vmallocinfo, &newBuffer.buffer, &newBuffer.allocation, &newBuffer.info)); @@ -652,7 +663,7 @@ AllocatedBuffer VulkanEngine::create_buffer(size_t allocSize, } void VulkanEngine::destroy_buffer(const AllocatedBuffer& buffer) const { - vmaDestroyBuffer(_allocator, buffer.buffer, buffer.allocation); + vmaDestroyBuffer(static_cast(allocator), buffer.buffer, buffer.allocation); } GPUMeshBuffers VulkanEngine::uploadMesh(std::span indices, @@ -714,8 +725,8 @@ GPUMeshBuffers VulkanEngine::uploadMesh(std::span indices, this); // Store mesh buffers in managed collections for automatic cleanup - _managedBuffers.push_back(std::make_unique(_allocator, newSurface.vertexBuffer)); - _managedBuffers.push_back(std::make_unique(_allocator, newSurface.indexBuffer)); + _managedBuffers.push_back(std::make_unique(static_cast(allocator), newSurface.vertexBuffer)); + _managedBuffers.push_back(std::make_unique(static_cast(allocator), newSurface.indexBuffer)); destroy_buffer(staging); return newSurface; @@ -758,7 +769,7 @@ void VulkanEngine::draw_geometry(VkCommandBuffer cmd) { // add it to the current frame's managed buffers for automatic cleanup get_current_frame()._frameBuffers.push_back( - std::make_unique(_allocator, gpuSceneDataBuffer)); + std::make_unique(static_cast(allocator), gpuSceneDataBuffer)); // write the buffer auto* sceneUniformData = @@ -1026,7 +1037,7 @@ AllocatedImage VulkanEngine::create_image(VkExtent3D size, VkFormat format, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); // allocate and create the image - VK_CHECK(vmaCreateImage(_allocator, &img_info, &allocinfo, &newImage.image, + VK_CHECK(vmaCreateImage(static_cast(allocator), &img_info, &allocinfo, &newImage.image, &newImage.allocation, nullptr)); // if the format is a depth format, we will need to have it use the correct diff --git a/src/include/graphics/vulkan/vk_engine.h b/src/include/graphics/vulkan/vk_engine.h index ccc63dad..a27a0a55 100644 --- a/src/include/graphics/vulkan/vk_engine.h +++ b/src/include/graphics/vulkan/vk_engine.h @@ -85,11 +85,13 @@ class VulkanEngine { Device device; struct Allocator { - VmaAllocator _allocator{nullptr}; - void init(VmaAllocatorCreateInfo info) {vmaCreateAllocator(&info, &_allocator);} // move info inside - ~Allocator() {vmaDestroyAllocator(_allocator);} + explicit operator VmaAllocator() const; + void init(const VkPhysicalDevice& gpu, const VkDevice& device, const VkInstance& instance); + ~Allocator(); + private: + VmaAllocator _allocator{VK_NULL_HANDLE}; }; - Allocator _a; // todo: rename + Allocator allocator; Pipelines pipelines; From 718dd70f5619a0edab42475e5c3e28837969f53d Mon Sep 17 00:00:00 2001 From: Varnill Date: Sun, 28 Sep 2025 23:56:54 +0300 Subject: [PATCH 4/4] refactor: Sampler --- src/graphics/vulkan/vk_engine.cpp | 20 +++++++++++++++++--- src/graphics/vulkan/vk_loader.cpp | 8 ++++---- src/include/graphics/vulkan/vk_engine.h | 15 +++++++++++++-- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/graphics/vulkan/vk_engine.cpp b/src/graphics/vulkan/vk_engine.cpp index ed205137..5c03200c 100644 --- a/src/graphics/vulkan/vk_engine.cpp +++ b/src/graphics/vulkan/vk_engine.cpp @@ -103,6 +103,20 @@ VulkanEngine::Allocator::~Allocator() { VulkanEngine::Allocator::operator VmaAllocator() const { return _allocator; } +void VulkanEngine::Sampler::create(const VkDevice& pDevice, + const VkSamplerCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator) { + _device = pDevice; + _allocator = pAllocator; + vkCreateSampler(_device, pCreateInfo, pAllocator, &_sampler); +} + +VulkanEngine::Sampler::~Sampler() { + vkDestroySampler(_device, _sampler, _allocator); +} + +VulkanEngine::Sampler::operator VkSampler() const { return _sampler; } + VKAPI_ATTR VkBool32 VKAPI_CALL VulkanEngine::debugCallback( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, @@ -221,9 +235,9 @@ void VulkanEngine::init_default_data() { GLTFMetallic_Roughness::MaterialResources materialResources{}; // default the material textures materialResources.colorImage = _whiteImage->get(); - materialResources.colorSampler = _defaultSamplerLinear; + materialResources.colorSampler = static_cast(_defaultSamplerLinear); materialResources.metalRoughImage = _whiteImage->get(); - materialResources.metalRoughSampler = _defaultSamplerLinear; + materialResources.metalRoughSampler = static_cast(_defaultSamplerLinear); // set the uniform buffer for the material data const AllocatedBuffer materialConstants = create_buffer( @@ -819,7 +833,7 @@ void VulkanEngine::draw_geometry(VkCommandBuffer cmd) { static_cast(device), _singleImageDescriptorLayout.set); DescriptorWriter single_image_writer; single_image_writer.write_image(0, _errorCheckerboardImage->imageView(), - _defaultSamplerNearest, + static_cast(_defaultSamplerNearest), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); single_image_writer.update_set(static_cast(device), imageSet); diff --git a/src/graphics/vulkan/vk_loader.cpp b/src/graphics/vulkan/vk_loader.cpp index 31ad66eb..285222a7 100644 --- a/src/graphics/vulkan/vk_loader.cpp +++ b/src/graphics/vulkan/vk_loader.cpp @@ -319,9 +319,9 @@ std::optional> loadGltf(VulkanEngine* engine, GLTFMetallic_Roughness::MaterialResources materialResources; materialResources.colorImage = engine->_whiteImage->get(); - materialResources.colorSampler = engine->_defaultSamplerLinear; + materialResources.colorSampler = static_cast(engine->_defaultSamplerLinear); materialResources.metalRoughImage = engine->_whiteImage->get(); - materialResources.metalRoughSampler = engine->_defaultSamplerLinear; + materialResources.metalRoughSampler = static_cast(engine->_defaultSamplerLinear); materialResources.dataBuffer = file.materialDataBuffer.buffer; materialResources.dataBufferOffset = data_index * sizeof(GLTFMetallic_Roughness::MaterialConstants); @@ -356,9 +356,9 @@ std::optional> loadGltf(VulkanEngine* engine, GLTFMetallic_Roughness::MaterialResources resources; resources.colorImage = engine->_whiteImage->get(); - resources.colorSampler = engine->_defaultSamplerLinear; + resources.colorSampler = static_cast(engine->_defaultSamplerLinear); resources.metalRoughImage = engine->_whiteImage->get(); - resources.metalRoughSampler = engine->_defaultSamplerLinear; + resources.metalRoughSampler = static_cast(engine->_defaultSamplerLinear); resources.dataBuffer = file.materialDataBuffer.buffer; resources.dataBufferOffset = 0; diff --git a/src/include/graphics/vulkan/vk_engine.h b/src/include/graphics/vulkan/vk_engine.h index a27a0a55..b13add86 100644 --- a/src/include/graphics/vulkan/vk_engine.h +++ b/src/include/graphics/vulkan/vk_engine.h @@ -197,8 +197,19 @@ class VulkanEngine { std::unique_ptr _greyImage; std::unique_ptr _errorCheckerboardImage; - VkSampler _defaultSamplerLinear; - VkSampler _defaultSamplerNearest; + struct Sampler { + explicit operator VkSampler() const; + void create(const VkDevice& pDevice, + const VkSamplerCreateInfo* pCreateInfo, + const VkAllocationCallbacks* pAllocator); + ~Sampler(); + private: + VkSampler _sampler{VK_NULL_HANDLE}; + VkDevice _device{VK_NULL_HANDLE}; + const VkAllocationCallbacks* _allocator{VK_NULL_HANDLE}; + }; + Sampler _defaultSamplerLinear; + Sampler _defaultSamplerNearest; VkDescriptorSetLayout _singleImageDescriptorLayout;