mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-27 13:38:29 +00:00
SDL GPU: Implemented opt out Vulkan device features (#13016)
This commit is contained in:
@@ -2254,6 +2254,22 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDevice(
|
||||
* - `SDL_PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING`: the prefix to
|
||||
* use for all vertex semantics, default is "TEXCOORD".
|
||||
*
|
||||
* With the Vulkan renderer:
|
||||
*
|
||||
* - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SHADERCLIPDISTANCE_BOOL`: Enable device feature
|
||||
* shaderClipDistance. If disabled, clip distances are not supported in shader code:
|
||||
* gl_ClipDistance[] built-ins of GLSL, SV_ClipDistance0/1 semantics of HLSL and
|
||||
* [[clip_distance]] attribute of Metal. Defaults to true.
|
||||
* - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DEPTHCLAMP_BOOL`: Enable device feature
|
||||
* depthClamp. If disabled, there is no depth clamp support and enable_depth_clip in
|
||||
* SDL_GPURasterizerState must always be set to true. Defaults to true.
|
||||
* - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DRAWINDIRECTFIRST_BOOL`: Enable device feature
|
||||
* drawIndirectFirstInstance. If disabled, the argument first_instance of
|
||||
* SDL_GPUIndirectDrawCommand must be set to zero. Defaults to true.
|
||||
* - `SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SAMPLERANISOTROPY_BOOL`: Enable device feature
|
||||
* samplerAnisotropy. If disabled, enable_anisotropy of SDL_GPUSamplerCreateInfo must
|
||||
* be set to false. Defaults to true.
|
||||
*
|
||||
* \param props the properties to use.
|
||||
* \returns a GPU context on success or NULL on failure; call SDL_GetError()
|
||||
* for more information.
|
||||
@@ -2279,6 +2295,10 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDeviceWithProperties(
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN "SDL.gpu.device.create.shaders.msl"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN "SDL.gpu.device.create.shaders.metallib"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING "SDL.gpu.device.create.d3d12.semantic"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SHADERCLIPDISTANCE_BOOLEAN "SDL.gpu.device.create.vulkan.shaderclipdistance"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DEPTHCLAMP_BOOLEAN "SDL.gpu.device.create.vulkan.depthclamp"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DRAWINDIRECTFIRST_BOOLEAN "SDL.gpu.device.create.vulkan.drawindirectfirstinstance"
|
||||
#define SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SAMPLERANISOTROPY_BOOLEAN "SDL.gpu.device.create.vulkan.sampleranisotropy"
|
||||
|
||||
/**
|
||||
* Destroys a GPU context previously returned by SDL_CreateGPUDevice.
|
||||
|
@@ -450,7 +450,7 @@ static const SDL_GPUBootstrap * SDL_GPUSelectBackend(SDL_PropertiesID props)
|
||||
SDL_SetError("Required shader format for backend %s not provided!", gpudriver);
|
||||
return NULL;
|
||||
}
|
||||
if (backends[i]->PrepareDriver(_this)) {
|
||||
if (backends[i]->PrepareDriver(_this, props)) {
|
||||
return backends[i];
|
||||
}
|
||||
}
|
||||
@@ -465,7 +465,7 @@ static const SDL_GPUBootstrap * SDL_GPUSelectBackend(SDL_PropertiesID props)
|
||||
// Don't select a backend which doesn't support the app's shaders.
|
||||
continue;
|
||||
}
|
||||
if (backends[i]->PrepareDriver(_this)) {
|
||||
if (backends[i]->PrepareDriver(_this, props)) {
|
||||
return backends[i];
|
||||
}
|
||||
}
|
||||
|
@@ -1142,7 +1142,7 @@ typedef struct SDL_GPUBootstrap
|
||||
{
|
||||
const char *name;
|
||||
const SDL_GPUShaderFormat shader_formats;
|
||||
bool (*PrepareDriver)(SDL_VideoDevice *_this);
|
||||
bool (*PrepareDriver)(SDL_VideoDevice *_this, SDL_PropertiesID props);
|
||||
SDL_GPUDevice *(*CreateDevice)(bool debug_mode, bool prefer_low_power, SDL_PropertiesID props);
|
||||
} SDL_GPUBootstrap;
|
||||
|
||||
|
@@ -8317,7 +8317,7 @@ static void D3D12_INTERNAL_InitBlitResources(
|
||||
}
|
||||
}
|
||||
|
||||
static bool D3D12_PrepareDriver(SDL_VideoDevice *_this)
|
||||
static bool D3D12_PrepareDriver(SDL_VideoDevice *_this, SDL_PropertiesID props)
|
||||
{
|
||||
#if defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)
|
||||
return true;
|
||||
|
@@ -4307,7 +4307,7 @@ static bool METAL_SupportsTextureFormat(
|
||||
|
||||
// Device Creation
|
||||
|
||||
static bool METAL_PrepareDriver(SDL_VideoDevice *this)
|
||||
static bool METAL_PrepareDriver(SDL_VideoDevice *this, SDL_PropertiesID props)
|
||||
{
|
||||
if (@available(macOS 10.14, iOS 13.0, tvOS 13.0, *)) {
|
||||
return (this->Metal_CreateView != NULL);
|
||||
|
@@ -1088,6 +1088,7 @@ struct VulkanRenderer
|
||||
VkPhysicalDevice physicalDevice;
|
||||
VkPhysicalDeviceProperties2KHR physicalDeviceProperties;
|
||||
VkPhysicalDeviceDriverPropertiesKHR physicalDeviceDriverProperties;
|
||||
VkPhysicalDeviceFeatures desiredDeviceFeatures;
|
||||
VkDevice logicalDevice;
|
||||
Uint8 integratedMemoryNotification;
|
||||
Uint8 outOfDeviceLocalMemoryWarning;
|
||||
@@ -11220,12 +11221,14 @@ static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
|
||||
renderer->vkGetPhysicalDeviceFeatures(
|
||||
physicalDevice,
|
||||
&deviceFeatures);
|
||||
if (!deviceFeatures.independentBlend ||
|
||||
!deviceFeatures.imageCubeArray ||
|
||||
!deviceFeatures.depthClamp ||
|
||||
!deviceFeatures.shaderClipDistance ||
|
||||
!deviceFeatures.drawIndirectFirstInstance ||
|
||||
!deviceFeatures.sampleRateShading) {
|
||||
|
||||
if ((!deviceFeatures.independentBlend && renderer->desiredDeviceFeatures.independentBlend) ||
|
||||
(!deviceFeatures.imageCubeArray && renderer->desiredDeviceFeatures.imageCubeArray) ||
|
||||
(!deviceFeatures.depthClamp && renderer->desiredDeviceFeatures.depthClamp) ||
|
||||
(!deviceFeatures.shaderClipDistance && renderer->desiredDeviceFeatures.shaderClipDistance) ||
|
||||
(!deviceFeatures.drawIndirectFirstInstance && renderer->desiredDeviceFeatures.drawIndirectFirstInstance) ||
|
||||
(!deviceFeatures.sampleRateShading && renderer->desiredDeviceFeatures.sampleRateShading) ||
|
||||
(!deviceFeatures.samplerAnisotropy && renderer->desiredDeviceFeatures.samplerAnisotropy)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -11441,7 +11444,6 @@ static Uint8 VULKAN_INTERNAL_CreateLogicalDevice(
|
||||
{
|
||||
VkResult vulkanResult;
|
||||
VkDeviceCreateInfo deviceCreateInfo;
|
||||
VkPhysicalDeviceFeatures desiredDeviceFeatures;
|
||||
VkPhysicalDeviceFeatures haveDeviceFeatures;
|
||||
VkPhysicalDevicePortabilitySubsetFeaturesKHR portabilityFeatures;
|
||||
const char **deviceExtensions;
|
||||
@@ -11465,22 +11467,13 @@ static Uint8 VULKAN_INTERNAL_CreateLogicalDevice(
|
||||
|
||||
// specifying used device features
|
||||
|
||||
SDL_zero(desiredDeviceFeatures);
|
||||
desiredDeviceFeatures.independentBlend = VK_TRUE;
|
||||
desiredDeviceFeatures.samplerAnisotropy = VK_TRUE;
|
||||
desiredDeviceFeatures.imageCubeArray = VK_TRUE;
|
||||
desiredDeviceFeatures.depthClamp = VK_TRUE;
|
||||
desiredDeviceFeatures.shaderClipDistance = VK_TRUE;
|
||||
desiredDeviceFeatures.drawIndirectFirstInstance = VK_TRUE;
|
||||
desiredDeviceFeatures.sampleRateShading = VK_TRUE;
|
||||
|
||||
if (haveDeviceFeatures.fillModeNonSolid) {
|
||||
desiredDeviceFeatures.fillModeNonSolid = VK_TRUE;
|
||||
renderer->desiredDeviceFeatures.fillModeNonSolid = VK_TRUE;
|
||||
renderer->supportsFillModeNonSolid = true;
|
||||
}
|
||||
|
||||
if (haveDeviceFeatures.multiDrawIndirect) {
|
||||
desiredDeviceFeatures.multiDrawIndirect = VK_TRUE;
|
||||
renderer->desiredDeviceFeatures.multiDrawIndirect = VK_TRUE;
|
||||
renderer->supportsMultiDrawIndirect = true;
|
||||
}
|
||||
|
||||
@@ -11521,7 +11514,7 @@ static Uint8 VULKAN_INTERNAL_CreateLogicalDevice(
|
||||
deviceCreateInfo.enabledExtensionCount);
|
||||
CreateDeviceExtensionArray(&renderer->supports, deviceExtensions);
|
||||
deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions;
|
||||
deviceCreateInfo.pEnabledFeatures = &desiredDeviceFeatures;
|
||||
deviceCreateInfo.pEnabledFeatures = &renderer->desiredDeviceFeatures;
|
||||
|
||||
vulkanResult = renderer->vkCreateDevice(
|
||||
renderer->physicalDevice,
|
||||
@@ -11606,7 +11599,7 @@ static bool VULKAN_INTERNAL_PrepareVulkan(
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this)
|
||||
static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this, SDL_PropertiesID props)
|
||||
{
|
||||
// Set up dummy VulkanRenderer
|
||||
VulkanRenderer *renderer;
|
||||
@@ -11622,6 +11615,17 @@ static bool VULKAN_PrepareDriver(SDL_VideoDevice *_this)
|
||||
|
||||
renderer = (VulkanRenderer *)SDL_calloc(1, sizeof(*renderer));
|
||||
if (renderer) {
|
||||
// Opt out device features (higher compatibility in exchange for reduced functionality)
|
||||
renderer->desiredDeviceFeatures.samplerAnisotropy = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SAMPLERANISOTROPY_BOOLEAN, true) ? VK_TRUE : VK_FALSE;
|
||||
renderer->desiredDeviceFeatures.depthClamp = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DEPTHCLAMP_BOOLEAN, true) ? VK_TRUE : VK_FALSE;
|
||||
renderer->desiredDeviceFeatures.shaderClipDistance = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SHADERCLIPDISTANCE_BOOLEAN, true) ? VK_TRUE : VK_FALSE;
|
||||
renderer->desiredDeviceFeatures.drawIndirectFirstInstance = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DRAWINDIRECTFIRST_BOOLEAN, true) ? VK_TRUE : VK_FALSE;
|
||||
|
||||
// These features have near universal support so they are always enabled
|
||||
renderer->desiredDeviceFeatures.independentBlend = VK_TRUE;
|
||||
renderer->desiredDeviceFeatures.sampleRateShading = VK_TRUE;
|
||||
renderer->desiredDeviceFeatures.imageCubeArray = VK_TRUE;
|
||||
|
||||
result = VULKAN_INTERNAL_PrepareVulkan(renderer);
|
||||
if (result) {
|
||||
renderer->vkDestroyInstance(renderer->instance, NULL);
|
||||
@@ -11660,6 +11664,17 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
|
||||
renderer->preferLowPower = preferLowPower;
|
||||
renderer->allowedFramesInFlight = 2;
|
||||
|
||||
// Opt out device features (higher compatibility in exchange for reduced functionality)
|
||||
renderer->desiredDeviceFeatures.samplerAnisotropy = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SAMPLERANISOTROPY_BOOLEAN, true) ? VK_TRUE : VK_FALSE;
|
||||
renderer->desiredDeviceFeatures.depthClamp = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DEPTHCLAMP_BOOLEAN, true) ? VK_TRUE : VK_FALSE;
|
||||
renderer->desiredDeviceFeatures.shaderClipDistance = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_SHADERCLIPDISTANCE_BOOLEAN, true) ? VK_TRUE : VK_FALSE;
|
||||
renderer->desiredDeviceFeatures.drawIndirectFirstInstance = SDL_GetBooleanProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_DRAWINDIRECTFIRST_BOOLEAN, true) ? VK_TRUE : VK_FALSE;
|
||||
|
||||
// These features have near universal support so they are always enabled
|
||||
renderer->desiredDeviceFeatures.independentBlend = VK_TRUE;
|
||||
renderer->desiredDeviceFeatures.sampleRateShading = VK_TRUE;
|
||||
renderer->desiredDeviceFeatures.imageCubeArray = VK_TRUE;
|
||||
|
||||
if (!VULKAN_INTERNAL_PrepareVulkan(renderer)) {
|
||||
SDL_free(renderer);
|
||||
SDL_Vulkan_UnloadLibrary();
|
||||
|
Reference in New Issue
Block a user