Vulkan surface and queues
- Vulkan SDL surface creation - Present support check in device selection - Present queue family and queue
This commit is contained in:
parent
721e5afbac
commit
7e59a9d2d7
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
std::set<uint32_t> uniqueQueueFamilies = {
|
||||||
|
queueFamilies.graphics,
|
||||||
|
queueFamilies.present
|
||||||
|
};
|
||||||
|
|
||||||
|
for (uint32_t queueFamily : uniqueQueueFamilies)
|
||||||
|
{
|
||||||
|
VkDeviceQueueCreateInfo queueCreateConfig {
|
||||||
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.queueFamilyIndex = queueFamilies.graphics.value(),
|
.queueFamilyIndex = queueFamily,
|
||||||
.queueCount = 1,
|
.queueCount = 1,
|
||||||
.pQueuePriorities = &defaultQueuePriority
|
.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");
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user