Skip to content

Commit 9dac2f6

Browse files
committed
Handle Vulkan 1.1 features properly
1 parent 9cd9bbd commit 9dac2f6

File tree

2 files changed

+147
-64
lines changed

2 files changed

+147
-64
lines changed

include/SDL3/SDL_gpu.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2355,19 +2355,17 @@ extern SDL_DECLSPEC SDL_GPUDevice * SDLCALL SDL_CreateGPUDeviceWithProperties(
23552355
* A structure specifying additional options when using Vulkan.
23562356
*
23572357
* When no such structure is provided, SDL will use Vulkan API version 1.0 and a minimal set of features.
2358-
* The feature list is only allowed to contain the following structures:
2359-
* - VkPhysicalDeviceFeatures2
2360-
* - VkPhysicalDeviceVulkan11Features
2361-
* - VkPhysicalDeviceVulkan12Features
2362-
* - VkPhysicalDeviceVulkan13Features
2358+
* The feature list gets passed to the vkCreateInstance function and allows requesting additional
2359+
* features.
23632360
*
23642361
* \since This struct is available since SDL 3.4.0.
23652362
*
23662363
*/
23672364
typedef struct SDL_GPUVulkanOptions
23682365
{
23692366
Uint32 vulkan_api_version; /**< The Vulkan API version to request for the instance. Use Vulkan's VK_MAKE_VERSION or VK_MAKE_API_VERSION. */
2370-
void *feature_list; /**< Pointer to the first element of a list of Vulkan physical device feature structs. */
2367+
void *feature_list; /**< Pointer to the first element of a list of structs to be passed to device creation. */
2368+
void *vulkan_10_physical_device_features; /**< Pointer to a VkPhysicalDeviceFeatures struct to enable additional Vulkan 1.0 features. */
23712369
} SDL_GPUVulkanOptions;
23722370

23732371
/**

src/gpu/vulkan/SDL_gpu_vulkan.c

Lines changed: 143 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -11389,77 +11389,162 @@ static void VULKAN_INTERNAL_AddDeviceFeatures(VkBool32 *firstFeature, VkBool32 *
1138911389
}
1139011390
}
1139111391

11392+
static bool VULKAN_INTERNAL_TryAddDeviceFeatures_Vulkan_11(VkPhysicalDeviceFeatures *dst10,
11393+
VkPhysicalDeviceVulkan11Features *dst11,
11394+
VkBaseOutStructure *src)
11395+
{
11396+
bool hasAdded = false;
11397+
switch (src->sType) {
11398+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2:
11399+
{
11400+
VkPhysicalDeviceFeatures2 *newFeatures = (VkPhysicalDeviceFeatures2 *)src;
11401+
VULKAN_INTERNAL_AddDeviceFeatures(&dst10->robustBufferAccess,
11402+
&dst10->inheritedQueries,
11403+
&newFeatures->features.robustBufferAccess);
11404+
hasAdded = true;
11405+
} break;
11406+
11407+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES:
11408+
{
11409+
VkPhysicalDevice16BitStorageFeatures *newFeatures = (VkPhysicalDevice16BitStorageFeatures *)src;
11410+
dst11->storageBuffer16BitAccess |= newFeatures->storageBuffer16BitAccess;
11411+
dst11->uniformAndStorageBuffer16BitAccess |= newFeatures->uniformAndStorageBuffer16BitAccess;
11412+
dst11->storagePushConstant16 |= newFeatures->storagePushConstant16;
11413+
dst11->storageInputOutput16 |= newFeatures->storageInputOutput16;
11414+
hasAdded = true;
11415+
} break;
11416+
11417+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES:
11418+
{
11419+
VkPhysicalDeviceMultiviewFeatures *newFeatures = (VkPhysicalDeviceMultiviewFeatures *)src;
11420+
dst11->multiview |= newFeatures->multiview;
11421+
dst11->multiviewGeometryShader |= newFeatures->multiviewGeometryShader;
11422+
dst11->multiviewTessellationShader |= newFeatures->multiviewTessellationShader;
11423+
hasAdded = true;
11424+
} break;
11425+
11426+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES:
11427+
{
11428+
VkPhysicalDeviceProtectedMemoryFeatures *newFeatures = (VkPhysicalDeviceProtectedMemoryFeatures *)src;
11429+
dst11->protectedMemory |= newFeatures->protectedMemory;
11430+
hasAdded = true;
11431+
} break;
11432+
11433+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES:
11434+
{
11435+
VkPhysicalDeviceSamplerYcbcrConversionFeatures *newFeatures = (VkPhysicalDeviceSamplerYcbcrConversionFeatures *)src;
11436+
dst11->samplerYcbcrConversion |= newFeatures->samplerYcbcrConversion;
11437+
hasAdded = true;
11438+
} break;
11439+
11440+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES:
11441+
{
11442+
VkPhysicalDeviceShaderDrawParametersFeatures *newFeatures = (VkPhysicalDeviceShaderDrawParametersFeatures *)src;
11443+
dst11->shaderDrawParameters |= newFeatures->shaderDrawParameters;
11444+
hasAdded = true;
11445+
} break;
11446+
11447+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES:
11448+
{
11449+
VkPhysicalDeviceVariablePointersFeatures *newFeatures = (VkPhysicalDeviceVariablePointersFeatures *)src;
11450+
dst11->variablePointers |= newFeatures->variablePointers;
11451+
dst11->variablePointersStorageBuffer |= newFeatures->variablePointersStorageBuffer;
11452+
hasAdded = true;
11453+
} break;
11454+
}
11455+
11456+
return hasAdded;
11457+
}
11458+
11459+
static bool VULKAN_INTERNAL_TryAddDeviceFeatures_Vulkan_12_Or_Later(VkPhysicalDeviceFeatures *dst10,
11460+
VkPhysicalDeviceVulkan11Features *dst11,
11461+
VkPhysicalDeviceVulkan12Features *dst12,
11462+
VkPhysicalDeviceVulkan13Features *dst13,
11463+
VkBaseOutStructure *src)
11464+
{
11465+
bool hasAdded = VULKAN_INTERNAL_TryAddDeviceFeatures_Vulkan_11(dst10, dst11, src);
11466+
if (!hasAdded) {
11467+
switch (src->sType) {
11468+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES:
11469+
{
11470+
VkPhysicalDeviceVulkan11Features *newFeatures = (VkPhysicalDeviceVulkan11Features *)src;
11471+
VULKAN_INTERNAL_AddDeviceFeatures(&dst11->storageBuffer16BitAccess,
11472+
&dst11->shaderDrawParameters,
11473+
&newFeatures->storageBuffer16BitAccess);
11474+
hasAdded = true;
11475+
} break;
11476+
11477+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES:
11478+
{
11479+
VkPhysicalDeviceVulkan12Features *newFeatures = (VkPhysicalDeviceVulkan12Features *)src;
11480+
VULKAN_INTERNAL_AddDeviceFeatures(&dst12->samplerMirrorClampToEdge,
11481+
&dst12->subgroupBroadcastDynamicId,
11482+
&newFeatures->samplerMirrorClampToEdge);
11483+
hasAdded = true;
11484+
} break;
11485+
11486+
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES:
11487+
{
11488+
VkPhysicalDeviceVulkan13Features *newFeatures = (VkPhysicalDeviceVulkan13Features *)src;
11489+
VULKAN_INTERNAL_AddDeviceFeatures(&dst13->robustImageAccess,
11490+
&dst13->maintenance4,
11491+
&newFeatures->robustImageAccess);
11492+
hasAdded = true;
11493+
} break;
11494+
}
11495+
}
11496+
11497+
return hasAdded;
11498+
}
11499+
1139211500
static bool VULKAN_INTERNAL_AddOptInVulkanOptions(SDL_PropertiesID props, VulkanRenderer *renderer)
1139311501
{
1139411502
if (SDL_HasProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_OPTIONS_POINTER)) {
1139511503
SDL_GPUVulkanOptions *options = (SDL_GPUVulkanOptions *)SDL_GetPointerProperty(props, SDL_PROP_GPU_DEVICE_CREATE_VULKAN_OPTIONS_POINTER, NULL);
1139611504
if (options) {
1139711505
renderer->usesCustomVulkanOptions = true;
1139811506
renderer->desiredApiVersion = options->vulkan_api_version;
11507+
11508+
SDL_memset(&renderer->desiredVulkan11DeviceFeatures, 0, sizeof(VkPhysicalDeviceVulkan11Features));
11509+
SDL_memset(&renderer->desiredVulkan12DeviceFeatures, 0, sizeof(VkPhysicalDeviceVulkan12Features));
11510+
SDL_memset(&renderer->desiredVulkan13DeviceFeatures, 0, sizeof(VkPhysicalDeviceVulkan13Features));
1139911511
renderer->desiredVulkan11DeviceFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES;
1140011512
renderer->desiredVulkan12DeviceFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES;
1140111513
renderer->desiredVulkan13DeviceFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES;
1140211514

11403-
if (options->feature_list) {
11404-
VkPhysicalDeviceFeatures *vk10Features = &renderer->desiredVulkan10DeviceFeatures;
11405-
VkPhysicalDeviceVulkan11Features *vk11Features = &renderer->desiredVulkan11DeviceFeatures;
11406-
VkPhysicalDeviceVulkan12Features *vk12Features = &renderer->desiredVulkan12DeviceFeatures;
11407-
VkPhysicalDeviceVulkan13Features *vk13Features = &renderer->desiredVulkan13DeviceFeatures;
11408-
11409-
// Iterate through the entire list and combine all requested features
11410-
VkBaseOutStructure *nextStructure = (VkBaseOutStructure *)options->feature_list;
11411-
while (nextStructure) {
11412-
switch (nextStructure->sType) {
11413-
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2:
11414-
{
11415-
VkPhysicalDeviceFeatures2 *newFeatures = (VkPhysicalDeviceFeatures2 *)nextStructure;
11416-
VULKAN_INTERNAL_AddDeviceFeatures(&vk10Features->robustBufferAccess,
11417-
&vk10Features->inheritedQueries,
11418-
&newFeatures->features.robustBufferAccess);
11419-
} break;
11420-
11421-
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES:
11422-
{
11423-
VkPhysicalDeviceVulkan11Features *newFeatures = (VkPhysicalDeviceVulkan11Features *)nextStructure;
11424-
VULKAN_INTERNAL_AddDeviceFeatures(&vk11Features->storageBuffer16BitAccess,
11425-
&vk11Features->shaderDrawParameters,
11426-
&newFeatures->storageBuffer16BitAccess);
11427-
} break;
11428-
11429-
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES:
11430-
{
11431-
VkPhysicalDeviceVulkan12Features *newFeatures = (VkPhysicalDeviceVulkan12Features *)nextStructure;
11432-
VULKAN_INTERNAL_AddDeviceFeatures(&vk12Features->samplerMirrorClampToEdge,
11433-
&vk12Features->subgroupBroadcastDynamicId,
11434-
&newFeatures->samplerMirrorClampToEdge);
11435-
} break;
11436-
11437-
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES:
11438-
{
11439-
VkPhysicalDeviceVulkan13Features *newFeatures = (VkPhysicalDeviceVulkan13Features *)nextStructure;
11440-
VULKAN_INTERNAL_AddDeviceFeatures(&vk13Features->robustImageAccess,
11441-
&vk13Features->maintenance4,
11442-
&newFeatures->robustImageAccess);
11443-
} break;
11444-
11445-
default:
11446-
{
11447-
// It's very important that this routine aborts when an unhandled type is encountered.
11448-
// Not all Vulkan structures (especially Vulkan 1.0 ones) cleanly cast to VkBaseOutStructure.
11449-
// If we don't bail out, nextStructure would get set to some garbage memory location and
11450-
// this loop would do very bad things.
11451-
SDL_LogError(
11452-
SDL_LOG_CATEGORY_GPU,
11453-
"Unhandled Vulkan structure type in requested device feature list! %d",
11454-
nextStructure->sType);
11455-
SDL_SetError(
11456-
"Unhandled Vulkan structure type in requested device feature list! %d",
11457-
nextStructure->sType);
11458-
return false;
11515+
// Handle requested device features
11516+
VkPhysicalDeviceFeatures *vk10Features = &renderer->desiredVulkan10DeviceFeatures;
11517+
VkPhysicalDeviceVulkan11Features *vk11Features = &renderer->desiredVulkan11DeviceFeatures;
11518+
VkPhysicalDeviceVulkan12Features *vk12Features = &renderer->desiredVulkan12DeviceFeatures;
11519+
VkPhysicalDeviceVulkan13Features *vk13Features = &renderer->desiredVulkan13DeviceFeatures;
11520+
11521+
if (options->vulkan_10_physical_device_features) {
11522+
VkPhysicalDeviceFeatures *features = (VkPhysicalDeviceFeatures *)options->vulkan_10_physical_device_features;
11523+
VULKAN_INTERNAL_AddDeviceFeatures(&vk10Features->robustBufferAccess,
11524+
&vk10Features->inheritedQueries,
11525+
&features->robustBufferAccess);
11526+
}
11527+
11528+
bool supportsHigherLevelFeatures = renderer->desiredApiVersion != VK_API_VERSION_1_0;
11529+
if (supportsHigherLevelFeatures && options->feature_list) {
11530+
if (renderer->desiredApiVersion == VK_API_VERSION_1_1) {
11531+
// Iterate through the entire list and combine all requested features
11532+
VkBaseOutStructure *nextStructure = (VkBaseOutStructure *)options->feature_list;
11533+
while (nextStructure) {
11534+
VULKAN_INTERNAL_TryAddDeviceFeatures_Vulkan_11(vk10Features, vk11Features, nextStructure);
11535+
nextStructure = nextStructure->pNext;
1145911536
}
11537+
} else {
11538+
// Iterate through the entire list and combine all requested features
11539+
VkBaseOutStructure *nextStructure = (VkBaseOutStructure *)options->feature_list;
11540+
while (nextStructure) {
11541+
VULKAN_INTERNAL_TryAddDeviceFeatures_Vulkan_12_Or_Later(vk10Features,
11542+
vk11Features,
11543+
vk12Features,
11544+
vk13Features,
11545+
nextStructure);
11546+
nextStructure = nextStructure->pNext;
1146011547
}
11461-
11462-
nextStructure = nextStructure->pNext;
1146311548
}
1146411549
}
1146511550
}

0 commit comments

Comments
 (0)