Vulkan surface and queues

- Vulkan SDL surface creation
- Present support check in device selection
- Present queue family and queue
This commit is contained in:
legatt 2025-08-12 16:48:13 +03:00
parent 721e5afbac
commit 7e59a9d2d7
2 changed files with 61 additions and 19 deletions

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include <thread> #include <thread>
#include <atomic> #include <atomic>
#include <optional>
#include <Boost/lockfree/spsc_queue.hpp> #include <Boost/lockfree/spsc_queue.hpp>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
@ -17,6 +16,9 @@
// GPU properties priority for selection // GPU properties priority for selection
#define GPU_DISCRETE_PRIORITY 1000 #define GPU_DISCRETE_PRIORITY 1000
#define GPU_GRAPHICS_WITH_PRESENT_PRIORITY 500
#define QUEUE_FAMILY_NO_VALUE UINT32_MAX
struct RenderCommand struct RenderCommand
{ {
@ -32,8 +34,14 @@ struct RenderCommand
struct QueueFamiliesBundle struct QueueFamiliesBundle
{ {
std::optional<uint32_t> graphics; uint32_t graphics = QUEUE_FAMILY_NO_VALUE;
std::optional<uint32_t> presence; uint32_t present = QUEUE_FAMILY_NO_VALUE;
};
struct QueuesBundle
{
VkQueue graphics;
VkQueue present;
}; };
class Renderer class Renderer
@ -45,9 +53,11 @@ private:
SDL_Window *window; SDL_Window *window;
VkInstance vulkan; VkInstance vulkan;
VkSurfaceKHR surface;
VkPhysicalDevice gpu; VkPhysicalDevice gpu;
VkDevice device; VkDevice device;
QueueFamiliesBundle queueFamilies; QueueFamiliesBundle queueFamilies;
QueuesBundle queues;
const float defaultQueuePriority = 1.0f; const float defaultQueuePriority = 1.0f;
Rml::Context *uiContext; Rml::Context *uiContext;

View File

@ -6,6 +6,7 @@
#include "Logger.h" #include "Logger.h"
#include <allocator.hpp> #include <allocator.hpp>
#include <exception> #include <exception>
#include <set>
Renderer::Renderer(SDL_Window *window) : isRunning(false) Renderer::Renderer(SDL_Window *window) : isRunning(false)
{ {
@ -74,6 +75,11 @@ void Renderer::InitVulkan()
if (vkResult != VK_SUCCESS) if (vkResult != VK_SUCCESS)
LOG(CRITICAL, "Vulkan is not instantiated! Code: %d", vkResult); LOG(CRITICAL, "Vulkan is not instantiated! Code: %d", vkResult);
else LOG(INFO, "Vulkan is instantiated"); 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() void Renderer::SetupDevice()
@ -140,22 +146,32 @@ void Renderer::SetupDevice()
for (const VkQueueFamilyProperties &familyProps : queueFamiliesProperties) for (const VkQueueFamilyProperties &familyProps : queueFamiliesProperties)
{ {
if (familyProps.queueFlags & VK_QUEUE_GRAPHICS_BIT) if (familyProps.queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
queueFamiliesBuffer.graphics = i; 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++; i++;
} }
if ( if (
!queueFamiliesBuffer.graphics.has_value() || queueFamiliesBuffer.graphics == QUEUE_FAMILY_NO_VALUE ||
!queueFamiliesBuffer.presence.has_value() queueFamiliesBuffer.present == QUEUE_FAMILY_NO_VALUE
) )
continue; continue;
if (queueFamiliesBuffer.graphics == queueFamiliesBuffer.present)
priority += GPU_GRAPHICS_WITH_PRESENT_PRIORITY;
if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
priority += GPU_DISCRETE_PRIORITY; priority += GPU_DISCRETE_PRIORITY;
@ -174,15 +190,26 @@ void Renderer::SetupDevice()
return; return;
} }
// Create queues // Define queues
VkDeviceQueueCreateInfo graphicsQueueCreateConfig { std::vector<VkDeviceQueueCreateInfo> queuesCreateConfigs;
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, std::set<uint32_t> uniqueQueueFamilies = {
.pNext = nullptr, queueFamilies.graphics,
.queueFamilyIndex = queueFamilies.graphics.value(), queueFamilies.present
.queueCount = 1,
.pQueuePriorities = &defaultQueuePriority
}; };
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 // Create logical device
std::vector<const char*> deviceExtensions = { std::vector<const char*> deviceExtensions = {
"VK_KHR_swapchain" "VK_KHR_swapchain"
@ -191,8 +218,8 @@ void Renderer::SetupDevice()
VkDeviceCreateInfo deviceInfo = { VkDeviceCreateInfo deviceInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.pNext = nullptr, .pNext = nullptr,
.queueCreateInfoCount = 1, .queueCreateInfoCount = static_cast<uint32_t>(queuesCreateConfigs.size()),
.pQueueCreateInfos = &graphicsQueueCreateConfig, .pQueueCreateInfos = queuesCreateConfigs.data(),
.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size()), .enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size()),
.ppEnabledExtensionNames = deviceExtensions.data(), .ppEnabledExtensionNames = deviceExtensions.data(),
.pEnabledFeatures = &enabledFeatures, .pEnabledFeatures = &enabledFeatures,
@ -204,7 +231,11 @@ void Renderer::SetupDevice()
LOG(CRITICAL, "Failed to create logical device on %hs. Code: %d", deviceProperties.deviceName, vkResult); LOG(CRITICAL, "Failed to create logical device on %hs. Code: %d", deviceProperties.deviceName, vkResult);
return; 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() void Renderer::Start()
@ -288,6 +319,7 @@ void Renderer::Request(RenderCommand::Type type)
void Renderer::Release() void Renderer::Release()
{ {
vkDestroyDevice(device, nullptr); vkDestroyDevice(device, nullptr);
vkDestroySurfaceKHR(vulkan, surface, nullptr);
vkDestroyInstance(vulkan, nullptr); vkDestroyInstance(vulkan, nullptr);
LOG(INFO, "Renderer is released"); LOG(INFO, "Renderer is released");