diff --git a/frontend/include/Renderer.hpp b/frontend/include/Renderer.hpp index 0bce7af..fc9064c 100644 --- a/frontend/include/Renderer.hpp +++ b/frontend/include/Renderer.hpp @@ -1,7 +1,6 @@ #pragma once #include #include -#include #include #include @@ -17,6 +16,9 @@ // GPU properties priority for selection #define GPU_DISCRETE_PRIORITY 1000 +#define GPU_GRAPHICS_WITH_PRESENT_PRIORITY 500 + +#define QUEUE_FAMILY_NO_VALUE UINT32_MAX struct RenderCommand { @@ -32,8 +34,14 @@ struct RenderCommand struct QueueFamiliesBundle { - std::optional graphics; - std::optional presence; + uint32_t graphics = QUEUE_FAMILY_NO_VALUE; + uint32_t present = QUEUE_FAMILY_NO_VALUE; +}; + +struct QueuesBundle +{ + VkQueue graphics; + VkQueue present; }; class Renderer @@ -45,9 +53,11 @@ private: SDL_Window *window; VkInstance vulkan; + VkSurfaceKHR surface; VkPhysicalDevice gpu; VkDevice device; QueueFamiliesBundle queueFamilies; + QueuesBundle queues; const float defaultQueuePriority = 1.0f; Rml::Context *uiContext; diff --git a/frontend/src/Renderer.cpp b/frontend/src/Renderer.cpp index fae6b56..11d7ed4 100644 --- a/frontend/src/Renderer.cpp +++ b/frontend/src/Renderer.cpp @@ -6,6 +6,7 @@ #include "Logger.h" #include #include +#include Renderer::Renderer(SDL_Window *window) : isRunning(false) { @@ -74,6 +75,11 @@ void Renderer::InitVulkan() if (vkResult != VK_SUCCESS) LOG(CRITICAL, "Vulkan is not instantiated! Code: %d", vkResult); else LOG(INFO, "Vulkan is instantiated"); + + // Create surface + if ( !SDL_Vulkan_CreateSurface(window, vulkan, &surface) ) + LOG(CRITICAL, "Failed to create SDL Vulkan surface. %hs", SDL_GetError()); + else LOG(INFO, "SDL Vulkan surface created"); } void Renderer::SetupDevice() @@ -140,22 +146,32 @@ void Renderer::SetupDevice() for (const VkQueueFamilyProperties &familyProps : queueFamiliesProperties) { if (familyProps.queueFlags & VK_QUEUE_GRAPHICS_BIT) - { queueFamiliesBuffer.graphics = i; - queueFamiliesBuffer.presence = i; - } - //TODO: if (vkGetPhysicalDeviceSurfaceSupportKHR(gpu, i, surface, value)) + if ( + queueFamiliesBuffer.graphics != queueFamiliesBuffer.present || + queueFamiliesBuffer.graphics == QUEUE_FAMILY_NO_VALUE + ) + { + VkBool32 presentSupport = VK_FALSE; + vkResult = vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, i, surface, &presentSupport); + if (vkResult != VK_SUCCESS) + LOG(WARNING, "Failed to check surface present support. Code: %d", vkResult); + if (presentSupport) + queueFamiliesBuffer.present = i; + } i++; } if ( - !queueFamiliesBuffer.graphics.has_value() || - !queueFamiliesBuffer.presence.has_value() + queueFamiliesBuffer.graphics == QUEUE_FAMILY_NO_VALUE || + queueFamiliesBuffer.present == QUEUE_FAMILY_NO_VALUE ) continue; + if (queueFamiliesBuffer.graphics == queueFamiliesBuffer.present) + priority += GPU_GRAPHICS_WITH_PRESENT_PRIORITY; if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) priority += GPU_DISCRETE_PRIORITY; @@ -174,15 +190,26 @@ void Renderer::SetupDevice() return; } - // Create queues - VkDeviceQueueCreateInfo graphicsQueueCreateConfig { - .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, - .pNext = nullptr, - .queueFamilyIndex = queueFamilies.graphics.value(), - .queueCount = 1, - .pQueuePriorities = &defaultQueuePriority + // Define queues + std::vector queuesCreateConfigs; + std::set uniqueQueueFamilies = { + queueFamilies.graphics, + queueFamilies.present }; + for (uint32_t queueFamily : uniqueQueueFamilies) + { + VkDeviceQueueCreateInfo queueCreateConfig { + .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, + .pNext = nullptr, + .queueFamilyIndex = queueFamily, + .queueCount = 1, + .pQueuePriorities = &defaultQueuePriority + }; + + queuesCreateConfigs.push_back(queueCreateConfig); + } + // Create logical device std::vector deviceExtensions = { "VK_KHR_swapchain" @@ -191,8 +218,8 @@ void Renderer::SetupDevice() VkDeviceCreateInfo deviceInfo = { .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .pNext = nullptr, - .queueCreateInfoCount = 1, - .pQueueCreateInfos = &graphicsQueueCreateConfig, + .queueCreateInfoCount = static_cast(queuesCreateConfigs.size()), + .pQueueCreateInfos = queuesCreateConfigs.data(), .enabledExtensionCount = static_cast(deviceExtensions.size()), .ppEnabledExtensionNames = deviceExtensions.data(), .pEnabledFeatures = &enabledFeatures, @@ -204,7 +231,11 @@ void Renderer::SetupDevice() LOG(CRITICAL, "Failed to create logical device on %hs. Code: %d", deviceProperties.deviceName, vkResult); return; } - else LOG(INFO, "%hs is selected for render", deviceProperties.deviceName); + else LOG(INFO, "%hs is selected for render with %d priority score", deviceProperties.deviceName, best_priority); + + // Save queues descriptor + vkGetDeviceQueue(device, queueFamilies.graphics, 0, &queues.graphics); + vkGetDeviceQueue(device, queueFamilies.present, 0, &queues.present); } void Renderer::Start() @@ -288,6 +319,7 @@ void Renderer::Request(RenderCommand::Type type) void Renderer::Release() { vkDestroyDevice(device, nullptr); + vkDestroySurfaceKHR(vulkan, surface, nullptr); vkDestroyInstance(vulkan, nullptr); LOG(INFO, "Renderer is released");