From f15221e842bd5518f5c60cb9ade51f9578fa8a8b Mon Sep 17 00:00:00 2001 From: Bjorn Tipling Date: Sun, 12 Jan 2025 15:08:38 -0800 Subject: [PATCH 1/6] init vma --- src/Engine/Graphics.cpp | 29 ++++++++++++++++++++++++----- src/Engine/VMA.cpp | 2 ++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/Engine/Graphics.cpp b/src/Engine/Graphics.cpp index 345d6074..819c8468 100644 --- a/src/Engine/Graphics.cpp +++ b/src/Engine/Graphics.cpp @@ -99,10 +99,10 @@ namespace { std::vector instance_extensions; std::vector device_extensions; - VkInstance instance; - VkDevice device; - VkPhysicalDevice physical_device; - VmaAllocator allocator; + VkInstance instance{0}; + VkDevice device{ 0 }; + VkPhysicalDevice physical_device{ 0 }; + VmaAllocator allocator{ 0 }; tracy::VkCtx* tracy_ctx{ nullptr }; @@ -297,7 +297,10 @@ namespace { void deinit() const { // Deinit acquired resources in the opposite order in which they were created - + if (graphics_created_bitmask & graphics_created_bit_vma) + { + vmaDestroyAllocator(allocator); + } if (tracy_ctx != nullptr) { TracyVkDestroy(tracy_ctx); } @@ -826,6 +829,22 @@ namespace { VkResult init_allocator() { l->info("Initializing VMA"); + + constexpr VkDeviceSize device_size{ 0 }; + VmaVulkanFunctions vulkan_functions{}; + vulkan_functions.vkGetInstanceProcAddr = vkGetInstanceProcAddr; + vulkan_functions.vkGetDeviceProcAddr = vkGetDeviceProcAddr; + + VmaAllocatorCreateInfo allocator_create_info{}; + allocator_create_info.vulkanApiVersion = VK_API_VERSION_1_3; + allocator_create_info.physicalDevice = physical_device; + allocator_create_info.device = device; + allocator_create_info.instance = instance; + allocator_create_info.pVulkanFunctions = &vulkan_functions; + allocator_create_info.preferredLargeHeapBlockSize = device_size; + allocator_create_info.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT; + + vmaCreateAllocator(&allocator_create_info, &allocator); graphics_created_bitmask |= graphics_created_bit_vma; return VK_SUCCESS; } diff --git a/src/Engine/VMA.cpp b/src/Engine/VMA.cpp index cac901ba..b8985512 100644 --- a/src/Engine/VMA.cpp +++ b/src/Engine/VMA.cpp @@ -1,3 +1,5 @@ #pragma warning(disable: 4100 4189 4127 4324 4505) + +#include "volk/volk.h" #define VMA_IMPLEMENTATION #include "vma/vk_mem_alloc.h" From fb8b708ac29367293c203da96f74ec29abb5d03f Mon Sep 17 00:00:00 2001 From: Bjorn Tipling Date: Sun, 12 Jan 2025 15:18:55 -0800 Subject: [PATCH 2/6] Add presentation queue --- src/Engine/Graphics.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/Engine/Graphics.cpp b/src/Engine/Graphics.cpp index 819c8468..052aa0b6 100644 --- a/src/Engine/Graphics.cpp +++ b/src/Engine/Graphics.cpp @@ -8,6 +8,7 @@ #include #pragma warning(disable: 4100 4459) +#include #include #include #pragma warning(default: 4100 4459) @@ -106,6 +107,9 @@ namespace { tracy::VkCtx* tracy_ctx{ nullptr }; + + VkQueue present_queue; + VkDebugUtilsMessengerEXT debug_messenger; VkSurfaceKHR surface; VkPhysicalDeviceFeatures required_features{}; @@ -852,6 +856,23 @@ namespace { VkResult init_presentation_queue() { l->info("Initializing presentation queue"); + { + VkDeviceQueueInfo2 get_info{}; + get_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2; + get_info.flags = 0; + get_info.queueFamilyIndex = queue_index; + get_info.queueIndex = 0; + vkGetDeviceQueue2(device, &get_info, &present_queue); + } + { + VkDebugUtilsObjectNameInfoEXT debug_name{}; + debug_name.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT; + debug_name.pNext = nullptr; + debug_name.objectType = VK_OBJECT_TYPE_QUEUE; + debug_name.objectHandle = reinterpret_cast(present_queue); + debug_name.pObjectName = "rosy present queue"; + if (const VkResult result = vkSetDebugUtilsObjectNameEXT(device, &debug_name); result != VK_SUCCESS) return result; + } return VK_SUCCESS; } From 660cfd7270a58f6075f364f2d86e18abc143978c Mon Sep 17 00:00:00 2001 From: Bjorn Tipling Date: Sun, 12 Jan 2025 16:28:25 -0800 Subject: [PATCH 3/6] init descriptor pool --- src/Engine/Graphics.cpp | 211 ++++++++++++++++++++++++++++++++++++++-- src/Engine/Types.h | 1 + 2 files changed, 202 insertions(+), 10 deletions(-) diff --git a/src/Engine/Graphics.cpp b/src/Engine/Graphics.cpp index 052aa0b6..1ed3bb30 100644 --- a/src/Engine/Graphics.cpp +++ b/src/Engine/Graphics.cpp @@ -9,6 +9,7 @@ #pragma warning(disable: 4100 4459) #include +#include #include #include #pragma warning(default: 4100 4459) @@ -21,6 +22,67 @@ namespace tracy { } namespace { + + //// Descriptor Set Allocator + + constexpr uint32_t descriptor_sampled_image_binding{ 0 }; + constexpr uint32_t descriptor_sample_binding{ 1 }; + constexpr uint32_t descriptor_storage_image_binding{ 2 }; + + constexpr uint32_t descriptor_max_storage_image_descriptors{ 100'000 }; + constexpr uint32_t descriptor_max_sampled_image_descriptors{ 100'000 }; + constexpr uint32_t descriptor_max_sample_descriptors{ 1000 }; + + struct descriptor_set_allocator + { + uint32_t max_indexes{ 1000 }; + std::stack recycled_indexes; + uint32_t num_allocated{ 0 }; + + result allocate(uint32_t* index) + { + uint32_t new_index = num_allocated; + if (recycled_indexes.empty()) + { + if (num_allocated >= max_indexes) + return rosy::result::overflow; + num_allocated += 1; + } + else + { + new_index = recycled_indexes.top(); + recycled_indexes.pop(); + } + *index = new_index; + return rosy::result::ok; + } + + void free(const uint32_t index) + { + recycled_indexes.push(index); + } + void reset() + { + while (!recycled_indexes.empty()) recycled_indexes.pop(); + num_allocated = 0; + } + }; + + //// Descriptor Set Manager + struct descriptor_set_manager + { + uint32_t binding{ 0 }; + descriptor_set_allocator allocator; + + result init(const uint32_t new_max_indexes, const uint32_t new_binding) + { + binding = new_binding; + allocator = descriptor_set_allocator{}; + allocator.max_indexes = new_max_indexes; + return result::ok; + } + }; + /// Graphics Device constexpr uint32_t graphics_created_bit_instance = 0b00000000000000000000000000000001; @@ -35,7 +97,8 @@ namespace { constexpr uint32_t graphics_created_bit_semaphore = 0b00000000000000000000001000000000; constexpr uint32_t graphics_created_bit_swapchain = 0b00000000000000000000010000000000; constexpr uint32_t graphics_created_bit_ktx = 0b00000000000000000000100000000000; - constexpr uint32_t graphics_created_bit_descriptor = 0b00000000000000000001000000000000; + constexpr uint32_t graphics_created_bit_descriptor_set = 0b00000000000000000001000000000000; + constexpr uint32_t graphics_created_bit_descriptor_pool = 0b00000000000000000010000000000000; const char* default_instance_layers[] = { "VK_LAYER_LUNARG_api_dump", @@ -100,16 +163,23 @@ namespace { std::vector instance_extensions; std::vector device_extensions; - VkInstance instance{0}; - VkDevice device{ 0 }; - VkPhysicalDevice physical_device{ 0 }; - VmaAllocator allocator{ 0 }; + VkInstance instance{ nullptr }; + VkDevice device{ nullptr }; + VkPhysicalDevice physical_device{ nullptr }; + VmaAllocator allocator{ nullptr }; tracy::VkCtx* tracy_ctx{ nullptr }; - VkQueue present_queue; + descriptor_set_manager *desc_storage_images{}; + descriptor_set_manager *desc_sampled_images{}; + descriptor_set_manager *desc_samples{}; + VkDescriptorSetLayout descriptor_set_layout; + VkDescriptorPool descriptor_pool; + std::vector pool_sizes; + VkDescriptorSet descriptor_set; + VkDebugUtilsMessengerEXT debug_messenger; VkSurfaceKHR surface; VkPhysicalDeviceFeatures required_features{}; @@ -298,21 +368,53 @@ namespace { return result::ok; } - void deinit() const + void deinit() { // Deinit acquired resources in the opposite order in which they were created + + if (desc_storage_images != nullptr) + { + delete desc_storage_images; + desc_storage_images = nullptr; + } + if (desc_sampled_images != nullptr) + { + delete desc_sampled_images; + desc_sampled_images = nullptr; + } + if (desc_samples != nullptr) + { + delete desc_samples; + desc_samples = nullptr; + } + if (graphics_created_bitmask & graphics_created_bit_device) + { + if (const VkResult result = vkDeviceWaitIdle(device); result != VK_SUCCESS) + { + l->error(std::format("Failed to wait device to be idle: {}", static_cast(result))); + } + } + + if (graphics_created_bitmask & graphics_created_bit_descriptor_set) + { + vkDestroyDescriptorSetLayout(device, descriptor_set_layout, nullptr); + } + if (graphics_created_bitmask & graphics_created_bit_descriptor_pool) + { + vkDestroyDescriptorPool(device, descriptor_pool, nullptr); + } if (graphics_created_bitmask & graphics_created_bit_vma) { vmaDestroyAllocator(allocator); } if (tracy_ctx != nullptr) { TracyVkDestroy(tracy_ctx); + tracy_ctx = nullptr; } if (graphics_created_bitmask & graphics_created_bit_device) { if (const VkResult result = vkDeviceWaitIdle(device); result == VK_SUCCESS) vkDestroyDevice(device, nullptr); } - if (graphics_created_bitmask & graphics_created_bit_surface) { SDL_Vulkan_DestroySurface(instance, surface, nullptr); @@ -893,7 +995,92 @@ namespace { VkResult init_descriptors() { l->info("Initializing descriptors"); - graphics_created_bitmask |= graphics_created_bit_descriptor; + + // Descriptor set managers + { + desc_storage_images = new(std::nothrow) descriptor_set_manager{}; + if (desc_storage_images == nullptr) + { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + desc_storage_images->init(descriptor_max_storage_image_descriptors, descriptor_storage_image_binding); + } + { + desc_sampled_images = new(std::nothrow) descriptor_set_manager{}; + if (desc_sampled_images == nullptr) + { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + desc_sampled_images->init(descriptor_max_sampled_image_descriptors, descriptor_sampled_image_binding); + } + { + desc_samples = new(std::nothrow) descriptor_set_manager{}; + if (desc_samples == nullptr) + { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + desc_samples->init(descriptor_max_sample_descriptors, descriptor_sample_binding); + } + + pool_sizes = std::vector({ + {.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, .descriptorCount = descriptor_max_storage_image_descriptors}, + {.type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, .descriptorCount = descriptor_max_sampled_image_descriptors}, + {.type = VK_DESCRIPTOR_TYPE_SAMPLER, .descriptorCount = descriptor_max_sample_descriptors}, + }); + + VkDescriptorPoolCreateInfo pool_create_info{}; + pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; + pool_create_info.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT; + pool_create_info.maxSets = 1; + pool_create_info.poolSizeCount = static_cast(pool_sizes.size()); + pool_create_info.pPoolSizes = pool_sizes.data(); + + VkResult result = vkCreateDescriptorPool(device, &pool_create_info, nullptr, &descriptor_pool); + if (result != VK_SUCCESS) return result; + graphics_created_bitmask |= graphics_created_bit_descriptor_set; + + const auto bindings = std::vector({ + {desc_storage_images->binding, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptor_max_storage_image_descriptors, VK_SHADER_STAGE_ALL}, + {desc_sampled_images->binding, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, descriptor_max_sampled_image_descriptors, VK_SHADER_STAGE_ALL}, + {desc_samples->binding, VK_DESCRIPTOR_TYPE_SAMPLER, descriptor_max_sample_descriptors, VK_SHADER_STAGE_ALL}, + }); + + const auto bindings_flags = std::vector({ + {VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT}, + {VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT}, + {VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT}, + }); + + if (bindings.size() != bindings_flags.size()) return VK_ERROR_INITIALIZATION_FAILED; + if (pool_sizes.size() != bindings_flags.size()) return VK_ERROR_INITIALIZATION_FAILED; + + VkDescriptorSetLayoutBindingFlagsCreateInfo layout_flags{}; + layout_flags.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO; + layout_flags.bindingCount = static_cast(bindings_flags.size()); + layout_flags.pBindingFlags = bindings_flags.data(); + + VkDescriptorSetLayoutCreateInfo layout_create_info{}; + layout_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; + layout_create_info.pNext = &layout_flags; + layout_create_info.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT; + layout_create_info.bindingCount = static_cast(bindings.size()); + layout_create_info.pBindings = bindings.data(); + + VkDescriptorSetLayout set_layout{}; + result = vkCreateDescriptorSetLayout(device, &layout_create_info, nullptr, &set_layout); + if (result != VK_SUCCESS) return result; + descriptor_set_layout = set_layout; + + VkDescriptorSetAllocateInfo set_create_info{}; + set_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; + set_create_info.descriptorPool = descriptor_pool; + set_create_info.descriptorSetCount = 1; + set_create_info.pSetLayouts = &set_layout; + + result = vkAllocateDescriptorSets(device, &set_create_info, &descriptor_set); + if (result != VK_SUCCESS) return result; + + graphics_created_bitmask |= graphics_created_bit_descriptor_pool; return VK_SUCCESS; } @@ -997,7 +1184,11 @@ namespace { result graphics::init(SDL_Window* new_window, log const* new_log) { - if (!new_window || !new_log) + if (new_window == nullptr) + { + return result::invalid_argument; + } + if (new_log == nullptr) { return result::invalid_argument; } diff --git a/src/Engine/Types.h b/src/Engine/Types.h index 9e845698..83ae7912 100644 --- a/src/Engine/Types.h +++ b/src/Engine/Types.h @@ -10,6 +10,7 @@ namespace rosy invalid_argument, allocation_failure, graphics_init_failure, + overflow, }; enum class log_level : uint8_t From 6163ca58de6bbd88e0133cc2f2c6fe4dbe232700 Mon Sep 17 00:00:00 2001 From: Bjorn Tipling Date: Sun, 12 Jan 2025 16:30:12 -0800 Subject: [PATCH 4/6] reorder these includes --- src/Engine/Graphics.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Engine/Graphics.cpp b/src/Engine/Graphics.cpp index 1ed3bb30..229e2799 100644 --- a/src/Engine/Graphics.cpp +++ b/src/Engine/Graphics.cpp @@ -2,14 +2,14 @@ #include #include +#include +#include #include "volk/volk.h" #include "vma/vk_mem_alloc.h" #include #pragma warning(disable: 4100 4459) -#include -#include #include #include #pragma warning(default: 4100 4459) From 5f48a73b0442f6d0df5e473ff0dfd2b7ae96d7f7 Mon Sep 17 00:00:00 2001 From: Bjorn Tipling Date: Sun, 12 Jan 2025 16:31:23 -0800 Subject: [PATCH 5/6] add new line here --- src/Engine/Graphics.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Engine/Graphics.cpp b/src/Engine/Graphics.cpp index 229e2799..8e85e499 100644 --- a/src/Engine/Graphics.cpp +++ b/src/Engine/Graphics.cpp @@ -69,6 +69,7 @@ namespace { }; //// Descriptor Set Manager + struct descriptor_set_manager { uint32_t binding{ 0 }; From c3d804e237b36dd33fb7596f536223dfd64558ce Mon Sep 17 00:00:00 2001 From: Bjorn Tipling Date: Sun, 12 Jan 2025 16:33:26 -0800 Subject: [PATCH 6/6] formatting --- src/Engine/Graphics.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Engine/Graphics.cpp b/src/Engine/Graphics.cpp index 8e85e499..f9dec35f 100644 --- a/src/Engine/Graphics.cpp +++ b/src/Engine/Graphics.cpp @@ -173,9 +173,9 @@ namespace { VkQueue present_queue; - descriptor_set_manager *desc_storage_images{}; - descriptor_set_manager *desc_sampled_images{}; - descriptor_set_manager *desc_samples{}; + descriptor_set_manager* desc_storage_images{}; + descriptor_set_manager* desc_sampled_images{}; + descriptor_set_manager* desc_samples{}; VkDescriptorSetLayout descriptor_set_layout; VkDescriptorPool descriptor_pool; std::vector pool_sizes; @@ -634,7 +634,7 @@ namespace { required_features.depthBiasClamp = VK_TRUE; required_features.depthClamp = VK_TRUE; required_features.depthBounds = VK_TRUE; - + for (const VkPhysicalDevice& p_device : physical_devices) { // get device properties @@ -1027,7 +1027,7 @@ namespace { {.type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, .descriptorCount = descriptor_max_storage_image_descriptors}, {.type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, .descriptorCount = descriptor_max_sampled_image_descriptors}, {.type = VK_DESCRIPTOR_TYPE_SAMPLER, .descriptorCount = descriptor_max_sample_descriptors}, - }); + }); VkDescriptorPoolCreateInfo pool_create_info{}; pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; @@ -1041,15 +1041,15 @@ namespace { graphics_created_bitmask |= graphics_created_bit_descriptor_set; const auto bindings = std::vector({ - {desc_storage_images->binding, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptor_max_storage_image_descriptors, VK_SHADER_STAGE_ALL}, - {desc_sampled_images->binding, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, descriptor_max_sampled_image_descriptors, VK_SHADER_STAGE_ALL}, - {desc_samples->binding, VK_DESCRIPTOR_TYPE_SAMPLER, descriptor_max_sample_descriptors, VK_SHADER_STAGE_ALL}, + {desc_storage_images->binding, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, descriptor_max_storage_image_descriptors, VK_SHADER_STAGE_ALL}, + {desc_sampled_images->binding, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, descriptor_max_sampled_image_descriptors, VK_SHADER_STAGE_ALL}, + {desc_samples->binding, VK_DESCRIPTOR_TYPE_SAMPLER, descriptor_max_sample_descriptors, VK_SHADER_STAGE_ALL}, }); const auto bindings_flags = std::vector({ - {VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT}, - {VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT}, - {VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT}, + {VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT}, + {VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT}, + {VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT | VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT}, }); if (bindings.size() != bindings_flags.size()) return VK_ERROR_INITIALIZATION_FAILED; @@ -1157,7 +1157,7 @@ namespace { } } - uint32_t present_mode_count{0}; + uint32_t present_mode_count{ 0 }; if (const VkResult res = vkGetPhysicalDeviceSurfacePresentModesKHR(p_device, surface, &present_mode_count, nullptr); res != VK_SUCCESS) { l->warn(std::format("Failed to get device surface formats: {}", static_cast(res)));