diff --git a/include/SDL3/SDL_gpu.h b/include/SDL3/SDL_gpu.h index 18ee000869..d3d97b96a7 100644 --- a/include/SDL3/SDL_gpu.h +++ b/include/SDL3/SDL_gpu.h @@ -2307,6 +2307,14 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDevice( * either supports Tier 2 Resource Binding or does not support D3D12 in any * capacity. Defaults to false. * + * With the Vulkan renderer: + * - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_REQUIRE_HARDWARE_ACCELERATION`: By + * default, Vulkan device enumeration includes drivers of all types, including + * software renderers (for example, the Lavapipe Mesa driver). This can be + * useful if your application _requires_ SDL_GPU, but if you can provide your + * own fallback renderer (for example, an OpenGL renderer) this property can + * be set to true. Defaults to false. + * * \param props the properties to use. * \returns a GPU context on success or NULL on failure; call SDL_GetError() * for more information. @@ -2337,6 +2345,7 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDeviceWithProperties( #define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN "SDL.gpu.device.create.shaders.metallib" #define SDL_PROP_GPU_DEVICE_CREATE_D3D12_ALLOW_FEWER_RESOURCE_SLOTS_BOOLEAN "SDL.gpu.device.create.d3d12.allowtier1resourcebinding" #define SDL_PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING "SDL.gpu.device.create.d3d12.semantic" +#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_REQUIRE_HARDWARE_ACCELERATION "SDL.gpu.device.create.vulkan.requirehardwareacceleration" /** * Destroys a GPU context previously returned by SDL_CreateGPUDevice. diff --git a/src/gpu/vulkan/SDL_gpu_vulkan.c b/src/gpu/vulkan/SDL_gpu_vulkan.c index 6dfb9c4624..3db3e25859 100644 --- a/src/gpu/vulkan/SDL_gpu_vulkan.c +++ b/src/gpu/vulkan/SDL_gpu_vulkan.c @@ -1096,6 +1096,7 @@ struct VulkanRenderer bool debugMode; bool preferLowPower; + bool requireHardwareAcceleration; SDL_PropertiesID props; Uint32 allowedFramesInFlight; @@ -11343,6 +11344,15 @@ static bool VULKAN_INTERNAL_GetDeviceRank( deviceType = physicalDeviceProperties.deviceType; } + if (renderer->requireHardwareAcceleration) { + if (deviceType != VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU && + deviceType != VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU && + deviceType != VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU) { + // In addition to CPU, "Other" drivers (including layered drivers) don't count as hardware-accelerated + return 0; + } + } + /* Apply a large bias on the devicePriority so that we always respect the order in the priority arrays. * We also rank by e.g. VRAM which should have less influence than the device type. */ @@ -11818,6 +11828,8 @@ static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this, SDL_PropertiesID props) renderer->desiredDeviceFeatures.sampleRateShading = VK_TRUE; renderer->desiredDeviceFeatures.imageCubeArray = VK_TRUE; + renderer->requireHardwareAcceleration = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_REQUIRE_HARDWARE_ACCELERATION, false); + result = VULKAN_INTERNAL_PrepareVulkan(renderer); if (result) { renderer->vkDestroyInstance(renderer->instance, NULL); @@ -11867,6 +11879,8 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S renderer->desiredDeviceFeatures.sampleRateShading = VK_TRUE; renderer->desiredDeviceFeatures.imageCubeArray = VK_TRUE; + renderer->requireHardwareAcceleration = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_REQUIRE_HARDWARE_ACCELERATION, false); + if (!VULKAN_INTERNAL_PrepareVulkan(renderer)) { SET_STRING_ERROR("Failed to initialize Vulkan!"); SDL_free(renderer);