Skip to content

Commit f85f83e

Browse files
authored
SDL GPU: Implemented opt out Vulkan device features (#13016)
1 parent 1eeffc5 commit f85f83e

File tree

6 files changed

+71
-36
lines changed

6 files changed

+71
-36
lines changed

include/SDL3/SDL_gpu.h

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2254,6 +2254,22 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDevice(
22542254
* - `SDL_PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING`: the prefix to
22552255
* use for all vertex semantics, default is "TEXCOORD".
22562256
*
2257+
* With the Vulkan renderer:
2258+
*
2259+
* - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SHADERCLIPDISTANCE_BOOL`: Enable device feature
2260+
* shaderClipDistance. If disabled, clip distances are not supported in shader code:
2261+
* gl_ClipDistance[] built-ins of GLSL, SV_ClipDistance0/1 semantics of HLSL and
2262+
* [[clip_distance]] attribute of Metal. Defaults to true.
2263+
* - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DEPTHCLAMP_BOOL`: Enable device feature
2264+
* depthClamp. If disabled, there is no depth clamp support and enable_depth_clip in
2265+
* SDL_GPURasterizerState must always be set to true. Defaults to true.
2266+
* - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DRAWINDIRECTFIRST_BOOL`: Enable device feature
2267+
* drawIndirectFirstInstance. If disabled, the argument first_instance of
2268+
* SDL_GPUIndirectDrawCommand must be set to zero. Defaults to true.
2269+
* - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SAMPLERANISOTROPY_BOOL`: Enable device feature
2270+
* samplerAnisotropy. If disabled, enable_anisotropy of SDL_GPUSamplerCreateInfo must
2271+
* be set to false. Defaults to true.
2272+
*
22572273
* \param props the properties to use.
22582274
* \returns a GPU context on success or NULL on failure; call SDL_GetError()
22592275
* for more information.
@@ -2268,17 +2284,21 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDevice(
22682284
extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDeviceWithProperties(
22692285
SDL_PropertiesID props);
22702286

2271-
#define SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN "SDL.gpu.device.create.debugmode"
2272-
#define SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOLEAN "SDL.gpu.device.create.preferlowpower"
2273-
#define SDL_PROP_GPU_DEVICE_CREATE_VERBOSE_BOOLEAN "SDL.gpu.device.create.verbose"
2274-
#define SDL_PROP_GPU_DEVICE_CREATE_NAME_STRING "SDL.gpu.device.create.name"
2275-
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_PRIVATE_BOOLEAN "SDL.gpu.device.create.shaders.private"
2276-
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOLEAN "SDL.gpu.device.create.shaders.spirv"
2277-
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXBC_BOOLEAN "SDL.gpu.device.create.shaders.dxbc"
2278-
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOLEAN "SDL.gpu.device.create.shaders.dxil"
2279-
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN "SDL.gpu.device.create.shaders.msl"
2280-
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN "SDL.gpu.device.create.shaders.metallib"
2281-
#define SDL_PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING "SDL.gpu.device.create.d3d12.semantic"
2287+
#define SDL_PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN "SDL.gpu.device.create.debugmode"
2288+
#define SDL_PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOLEAN "SDL.gpu.device.create.preferlowpower"
2289+
#define SDL_PROP_GPU_DEVICE_CREATE_VERBOSE_BOOLEAN "SDL.gpu.device.create.verbose"
2290+
#define SDL_PROP_GPU_DEVICE_CREATE_NAME_STRING "SDL.gpu.device.create.name"
2291+
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_PRIVATE_BOOLEAN "SDL.gpu.device.create.shaders.private"
2292+
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOLEAN "SDL.gpu.device.create.shaders.spirv"
2293+
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXBC_BOOLEAN "SDL.gpu.device.create.shaders.dxbc"
2294+
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOLEAN "SDL.gpu.device.create.shaders.dxil"
2295+
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN "SDL.gpu.device.create.shaders.msl"
2296+
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN "SDL.gpu.device.create.shaders.metallib"
2297+
#define SDL_PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING "SDL.gpu.device.create.d3d12.semantic"
2298+
#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SHADERCLIPDISTANCE_BOOLEAN "SDL.gpu.device.create.vulkan.shaderclipdistance"
2299+
#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DEPTHCLAMP_BOOLEAN "SDL.gpu.device.create.vulkan.depthclamp"
2300+
#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DRAWINDIRECTFIRST_BOOLEAN "SDL.gpu.device.create.vulkan.drawindirectfirstinstance"
2301+
#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SAMPLERANISOTROPY_BOOLEAN "SDL.gpu.device.create.vulkan.sampleranisotropy"
22822302

22832303
/**
22842304
* Destroys a GPU context previously returned by SDL_CreateGPUDevice.

src/gpu/SDL_gpu.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ static const SDL_GPUBootstrap * SDL_GPUSelectBackend(SDL_PropertiesID props)
450450
SDL_SetError("Required shader format for backend %s not provided!", gpudriver);
451451
return NULL;
452452
}
453-
if (backends[i]->PrepareDriver(_this)) {
453+
if (backends[i]->PrepareDriver(_this, props)) {
454454
return backends[i];
455455
}
456456
}
@@ -465,7 +465,7 @@ static const SDL_GPUBootstrap * SDL_GPUSelectBackend(SDL_PropertiesID props)
465465
// Don't select a backend which doesn't support the app's shaders.
466466
continue;
467467
}
468-
if (backends[i]->PrepareDriver(_this)) {
468+
if (backends[i]->PrepareDriver(_this, props)) {
469469
return backends[i];
470470
}
471471
}

src/gpu/SDL_sysgpu.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1142,7 +1142,7 @@ typedef struct SDL_GPUBootstrap
11421142
{
11431143
const char *name;
11441144
const SDL_GPUShaderFormat shader_formats;
1145-
bool (*PrepareDriver)(SDL_VideoDevice *_this);
1145+
bool (*PrepareDriver)(SDL_VideoDevice *_this, SDL_PropertiesID props);
11461146
SDL_GPUDevice *(*CreateDevice)(bool debug_mode, bool prefer_low_power, SDL_PropertiesID props);
11471147
} SDL_GPUBootstrap;
11481148

src/gpu/d3d12/SDL_gpu_d3d12.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8317,7 +8317,7 @@ static void D3D12_INTERNAL_InitBlitResources(
83178317
}
83188318
}
83198319

8320-
static bool D3D12_PrepareDriver(SDL_VideoDevice *_this)
8320+
static bool D3D12_PrepareDriver(SDL_VideoDevice *_this, SDL_PropertiesID props)
83218321
{
83228322
#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
83238323
return true;

src/gpu/metal/SDL_gpu_metal.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4307,7 +4307,7 @@ static bool METAL_SupportsTextureFormat(
43074307

43084308
// Device Creation
43094309

4310-
static bool METAL_PrepareDriver(SDL_VideoDevice *this)
4310+
static bool METAL_PrepareDriver(SDL_VideoDevice *this, SDL_PropertiesID props)
43114311
{
43124312
if (@available(macOS 10.14, iOS 13.0, tvOS 13.0, *)) {
43134313
return (this->Metal_CreateView != NULL);

src/gpu/vulkan/SDL_gpu_vulkan.c

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,7 @@ struct VulkanRenderer
10881088
VkPhysicalDevice physicalDevice;
10891089
VkPhysicalDeviceProperties2KHR physicalDeviceProperties;
10901090
VkPhysicalDeviceDriverPropertiesKHR physicalDeviceDriverProperties;
1091+
VkPhysicalDeviceFeatures desiredDeviceFeatures;
10911092
VkDevice logicalDevice;
10921093
Uint8 integratedMemoryNotification;
10931094
Uint8 outOfDeviceLocalMemoryWarning;
@@ -11220,12 +11221,14 @@ static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
1122011221
renderer->vkGetPhysicalDeviceFeatures(
1122111222
physicalDevice,
1122211223
&deviceFeatures);
11223-
if (!deviceFeatures.independentBlend ||
11224-
!deviceFeatures.imageCubeArray ||
11225-
!deviceFeatures.depthClamp ||
11226-
!deviceFeatures.shaderClipDistance ||
11227-
!deviceFeatures.drawIndirectFirstInstance ||
11228-
!deviceFeatures.sampleRateShading) {
11224+
11225+
if ((!deviceFeatures.independentBlend && renderer->desiredDeviceFeatures.independentBlend) ||
11226+
(!deviceFeatures.imageCubeArray && renderer->desiredDeviceFeatures.imageCubeArray) ||
11227+
(!deviceFeatures.depthClamp && renderer->desiredDeviceFeatures.depthClamp) ||
11228+
(!deviceFeatures.shaderClipDistance && renderer->desiredDeviceFeatures.shaderClipDistance) ||
11229+
(!deviceFeatures.drawIndirectFirstInstance && renderer->desiredDeviceFeatures.drawIndirectFirstInstance) ||
11230+
(!deviceFeatures.sampleRateShading && renderer->desiredDeviceFeatures.sampleRateShading) ||
11231+
(!deviceFeatures.samplerAnisotropy && renderer->desiredDeviceFeatures.samplerAnisotropy)) {
1122911232
return 0;
1123011233
}
1123111234

@@ -11441,7 +11444,6 @@ static Uint8 VULKAN_INTERNAL_CreateLogicalDevice(
1144111444
{
1144211445
VkResult vulkanResult;
1144311446
VkDeviceCreateInfo deviceCreateInfo;
11444-
VkPhysicalDeviceFeatures desiredDeviceFeatures;
1144511447
VkPhysicalDeviceFeatures haveDeviceFeatures;
1144611448
VkPhysicalDevicePortabilitySubsetFeaturesKHR portabilityFeatures;
1144711449
const char **deviceExtensions;
@@ -11465,22 +11467,13 @@ static Uint8 VULKAN_INTERNAL_CreateLogicalDevice(
1146511467

1146611468
// specifying used device features
1146711469

11468-
SDL_zero(desiredDeviceFeatures);
11469-
desiredDeviceFeatures.independentBlend = VK_TRUE;
11470-
desiredDeviceFeatures.samplerAnisotropy = VK_TRUE;
11471-
desiredDeviceFeatures.imageCubeArray = VK_TRUE;
11472-
desiredDeviceFeatures.depthClamp = VK_TRUE;
11473-
desiredDeviceFeatures.shaderClipDistance = VK_TRUE;
11474-
desiredDeviceFeatures.drawIndirectFirstInstance = VK_TRUE;
11475-
desiredDeviceFeatures.sampleRateShading = VK_TRUE;
11476-
1147711470
if (haveDeviceFeatures.fillModeNonSolid) {
11478-
desiredDeviceFeatures.fillModeNonSolid = VK_TRUE;
11471+
renderer->desiredDeviceFeatures.fillModeNonSolid = VK_TRUE;
1147911472
renderer->supportsFillModeNonSolid = true;
1148011473
}
1148111474

1148211475
if (haveDeviceFeatures.multiDrawIndirect) {
11483-
desiredDeviceFeatures.multiDrawIndirect = VK_TRUE;
11476+
renderer->desiredDeviceFeatures.multiDrawIndirect = VK_TRUE;
1148411477
renderer->supportsMultiDrawIndirect = true;
1148511478
}
1148611479

@@ -11521,7 +11514,7 @@ static Uint8 VULKAN_INTERNAL_CreateLogicalDevice(
1152111514
deviceCreateInfo.enabledExtensionCount);
1152211515
CreateDeviceExtensionArray(&renderer->supports, deviceExtensions);
1152311516
deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions;
11524-
deviceCreateInfo.pEnabledFeatures = &desiredDeviceFeatures;
11517+
deviceCreateInfo.pEnabledFeatures = &renderer->desiredDeviceFeatures;
1152511518

1152611519
vulkanResult = renderer->vkCreateDevice(
1152711520
renderer->physicalDevice,
@@ -11606,7 +11599,7 @@ static bool VULKAN_INTERNAL_PrepareVulkan(
1160611599
return true;
1160711600
}
1160811601

11609-
static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this)
11602+
static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this, SDL_PropertiesID props)
1161011603
{
1161111604
// Set up dummy VulkanRenderer
1161211605
VulkanRenderer *renderer;
@@ -11622,6 +11615,17 @@ static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this)
1162211615

1162311616
renderer = (VulkanRenderer *)SDL_calloc(1, sizeof(*renderer));
1162411617
if (renderer) {
11618+
// Opt out device features (higher compatibility in exchange for reduced functionality)
11619+
renderer->desiredDeviceFeatures.samplerAnisotropy = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SAMPLERANISOTROPY_BOOLEAN, true) ? VK_TRUE : VK_FALSE;
11620+
renderer->desiredDeviceFeatures.depthClamp = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DEPTHCLAMP_BOOLEAN, true) ? VK_TRUE : VK_FALSE;
11621+
renderer->desiredDeviceFeatures.shaderClipDistance = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SHADERCLIPDISTANCE_BOOLEAN, true) ? VK_TRUE : VK_FALSE;
11622+
renderer->desiredDeviceFeatures.drawIndirectFirstInstance = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DRAWINDIRECTFIRST_BOOLEAN, true) ? VK_TRUE : VK_FALSE;
11623+
11624+
// These features have near universal support so they are always enabled
11625+
renderer->desiredDeviceFeatures.independentBlend = VK_TRUE;
11626+
renderer->desiredDeviceFeatures.sampleRateShading = VK_TRUE;
11627+
renderer->desiredDeviceFeatures.imageCubeArray = VK_TRUE;
11628+
1162511629
result = VULKAN_INTERNAL_PrepareVulkan(renderer);
1162611630
if (result) {
1162711631
renderer->vkDestroyInstance(renderer->instance, NULL);
@@ -11660,6 +11664,17 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
1166011664
renderer->preferLowPower = preferLowPower;
1166111665
renderer->allowedFramesInFlight = 2;
1166211666

11667+
// Opt out device features (higher compatibility in exchange for reduced functionality)
11668+
renderer->desiredDeviceFeatures.samplerAnisotropy = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SAMPLERANISOTROPY_BOOLEAN, true) ? VK_TRUE : VK_FALSE;
11669+
renderer->desiredDeviceFeatures.depthClamp = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DEPTHCLAMP_BOOLEAN, true) ? VK_TRUE : VK_FALSE;
11670+
renderer->desiredDeviceFeatures.shaderClipDistance = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SHADERCLIPDISTANCE_BOOLEAN, true) ? VK_TRUE : VK_FALSE;
11671+
renderer->desiredDeviceFeatures.drawIndirectFirstInstance = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DRAWINDIRECTFIRST_BOOLEAN, true) ? VK_TRUE : VK_FALSE;
11672+
11673+
// These features have near universal support so they are always enabled
11674+
renderer->desiredDeviceFeatures.independentBlend = VK_TRUE;
11675+
renderer->desiredDeviceFeatures.sampleRateShading = VK_TRUE;
11676+
renderer->desiredDeviceFeatures.imageCubeArray = VK_TRUE;
11677+
1166311678
if (!VULKAN_INTERNAL_PrepareVulkan(renderer)) {
1166411679
SDL_free(renderer);
1166511680
SDL_Vulkan_UnloadLibrary();

0 commit comments

Comments
 (0)