diff --git a/src/main.cpp b/src/main.cpp index c97db21..e586479 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,6 +32,8 @@ #include #define VMA_IMPLEMENTATION +#define VMA_DEBUG_INITIALIZE_ALLOCATIONS 1 // Obviously its the C++ way, just initialize it since its ez // https://gpuopen-librariesandsdks.github.io/VulkanMemoryAllocator/html/debugging_memory_usage.html +#define VMA_DEBUG_DETECT_CORRUPTION 1 // heap overflow, enable! #include #define GLM_FORCE_DEPTH_ZERO_TO_ONE @@ -84,10 +86,10 @@ private: std::optional vk_queue_graphics; std::optional vk_queue_present; -public: +private: vma::UniqueAllocator vk_allocator; -public: +private: std::optional vk_swapchain; vk::Format vk_swapchain_image_format; vk::Extent2D vk_swapchain_extent; @@ -119,12 +121,15 @@ public: bool surface_has_present_modes = false; bool surface_has_format_modes = false; std::optional msaa_samples; + std::vector supported_features_vma_device; + std::vector supported_features_vma_allocator; + bool IsGoodCard() const { return this->graphics_family.has_value() && this->present_family.has_value() && this->screen_surface && surface_has_present_modes && surface_has_format_modes; } } vk_physical_card_info; -public: +private: VulkanBuffer vk_buffer_vertex; // in order to get a clean destruction sequence, instantiate the DeviceMemory for the vertex buffer first // https://github.com/KhronosGroup/Vulkan-Hpp/blob/6f72ceca515d59f40d64b64cf2734f6261e1f9f2/RAII_Samples/13_InitVertexBuffer/13_InitVertexBuffer.cpp VulkanBuffer vk_buffer_index; // used to make rendering models more efficent by sharing values @@ -179,7 +184,7 @@ public: 4, 5, 6, 6, 7, 4 }; -public: +private: // https://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/ struct UniformBufferObject { // https://docs.vulkan.org/tutorial/latest/05_Uniform_buffers/01_Descriptor_pool_and_sets.html#_alignment_requirements alignas(16) glm::mat4 model; @@ -189,18 +194,18 @@ public: std::vector vk_buffers_uniform; std::vector vk_buffers_uniform_mapped; -public: +private: vk::SampleCountFlagBits vk_msaa_samples_wanted = vk::SampleCountFlagBits::e8; vk::SampleCountFlagBits vk_msaa_samples; VulkanImage vk_color_image; std::optional vk_color_view; -public: +private: vk::Format vk_depth_format; VulkanImage vk_depth_image; std::optional vk_depth_view; -public: +private: std::uint32_t vk_texture_mip_levels; VulkanImage vk_texture_image; std::optional vk_texture_view; @@ -350,20 +355,42 @@ public: gfx_card_info.present_family = found_present_family_idx; cur_score += 5; - const auto CheckDeviceExtensionSupport = [](const vk::PhysicalDevice& gfx_card) -> bool { - const auto available_extensions = gfx_card.enumerateDeviceExtensionProperties(); - for (const std::string_view required_ext_name : required_vulkan_device_extensions) { - const auto find_wanted_ext = std::find_if(available_extensions.begin(), available_extensions.end(), [&](const auto& ext_to_test) { return std::string_view(ext_to_test.extensionName) == required_ext_name; }); - if (find_wanted_ext == available_extensions.end()) - return false; - } - return true; + const auto available_extensions = gfx_card.enumerateDeviceExtensionProperties(); + const auto DeviceSupportsExtension = [&available_extensions](const std::string_view required_ext_name) -> bool { + return available_extensions.end() != std::find_if(available_extensions.begin(), available_extensions.end(), [&](const auto& ext_to_test) { return std::string_view(ext_to_test.extensionName) == required_ext_name; }); }; - if (!CheckDeviceExtensionSupport(gfx_card)) { - ReturnScore(); - continue; + { + bool has_all_required_extensions = true; + for (const std::string_view ext_name_required : required_vulkan_device_extensions) { + if (!DeviceSupportsExtension(ext_name_required)) { + has_all_required_extensions = false; + } + } + if (!has_all_required_extensions) { + ReturnScore(); + continue; + } + cur_score += 2; + } + + const auto vma_feature_sets = std::array, vma::AllocatorCreateFlagBits>, 4> { + std::make_pair(std::vector { "VK_KHR_dedicated_allocation", "VK_KHR_get_memory_requirements2" }, vma::AllocatorCreateFlagBits::eKhrDedicatedAllocation), + { { "VK_KHR_bind_memory2" }, vma::AllocatorCreateFlagBits::eKhrBindMemory2 }, + { { "VK_KHR_maintenance4" }, vma::AllocatorCreateFlagBits::eKhrMaintenance4 }, + { { "VK_KHR_maintenance5" }, vma::AllocatorCreateFlagBits::eKhrMaintenance5 } + }; + for (const auto& wanted_vma_feature_set : vma_feature_sets) { + bool has_all_required_features = true; + for (const auto& required_device_feature : wanted_vma_feature_set.first) + if (!DeviceSupportsExtension(required_device_feature)) + has_all_required_features = false; + if (has_all_required_features) { + for (const auto& required_device_feature : wanted_vma_feature_set.first) + gfx_card_info.supported_features_vma_device.emplace_back(required_device_feature); + gfx_card_info.supported_features_vma_allocator.emplace_back(wanted_vma_feature_set.second); + cur_score += 2; + } } - cur_score += 2; if (!device_features.samplerAnisotropy) { ReturnScore(); @@ -433,14 +460,24 @@ public: return device_queues_we_need; }(this->vk_physical_card_info.graphics_family.value(), this->vk_physical_card_info.present_family.value()); + const std::vector enabled_extensions_device = [this]() -> std::vector { + std::vector enabled_extensions(required_vulkan_device_extensions.begin(), required_vulkan_device_extensions.end()); + + for (const auto& i : this->vk_physical_card_info.supported_features_vma_device) + enabled_extensions.emplace_back(i.data()); + + return enabled_extensions; + }(); + constexpr vk::PhysicalDeviceFeatures device_features { .samplerAnisotropy = vk::True }; + const vk::DeviceCreateInfo device_create_info { .queueCreateInfoCount = static_cast(device_queue_create_infos.size()), .pQueueCreateInfos = device_queue_create_infos.data(), - .enabledExtensionCount = static_cast(required_vulkan_device_extensions.size()), - .ppEnabledExtensionNames = required_vulkan_device_extensions.data(), + .enabledExtensionCount = static_cast(enabled_extensions_device.size()), + .ppEnabledExtensionNames = enabled_extensions_device.data(), .pEnabledFeatures = &device_features, }; this->vk_gpu.emplace(*this->vk_gfx_card, device_create_info); @@ -471,9 +508,16 @@ public: .vkDestroyBuffer = dispatcher_gpu->vkDestroyBuffer, .vkCreateImage = dispatcher_gpu->vkCreateImage, .vkDestroyImage = dispatcher_gpu->vkDestroyImage, - .vkCmdCopyBuffer = dispatcher_gpu->vkCmdCopyBuffer + .vkCmdCopyBuffer = dispatcher_gpu->vkCmdCopyBuffer, + .vkGetBufferMemoryRequirements2KHR = dispatcher_gpu->vkGetBufferMemoryRequirements2KHR, }; const vma::AllocatorCreateInfo allocator_create_info = { + .flags = [&]() -> vma::AllocatorCreateFlags { + vma::AllocatorCreateFlags enabled_flags; + for (const auto& wanted_feature : this->vk_physical_card_info.supported_features_vma_allocator) + enabled_flags |= wanted_feature; + return enabled_flags; + }(), .physicalDevice = **this->vk_gfx_card, .device = **this->vk_gpu, .pVulkanFunctions = &vulkan_functions, @@ -1130,7 +1174,9 @@ protected: vma::AllocationCreateFlags ret; if (wanted_properties & vk::MemoryPropertyFlagBits::eHostVisible) ret |= vma::AllocationCreateFlagBits::eHostAccessSequentialWrite; - if (wanted_usage == vk::BufferUsageFlagBits::eUniformBuffer) + else + ret |= vma::AllocationCreateFlagBits::eDedicatedMemory; + if (wanted_usage & vk::BufferUsageFlagBits::eUniformBuffer) ret |= vma::AllocationCreateFlagBits::eMapped; return ret; } @@ -1488,6 +1534,8 @@ public: command_buffer.setViewport(0, viewport); command_buffer.setScissor(0, scissor); } + +private: void UpdateUniformBuffer(const std::uint32_t current_image) const { static auto startTime = std::chrono::high_resolution_clock::now();