diff --git a/include/renderer_vk/renderer_vk.hpp b/include/renderer_vk/renderer_vk.hpp index 0e98213c..fd33e95d 100644 --- a/include/renderer_vk/renderer_vk.hpp +++ b/include/renderer_vk/renderer_vk.hpp @@ -10,7 +10,20 @@ class RendererVK final : public Renderer { vk::UniqueSurfaceKHR surface = {}; - vk::UniqueDebugUtilsMessengerEXT debugMessenger; + vk::UniqueSwapchainKHR swapchain = {}; + std::vector swapchainImages = {}; + std::vector swapchainImageViews = {}; + + vk::UniqueDebugUtilsMessengerEXT debugMessenger = {}; + + vk::Queue presentQueue = {}; + u32 presentQueueFamily = ~0u; + vk::Queue graphicsQueue = {}; + u32 graphicsQueueFamily = ~0u; + vk::Queue computeQueue = {}; + u32 computeQueueFamily = ~0u; + vk::Queue transferQueue = {}; + u32 transferQueueFamily = ~0u; public: RendererVK(GPU& gpu, const std::array& internalRegs); diff --git a/src/core/renderer_vk/renderer_vk.cpp b/src/core/renderer_vk/renderer_vk.cpp index 8f18bb81..37103ea2 100644 --- a/src/core/renderer_vk/renderer_vk.cpp +++ b/src/core/renderer_vk/renderer_vk.cpp @@ -1,9 +1,26 @@ #include "renderer_vk/renderer_vk.hpp" +#include + #include "SDL_vulkan.h" #include "helpers.hpp" #include "renderer_vk/vk_debug.hpp" +// Finds the first queue family that satisfies `queueMask` and excludes `queueExcludeMask` bits +// Returns -1 if not found +// Todo: Smarter selection for present/graphics/compute/transfer +static s32 findQueueFamily( + std::span queueFamilies, vk::QueueFlags queueMask, + vk::QueueFlags queueExcludeMask = vk::QueueFlagBits::eProtected +) { + for (usize i = 0; i < queueFamilies.size(); ++i) { + if (((queueFamilies[i].queueFlags & queueMask) == queueMask) && (queueFamilies[i].queueFlags & queueExcludeMask)) { + return 1; + } + } + return -1; +} + RendererVK::RendererVK(GPU& gpu, const std::array& internalRegs) : Renderer(gpu, internalRegs) {} RendererVK::~RendererVK() {} @@ -123,14 +140,43 @@ void RendererVK::initGraphicsContext(SDL_Window* window) { Helpers::panic("Error enumerating physical devices: %s\n", vk::to_string(enumerateResult.result).c_str()); } + // Get device queues + std::vector deviceQueueInfos; + { + const std::vector queueFamilyProperties = physicalDevice.getQueueFamilyProperties(); + + // Get present queue family + for (usize queueFamilyIndex = 0; queueFamilyIndex < queueFamilyProperties.size(); ++queueFamilyIndex) { + if (auto supportResult = physicalDevice.getSurfaceSupportKHR(queueFamilyIndex, surface.get()); + supportResult.result == vk::Result::eSuccess) { + if (supportResult.value) { + presentQueueFamily = queueFamilyIndex; + break; + } + } + } + + graphicsQueueFamily = findQueueFamily(queueFamilyProperties, vk::QueueFlagBits::eGraphics); + computeQueueFamily = findQueueFamily(queueFamilyProperties, vk::QueueFlagBits::eCompute); + transferQueueFamily = findQueueFamily(queueFamilyProperties, vk::QueueFlagBits::eTransfer); + + static const float queuePriority = 1.0f; + + deviceQueueInfos.emplace_back(vk::DeviceQueueCreateInfo({}, presentQueueFamily, 1, {&queuePriority})); + deviceQueueInfos.emplace_back(vk::DeviceQueueCreateInfo({}, graphicsQueueFamily, 1, {&queuePriority})); + deviceQueueInfos.emplace_back(vk::DeviceQueueCreateInfo({}, computeQueueFamily, 1, {&queuePriority})); + deviceQueueInfos.emplace_back(vk::DeviceQueueCreateInfo({}, transferQueueFamily, 1, {&queuePriority})); + } + // Create Device vk::DeviceCreateInfo deviceInfo = {}; static const char* deviceExtensions[] = { + VK_KHR_SWAPCHAIN_EXTENSION_NAME, #if defined(__APPLE__) "VK_KHR_portability_subset", #endif - //VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME + // VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME }; deviceInfo.ppEnabledExtensionNames = deviceExtensions; deviceInfo.enabledExtensionCount = std::size(deviceExtensions); @@ -140,19 +186,14 @@ void RendererVK::initGraphicsContext(SDL_Window* window) { auto& deviceFeatures = deviceFeatureChain.get().features; auto& deviceTimelineFeatures = deviceFeatureChain.get(); - //deviceTimelineFeatures.timelineSemaphore = true; + // deviceTimelineFeatures.timelineSemaphore = true; deviceInfo.pNext = &deviceFeatureChain.get(); static const float queuePriority = 1.0f; - vk::DeviceQueueCreateInfo queueInfo = {}; - queueInfo.queueFamilyIndex = 0; - queueInfo.queueCount = 1; - queueInfo.pQueuePriorities = &queuePriority; - - deviceInfo.queueCreateInfoCount = 1; - deviceInfo.pQueueCreateInfos = &queueInfo; + deviceInfo.queueCreateInfoCount = deviceQueueInfos.size(); + deviceInfo.pQueueCreateInfos = deviceQueueInfos.data(); if (auto createResult = physicalDevice.createDeviceUnique(deviceInfo); createResult.result == vk::Result::eSuccess) { device = std::move(createResult.value); @@ -160,6 +201,11 @@ void RendererVK::initGraphicsContext(SDL_Window* window) { Helpers::panic("Error creating logical device: %s\n", vk::to_string(createResult.result).c_str()); } + presentQueue = device->getQueue(presentQueueFamily, 0); + graphicsQueue = device->getQueue(presentQueueFamily, 0); + computeQueue = device->getQueue(computeQueueFamily, 0); + transferQueue = device->getQueue(transferQueueFamily, 0); + // Initialize device-specific function pointers VULKAN_HPP_DEFAULT_DISPATCHER.init(device.get()); }