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 99b94292..5c03200c 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,75 @@ 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; } + +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; } + +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; } + +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, @@ -98,6 +166,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(static_cast(allocator), img.image, img.allocation); +} + void VulkanEngine::init_default_data() { std::array rect_vertices{}; @@ -124,17 +197,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(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(_allocator, _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(_allocator, _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)); @@ -146,26 +219,25 @@ 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(static_cast(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 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( @@ -180,7 +252,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; @@ -217,6 +289,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 +303,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 = { @@ -260,41 +336,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 @@ -306,14 +364,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); } @@ -332,7 +390,7 @@ void VulkanEngine::init(SDL_Window* window) { command_buffers_container.init_sync_structures(this); init_descriptors(); init_pipelines(); - init_imgui(); + _imgui.init(static_cast(device), _window.ptr, static_cast(instance), _chosenGPU, _graphicsQueue, &_swapchainImageFormat); init_default_data(); mainCamera->velocity = glm::vec3(0.f); @@ -371,28 +429,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 +450,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) @@ -436,10 +476,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()); @@ -447,28 +487,21 @@ 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()); } _graphicsQueueFamily = queue_family_ret.value(); - - // initialize the memory allocator - VmaAllocatorCreateInfo allocatorInfo = {}; - allocatorInfo.physicalDevice = _chosenGPU; - allocatorInfo.device = _device; - allocatorInfo.instance = _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 } 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; @@ -528,7 +561,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 @@ -536,11 +569,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(static_cast(allocator), static_cast(device), drawImageData); // Create depth image VkExtent3D depthImageExtent = { @@ -566,33 +599,33 @@ 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 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(static_cast(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(); @@ -606,19 +639,13 @@ 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(); - 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 @@ -642,7 +669,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)); @@ -650,7 +677,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, @@ -673,7 +700,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( @@ -712,8 +739,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; @@ -756,7 +783,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 = @@ -766,12 +793,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 +830,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, + static_cast(_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 +871,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 +1008,7 @@ void VulkanEngine::draw() { } void VulkanEngine::resize_swapchain() { - vkDeviceWaitIdle(_device); + vkDeviceWaitIdle(static_cast(device)); destroy_swapchain(); @@ -1024,7 +1051,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 @@ -1039,7 +1066,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..285222a7 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); } @@ -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; @@ -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 40db0c65..b13add86 100644 --- a/src/include/graphics/vulkan/vk_engine.h +++ b/src/include/graphics/vulkan/vk_engine.h @@ -64,6 +64,34 @@ 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 { + explicit operator VkDevice() const; + explicit operator vkb::Device() const; + void init(const vkb::PhysicalDevice& physical_device); + ~Device(); + private: + vkb::Device _device; + }; + Device device; + + struct Allocator { + explicit operator VmaAllocator() const; + void init(const VkPhysicalDevice& gpu, const VkDevice& device, const VkInstance& instance); + ~Allocator(); + private: + VmaAllocator _allocator{VK_NULL_HANDLE}; + }; + Allocator allocator; Pipelines pipelines; @@ -169,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; @@ -181,6 +220,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;