From 899f0fa558c1ee18d1212cfba7123b9f3f1a46f3 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Thu, 23 Sep 2021 11:26:41 +0200 Subject: [PATCH] app: [Android] check for physical devices before creating Vulkan surface The LG K20 doesn't support Vulkan, but has a stub implementation that lets us get so far as to creating a VkSurfaceKHR. However, creating a surface leads to crashes later. This change checks whether any device is available before proceeding. Signed-off-by: Elias Naur --- app/vulkan_android.go | 11 +++++++++++ internal/vk/vulkan.go | 20 ++++++++++++++------ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/app/vulkan_android.go b/app/vulkan_android.go index a3f54fe6e..0ae2bef29 100644 --- a/app/vulkan_android.go +++ b/app/vulkan_android.go @@ -6,6 +6,7 @@ package app import ( + "errors" "unsafe" "gioui.org/gpu" @@ -24,6 +25,16 @@ func init() { if err != nil { return nil, err } + // Some devices (e.g. LG K20) will crash if we create a surface. They + // also don't report any physical devices, so check for that before + // proceeding. + devs, err := vk.EnumeratePhysicalDevices(inst) + if err != nil { + return nil, err + } + if len(devs) == 0 { + return nil, errors.New("vulkan: no physical devices available") + } window, _, _ := w.nativeWindow() surf, err := vk.CreateAndroidSurface(inst, unsafe.Pointer(window)) if err != nil { diff --git a/internal/vk/vulkan.go b/internal/vk/vulkan.go index a6efbcb01..6ef59317a 100644 --- a/internal/vk/vulkan.go +++ b/internal/vk/vulkan.go @@ -816,12 +816,12 @@ func CreateInstance(exts ...string) (Instance, error) { return nil, err } inf := C.VkInstanceCreateInfo{ - sType: C.VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, - enabledExtensionCount: C.uint32_t(len(exts)), + sType: C.VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, } if len(exts) > 0 { cexts := mallocCStringArr(exts) defer freeCStringArr(cexts) + inf.enabledExtensionCount = C.uint32_t(len(exts)) inf.ppEnabledExtensionNames = &cexts[0] } var inst Instance @@ -861,17 +861,25 @@ func GetPhysicalDeviceQueueFamilyProperties(pd PhysicalDevice) []QueueFamilyProp return queues } -func ChoosePhysicalDevice(inst Instance, surf Surface) (PhysicalDevice, int, error) { +func EnumeratePhysicalDevices(inst Instance) ([]PhysicalDevice, error) { var count C.uint32_t if err := vkErr(C.vkEnumeratePhysicalDevices(funcs.vkEnumeratePhysicalDevices, inst, &count, nil)); err != nil { - return nil, 0, fmt.Errorf("vulkan: vkEnumeratePhysicalDevices: %w", err) + return nil, fmt.Errorf("vulkan: vkEnumeratePhysicalDevices: %w", err) } if count == 0 { - return nil, 0, errors.New("vulkan: no devices available") + return nil, nil } devs := make([]C.VkPhysicalDevice, count) if err := vkErr(C.vkEnumeratePhysicalDevices(funcs.vkEnumeratePhysicalDevices, inst, &count, &devs[0])); err != nil { - return nil, 0, fmt.Errorf("vulkan: vkEnumeratePhysicalDevices: %w", err) + return nil, fmt.Errorf("vulkan: vkEnumeratePhysicalDevices: %w", err) + } + return devs, nil +} + +func ChoosePhysicalDevice(inst Instance, surf Surface) (PhysicalDevice, int, error) { + devs, err := EnumeratePhysicalDevices(inst) + if err != nil { + return nil, 0, err } for _, pd := range devs { const caps = C.VK_QUEUE_GRAPHICS_BIT | C.VK_QUEUE_COMPUTE_BIT