From 1b5f373f8e913aa948ef0964d26a0082e6563f0a Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Thu, 2 May 2024 00:09:00 +0200 Subject: Vulkan surface creation & present queue selection --- main/main.cpp | 139 ++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 91 insertions(+), 48 deletions(-) (limited to 'main/main.cpp') diff --git a/main/main.cpp b/main/main.cpp index 4a999ce..602b6ab 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -13,7 +13,6 @@ static OsApi* os_api; static const VkAllocationCallbacks* kVkAlloc = nullptr; -[[nodiscard]] StatusOr CreateInstance(VulkanApi* vk) { const VkApplicationInfo application_info{ @@ -58,34 +57,33 @@ StatusOr CreateInstance(VulkanApi* vk) return instance; } -StatusOr FindPhysicalDevice(VulkanApi* vk, VkInstance instance) +StatusOr CreateSurface(VulkanApi* vk, VkInstance instance, OsWindow* window) { - auto temp_alloc = temp_api->Acquire(); - - uint32_t physical_device_count = 0; - vk->EnumeratePhysicalDevices(instance, &physical_device_count, nullptr); - if (physical_device_count == 0) + const VkWin32SurfaceCreateInfoKHR create_info{ + .sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, + .pNext = nullptr, + .flags = 0, + .hinstance = os_api->window->Win32Hinstance(window), + .hwnd = os_api->window->Win32Hwnd(window), + }; + + VkSurfaceKHR surface{}; + const VkResult res = vk->CreateWin32SurfaceKHR(instance, &create_info, kVkAlloc, &surface); + if (res != VK_SUCCESS) { - return InternalError("No Vulkan device found"); + return InternalError("vkCreateWin32SurfaceKHR failed"); } - log_api->LogInfo("Found $ physical devices", physical_device_count); - - auto devices = temp_alloc.allocator().NewArray(physical_device_count); - vk->EnumeratePhysicalDevices(instance, &physical_device_count, devices.data()); - - // @Todo Physical device selection - // In fact, FindQueueFamily should be done here. - return devices[0]; + return surface; } -StatusOr FindQueueFamily(VulkanApi* vk, VkPhysicalDevice physical_device) +StatusOr FindQueueFamily(VulkanApi* vk, VkPhysicalDevice physical_device, VkSurfaceKHR surface) { auto temp_alloc = temp_api->Acquire(); uint32_t queue_family_count = 0; vk->GetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, nullptr); - if (queue_family_count == 0) + if (queue_family_count == 0) { return InternalError("No queue on this physical device"); } @@ -100,7 +98,11 @@ StatusOr FindQueueFamily(VulkanApi* vk, VkPhysicalDevice physical_devi const auto& prps = queue_families[index]; const bool supports_graphics_compute = (prps.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0 && (prps.queueFlags & VK_QUEUE_COMPUTE_BIT) != 0; - const bool supports_presentation = vk->GetPhysicalDeviceWin32PresentationSupportKHR(physical_device, index) == VK_TRUE; + + VkBool32 vk_supports_presentation{}; + const VkResult presentation_res = vk->GetPhysicalDeviceSurfaceSupportKHR(physical_device, index, surface, &vk_supports_presentation); + const bool supports_presentation = presentation_res == VK_SUCCESS && vk_supports_presentation == VK_TRUE; + if (supports_graphics_compute && supports_presentation) { return index; @@ -110,6 +112,59 @@ StatusOr FindQueueFamily(VulkanApi* vk, VkPhysicalDevice physical_devi return InternalError("Couldn't find a suitable queue"); } +Status FindPhysicalDevice( + VulkanApi* vk, + VkInstance instance, + VkSurfaceKHR surface, + VkPhysicalDevice* out_physical_device, + uint32_t* out_queue_family) +{ + auto temp_alloc = temp_api->Acquire(); + + uint32_t physical_device_count = 0; + vk->EnumeratePhysicalDevices(instance, &physical_device_count, nullptr); + if (physical_device_count == 0) + { + return InternalError("No Vulkan device found"); + } + + log_api->LogInfo("Found $ physical devices", physical_device_count); + + auto physical_devices = temp_alloc.allocator().NewArray(physical_device_count); + vk->EnumeratePhysicalDevices(instance, &physical_device_count, physical_devices.data()); + + for (VkPhysicalDevice physical_device: physical_devices) + { + { + VkPhysicalDeviceVulkan12Properties prps12{}; + prps12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES; + prps12.pNext = nullptr; + + VkPhysicalDeviceProperties2 prps{}; + prps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; + prps.pNext = &prps12; + + vk->GetPhysicalDeviceProperties2(physical_device, &prps); + + log_api->LogInfo("Trying Vulkan device $ ($, $)", + prps.properties.deviceName, prps12.driverName, prps12.driverInfo); + } + + auto maybe_queue_family = FindQueueFamily(vk, physical_device, surface); + if (maybe_queue_family.ok()) + { + log_api->LogInfo("This device is compatible, choosing it"); + *out_physical_device = physical_device; + *out_queue_family = maybe_queue_family.value(); + return {}; + } + + log_api->LogInfo("Incompatible because: $", maybe_queue_family); + } + + return InternalError("No suitable device found"); +} + StatusOr CreateDevice(VulkanApi* vk, VkPhysicalDevice physical_device, uint32_t queue_family) { const float queue_priority = 1.0F; @@ -150,7 +205,7 @@ StatusOr CreateDevice(VulkanApi* vk, VkPhysicalDevice physical_device, return device; } -Status InitializeVulkan(ApiRegistry* api_registry) +Status InitializeVulkan(ApiRegistry* api_registry, OsWindow* window) { RegisterVulkanLoaderApi(api_registry); auto* loader_api = api_registry->Get(); @@ -166,32 +221,19 @@ Status InitializeVulkan(ApiRegistry* api_registry) loader_api->LoadInstance(vk, instance); - VkPhysicalDevice physical_device{}; + VkSurfaceKHR surface{}; { - StatusOr s = FindPhysicalDevice(vk, instance); + StatusOr s = CreateSurface(vk, instance, window); if (!s.ok()) { return s.status(); } - physical_device = s.value(); + surface = s.value(); + log_api->LogInfo("Vulkan surface created"); } + VkPhysicalDevice physical_device{}; + uint32_t queue_family{}; { - VkPhysicalDeviceVulkan12Properties prps12{}; - prps12.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES; - prps12.pNext = nullptr; - - VkPhysicalDeviceProperties2 prps{}; - prps.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; - prps.pNext = &prps12; - - vk->GetPhysicalDeviceProperties2(physical_device, &prps); - log_api->LogInfo("Vulkan device: $", prps.properties.deviceName); - log_api->LogInfo("Vulkan driver: $, $", prps12.driverName, prps12.driverInfo); - } - - uint32_t queue_family = 0; - { - StatusOr s = FindQueueFamily(vk, physical_device); - if (!s.ok()) { return s.status(); } - queue_family = s.value(); + Status s = FindPhysicalDevice(vk, instance, surface, &physical_device, &queue_family); + if (!s.ok()) { return s; } log_api->LogInfo("Vulkan queue family: $", queue_family); } @@ -210,6 +252,7 @@ Status InitializeVulkan(ApiRegistry* api_registry) Ensures(queue != VK_NULL_HANDLE); vk->DestroyDevice(device, kVkAlloc); + vk->DestroySurfaceKHR(instance, surface, kVkAlloc); vk->DestroyInstance(instance, kVkAlloc); return {}; @@ -235,19 +278,19 @@ int main(int /* argc */, char* /* argv */[]) window = s.value(); } - while (!os_api->window->QuitRequested(window)) - { - os_api->window->Update(window); - } - - const Status s = InitializeVulkan(api_registry); + const Status s = InitializeVulkan(api_registry, window); if (!s.ok()) { log_api->LogError("Vulkan initializaiton error: $", s); return 1; } - log_api->LogInfo("OK"); + while (!os_api->window->QuitRequested(window)) + { + os_api->window->Update(window); + } + + log_api->LogInfo("Goodbye"); return 0; } -- cgit