From 9172e413ada9eea0a405b95f9b669b71853dc89d Mon Sep 17 00:00:00 2001 From: Vanfanel Date: Sun, 21 Feb 2021 22:57:22 +0100 Subject: [PATCH] [KMSDRM] Fix intermitent bug in Vulkan initialization on Raspberry Pi 4. --- src/video/kmsdrm/SDL_kmsdrmvulkan.c | 42 ++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/src/video/kmsdrm/SDL_kmsdrmvulkan.c b/src/video/kmsdrm/SDL_kmsdrmvulkan.c index a429f42c3..34922980a 100644 --- a/src/video/kmsdrm/SDL_kmsdrmvulkan.c +++ b/src/video/kmsdrm/SDL_kmsdrmvulkan.c @@ -189,6 +189,7 @@ SDL_bool KMSDRM_Vulkan_CreateSurface(_THIS, uint32_t plane_count; VkPhysicalDevice *physical_devices = NULL; + VkPhysicalDeviceProperties *device_props = NULL; VkDisplayPropertiesKHR *displays_props = NULL; VkDisplayModePropertiesKHR *modes_props = NULL; VkDisplayPlanePropertiesKHR *planes_props = NULL; @@ -203,6 +204,7 @@ SDL_bool KMSDRM_Vulkan_CreateSurface(_THIS, VkResult result; SDL_bool ret = SDL_FALSE; + SDL_bool valid_gpu = SDL_FALSE; SDL_bool mode_found = SDL_FALSE; /* We don't receive a display index in KMSDRM_CreateDevice(), only @@ -214,8 +216,6 @@ SDL_bool KMSDRM_Vulkan_CreateSurface(_THIS, int i; - SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata); - /* Get the function pointers for the functions we will use. */ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr; @@ -228,6 +228,10 @@ SDL_bool KMSDRM_Vulkan_CreateSurface(_THIS, (PFN_vkEnumeratePhysicalDevices)vkGetInstanceProcAddr( instance, "vkEnumeratePhysicalDevices"); + PFN_vkGetPhysicalDeviceProperties vkGetPhysicalDeviceProperties = + (PFN_vkGetPhysicalDeviceProperties)vkGetInstanceProcAddr( + instance, "vkGetPhysicalDeviceProperties"); + PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR = (PFN_vkGetPhysicalDeviceDisplayPropertiesKHR)vkGetInstanceProcAddr( instance, "vkGetPhysicalDeviceDisplayPropertiesKHR"); @@ -275,6 +279,12 @@ SDL_bool KMSDRM_Vulkan_CreateSurface(_THIS, goto clean; } + /* A GPU (or physical_device, in vkcube terms) is a physical GPU. + A machine with more than one video output doesn't need to have more than one GPU, + like the Pi4 which has 1 GPU and 2 video outputs. + Just in case, we test that the GPU we choose is Vulkan-capable. + */ + /* Get the physical device count. */ vkEnumeratePhysicalDevices(instance, &gpu_count, NULL); @@ -285,13 +295,31 @@ SDL_bool KMSDRM_Vulkan_CreateSurface(_THIS, /* Get the physical devices. */ physical_devices = SDL_malloc(sizeof(VkPhysicalDevice) * gpu_count); + device_props = SDL_malloc(sizeof(VkPhysicalDeviceProperties)); vkEnumeratePhysicalDevices(instance, &gpu_count, physical_devices); - /* A GPU (or physical_device, in vkcube terms) is a GPU. A machine with more - than one video output doen't need to have more than one GPU, like the Pi4 - which has 1 GPU and 2 video outputs. - We grab the GPU/physical_device with the index we got in KMSDR_CreateDevice(). */ - gpu = physical_devices[viddata->devindex]; + /* Iterate on the physical devices. */ + for (i = 0; i < gpu_count; i++) { + + /* Get the physical device properties. */ + vkGetPhysicalDeviceProperties( + physical_devices[i], + device_props + ); + + /* Is this device a real GPU that supports API version 1 at least? */ + if (device_props->apiVersion >= 1 && + (device_props->deviceType == 1 || device_props->deviceType == 2)) + { + gpu = physical_devices[i]; + valid_gpu = SDL_TRUE; + } + } + + if (!valid_gpu) { + SDL_SetError("Vulkan can't find a valid physical device (gpu)."); + goto clean; + } /* A display is a video output. 1 GPU can have N displays. Vulkan only counts the connected displays.