From e7be7d844a06bd160f6147e9ecb6aa6bed94769f Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Thu, 9 Jul 2026 17:20:44 -0400
Subject: [PATCH] vulkan: Make SDL_Vulkan_GetInstanceExtensions more robust.
Now it handles NULL `count` params at the higher level, and doesn't explode if
a backend doesn't implement it.
---
src/video/SDL_video.c | 11 +++++
src/video/android/SDL_androidvulkan.c | 4 +-
src/video/cocoa/SDL_cocoavulkan.m | 4 +-
src/video/kmsdrm/SDL_kmsdrmvulkan.c | 4 +-
src/video/offscreen/SDL_offscreenvulkan.c | 50 +++++++++--------------
src/video/uikit/SDL_uikitvulkan.m | 4 +-
src/video/vivante/SDL_vivantevulkan.c | 4 +-
src/video/wayland/SDL_waylandvulkan.c | 5 +--
src/video/windows/SDL_windowsvulkan.c | 4 +-
src/video/x11/SDL_x11vulkan.c | 8 +---
10 files changed, 40 insertions(+), 58 deletions(-)
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 3ae6ea215c454..4ea43ae23d299 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -6315,6 +6315,17 @@ void SDL_Vulkan_UnloadLibrary(void)
char const * const *SDL_Vulkan_GetInstanceExtensions(Uint32 *count)
{
+ Uint32 tmpcount = 0;
+ if (!count) {
+ count = &tmpcount;
+ }
+
+ if (!_this->Vulkan_GetInstanceExtensions) {
+ *count = 0;
+ SDL_Unsupported();
+ return NULL;
+ }
+
return _this->Vulkan_GetInstanceExtensions(_this, count);
}
diff --git a/src/video/android/SDL_androidvulkan.c b/src/video/android/SDL_androidvulkan.c
index 7436c2df5ac80..117f2dbd09a42 100644
--- a/src/video/android/SDL_androidvulkan.c
+++ b/src/video/android/SDL_androidvulkan.c
@@ -115,9 +115,7 @@ char const * const *Android_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
static const char *const extensionsForAndroid[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME
};
- if (count) {
- *count = SDL_arraysize(extensionsForAndroid);
- }
+ *count = SDL_arraysize(extensionsForAndroid);
return extensionsForAndroid;
}
diff --git a/src/video/cocoa/SDL_cocoavulkan.m b/src/video/cocoa/SDL_cocoavulkan.m
index 991d10dbfa15b..74c64733abf41 100644
--- a/src/video/cocoa/SDL_cocoavulkan.m
+++ b/src/video/cocoa/SDL_cocoavulkan.m
@@ -168,9 +168,7 @@ void Cocoa_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
static const char *const extensionsForCocoa[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_METAL_SURFACE_EXTENSION_NAME
};
- if(count) {
- *count = SDL_arraysize(extensionsForCocoa);
- }
+ *count = SDL_arraysize(extensionsForCocoa);
return extensionsForCocoa;
}
diff --git a/src/video/kmsdrm/SDL_kmsdrmvulkan.c b/src/video/kmsdrm/SDL_kmsdrmvulkan.c
index 8fdde581a027b..9d1f8cb003040 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvulkan.c
+++ b/src/video/kmsdrm/SDL_kmsdrmvulkan.c
@@ -152,9 +152,7 @@ char const * const *KMSDRM_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
static const char *const extensionsForKMSDRM[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_DISPLAY_EXTENSION_NAME
};
- if (count) {
- *count = SDL_arraysize(extensionsForKMSDRM);
- }
+ *count = SDL_arraysize(extensionsForKMSDRM);
return extensionsForKMSDRM;
}
diff --git a/src/video/offscreen/SDL_offscreenvulkan.c b/src/video/offscreen/SDL_offscreenvulkan.c
index 79c6f6d12540c..0a5f5c0bc2426 100644
--- a/src/video/offscreen/SDL_offscreenvulkan.c
+++ b/src/video/offscreen/SDL_offscreenvulkan.c
@@ -179,45 +179,35 @@ void OFFSCREEN_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
char const *const *OFFSCREEN_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
Uint32 *count)
{
+ static const char *const returnExtensions[] = { VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME };
+
+ *count = SDL_arraysize(returnExtensions);
+
#if (HEADLESS_SURFACE_EXTENSION_REQUIRED_TO_LOAD == 0)
VkExtensionProperties *enumerateExtensions = NULL;
Uint32 enumerateExtensionCount = 0;
bool hasHeadlessSurfaceExtension = false;
Uint32 i;
-#endif
- static const char *const returnExtensions[] = { VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME };
- if (count) {
-# if (HEADLESS_SURFACE_EXTENSION_REQUIRED_TO_LOAD == 0)
- {
- /* In optional mode, only return VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME if it's already supported by the instance
- There's probably a better way to cache the presence of the extension during OFFSCREEN_Vulkan_LoadLibrary().
- But both SDL_VideoData and SDL_VideoDevice::vulkan_config seem like I'd need to touch a bunch of code to do properly.
- And I want a smaller footprint for the first pass*/
- if ( _this->vulkan_config.vkEnumerateInstanceExtensionProperties ) {
- enumerateExtensions = SDL_Vulkan_CreateInstanceExtensionsList(
- (PFN_vkEnumerateInstanceExtensionProperties)
- _this->vulkan_config.vkEnumerateInstanceExtensionProperties,
- &enumerateExtensionCount);
- for (i = 0; i < enumerateExtensionCount; i++) {
- if (SDL_strcmp(VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, enumerateExtensions[i].extensionName) == 0) {
- hasHeadlessSurfaceExtension = true;
- }
- }
- SDL_free(enumerateExtensions);
- }
- if ( hasHeadlessSurfaceExtension == true ) {
- *count = SDL_arraysize(returnExtensions);
- } else {
- *count = SDL_arraysize(returnExtensions) - 1; // assumes VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME is last
+ /* In optional mode, only return VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME if it's already supported by the instance
+ There's probably a better way to cache the presence of the extension during OFFSCREEN_Vulkan_LoadLibrary().
+ But both SDL_VideoData and SDL_VideoDevice::vulkan_config seem like I'd need to touch a bunch of code to do properly.
+ And I want a smaller footprint for the first pass*/
+ if ( _this->vulkan_config.vkEnumerateInstanceExtensionProperties ) {
+ enumerateExtensions = SDL_Vulkan_CreateInstanceExtensionsList((PFN_vkEnumerateInstanceExtensionProperties) _this->vulkan_config.vkEnumerateInstanceExtensionProperties, &enumerateExtensionCount);
+ for (i = 0; i < enumerateExtensionCount; i++) {
+ if (SDL_strcmp(VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME, enumerateExtensions[i].extensionName) == 0) {
+ hasHeadlessSurfaceExtension = true;
}
}
-# else
- {
- *count = SDL_arraysize(returnExtensions);
- }
-# endif
+ SDL_free(enumerateExtensions);
+ }
+
+ if (!hasHeadlessSurfaceExtension) {
+ (*count)--; // assumes VK_EXT_HEADLESS_SURFACE_EXTENSION_NAME is last
}
+#endif
+
return returnExtensions;
}
diff --git a/src/video/uikit/SDL_uikitvulkan.m b/src/video/uikit/SDL_uikitvulkan.m
index b15621926e5c2..d753654912f41 100644
--- a/src/video/uikit/SDL_uikitvulkan.m
+++ b/src/video/uikit/SDL_uikitvulkan.m
@@ -172,9 +172,7 @@ void UIKit_Vulkan_UnloadLibrary(SDL_VideoDevice *_this)
static const char *const extensionsForUIKit[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_METAL_SURFACE_EXTENSION_NAME
};
- if(count) {
- *count = SDL_arraysize(extensionsForUIKit);
- }
+ *count = SDL_arraysize(extensionsForUIKit);
return extensionsForUIKit;
}
diff --git a/src/video/vivante/SDL_vivantevulkan.c b/src/video/vivante/SDL_vivantevulkan.c
index dc1ec7dc6bff1..d5749d98d5477 100644
--- a/src/video/vivante/SDL_vivantevulkan.c
+++ b/src/video/vivante/SDL_vivantevulkan.c
@@ -122,9 +122,7 @@ char const * const *VIVANTE_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
static const char *const extensionsForVivante[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_DISPLAY_EXTENSION_NAME
};
- if (count) {
- *count = SDL_arraysize(extensionsForVivante);
- }
+ *count = SDL_arraysize(extensionsForVivante);
return extensionsForVivante;
}
diff --git a/src/video/wayland/SDL_waylandvulkan.c b/src/video/wayland/SDL_waylandvulkan.c
index aa1b48e7dcd07..408fcedd8e968 100644
--- a/src/video/wayland/SDL_waylandvulkan.c
+++ b/src/video/wayland/SDL_waylandvulkan.c
@@ -128,10 +128,7 @@ char const * const *Wayland_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME
};
- if (count) {
- *count = SDL_arraysize(extensionsForWayland);
- }
-
+ *count = SDL_arraysize(extensionsForWayland);
return extensionsForWayland;
}
diff --git a/src/video/windows/SDL_windowsvulkan.c b/src/video/windows/SDL_windowsvulkan.c
index 59f43a01824cd..be215abf8d5c4 100644
--- a/src/video/windows/SDL_windowsvulkan.c
+++ b/src/video/windows/SDL_windowsvulkan.c
@@ -115,9 +115,7 @@ char const * const *WIN_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uin
static const char *const extensionsForWin32[] = {
VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_WIN32_SURFACE_EXTENSION_NAME
};
- if (count) {
- *count = SDL_arraysize(extensionsForWin32);
- }
+ *count = SDL_arraysize(extensionsForWin32);
return extensionsForWin32;
}
diff --git a/src/video/x11/SDL_x11vulkan.c b/src/video/x11/SDL_x11vulkan.c
index 11fc05c3bc275..a0f4b5747df7a 100644
--- a/src/video/x11/SDL_x11vulkan.c
+++ b/src/video/x11/SDL_x11vulkan.c
@@ -166,18 +166,14 @@ char const * const *X11_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this, Uin
VK_KHR_SURFACE_EXTENSION_NAME,
VK_KHR_XCB_SURFACE_EXTENSION_NAME,
};
- if(count) {
- *count = SDL_arraysize(extensionsForXCB);
- }
+ *count = SDL_arraysize(extensionsForXCB);
return extensionsForXCB;
} else {
static const char *const extensionsForXlib[] = {
VK_KHR_SURFACE_EXTENSION_NAME,
VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
};
- if(count) {
- *count = SDL_arraysize(extensionsForXlib);
- }
+ *count = SDL_arraysize(extensionsForXlib);
return extensionsForXlib;
}
}