Add SDL_Vulkan_DestroySurface functionality (#9817)

Added SDL_Vulkan_DestroySurface, its documentation and corresponding platform specific implementations. Fixed some header inclusion orders to improve consistency between platforms. Added TODOs regarding MetalView creation and destruction which will benefit from the new functionality.
This commit is contained in:
Ali Emre Gülcü 2024-05-17 03:41:15 +03:00 committed by GitHub
parent a69eaae32e
commit f17b556c76
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 211 additions and 13 deletions

View file

@ -177,12 +177,40 @@ extern DECLSPEC char const* const* SDLCALL SDL_Vulkan_GetInstanceExtensions(Uint
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_Vulkan_GetInstanceExtensions
* \sa SDL_Vulkan_DestroySurface
*/
extern DECLSPEC SDL_bool SDLCALL SDL_Vulkan_CreateSurface(SDL_Window *window,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR* surface);
/**
* Destroy the Vulkan rendering surface of a window.
*
* This should be called before SDL_DestroyWindow, if SDL_Vulkan_CreateSurface
* was called after SDL_CreateWindow.
*
* The `instance` must have been created with extensions returned by
* SDL_Vulkan_GetInstanceExtensions() enabled and `surface` must have been
* created successfully by an SDL_Vulkan_CreateSurface() call.
*
* If `allocator` is NULL, Vulkan will use the system default allocator. This
* argument is passed directly to Vulkan and isn't used by SDL itself.
*
* \param instance The Vulkan instance handle
* \param surface VkSurfaceKHR handle to destroy
* \param allocator A VkAllocationCallbacks struct, which lets the app set the
* allocator that destroys the surface. Can be NULL.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_Vulkan_GetInstanceExtensions
* \sa SDL_Vulkan_CreateSurface
*/
extern DECLSPEC void SDLCALL SDL_Vulkan_DestroySurface(VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator);
/* @} *//* Vulkan support functions */
/* Ends C function definitions when using C++ */

View file

@ -825,6 +825,7 @@ SDL3_0.0.0 {
SDL_UpdateWindowSurfaceRects;
SDL_UpdateYUVTexture;
SDL_Vulkan_CreateSurface;
SDL_Vulkan_DestroySurface;
SDL_Vulkan_GetInstanceExtensions;
SDL_Vulkan_GetVkGetInstanceProcAddr;
SDL_Vulkan_LoadLibrary;

View file

@ -849,6 +849,7 @@
#define SDL_UpdateWindowSurfaceRects SDL_UpdateWindowSurfaceRects_REAL
#define SDL_UpdateYUVTexture SDL_UpdateYUVTexture_REAL
#define SDL_Vulkan_CreateSurface SDL_Vulkan_CreateSurface_REAL
#define SDL_Vulkan_DestroySurface SDL_Vulkan_DestroySurface_REAL
#define SDL_Vulkan_GetInstanceExtensions SDL_Vulkan_GetInstanceExtensions_REAL
#define SDL_Vulkan_GetVkGetInstanceProcAddr SDL_Vulkan_GetVkGetInstanceProcAddr_REAL
#define SDL_Vulkan_LoadLibrary SDL_Vulkan_LoadLibrary_REAL

View file

@ -869,6 +869,7 @@ SDL_DYNAPI_PROC(int,SDL_UpdateWindowSurface,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_UpdateWindowSurfaceRects,(SDL_Window *a, const SDL_Rect *b, int c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_UpdateYUVTexture,(SDL_Texture *a, const SDL_Rect *b, const Uint8 *c, int d, const Uint8 *e, int f, const Uint8 *g, int h),(a,b,c,d,e,f,g,h),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_Vulkan_CreateSurface,(SDL_Window *a, VkInstance b, const struct VkAllocationCallbacks *c, VkSurfaceKHR *d),(a,b,c,d),return)
SDL_DYNAPI_PROC(void,SDL_Vulkan_DestroySurface,(VkInstance a, VkSurfaceKHR b, const struct VkAllocationCallbacks *c),(a,b,c),)
SDL_DYNAPI_PROC(char const* const*,SDL_Vulkan_GetInstanceExtensions,(Uint32 *a),(a),return)
SDL_DYNAPI_PROC(SDL_FunctionPointer,SDL_Vulkan_GetVkGetInstanceProcAddr,(void),(),return)
SDL_DYNAPI_PROC(int,SDL_Vulkan_LoadLibrary,(const char *a),(a),return)

View file

@ -285,6 +285,7 @@ struct SDL_VideoDevice
void (*Vulkan_UnloadLibrary)(SDL_VideoDevice *_this);
char const* const* (*Vulkan_GetInstanceExtensions)(SDL_VideoDevice *_this, Uint32 *count);
SDL_bool (*Vulkan_CreateSurface)(SDL_VideoDevice *_this, SDL_Window *window, VkInstance instance, const struct VkAllocationCallbacks *allocator, VkSurfaceKHR *surface);
void (*Vulkan_DestroySurface)(SDL_VideoDevice *_this, VkInstance instance, VkSurfaceKHR surface, const struct VkAllocationCallbacks *allocator);
/* * * */
/*

View file

@ -5344,6 +5344,15 @@ SDL_bool SDL_Vulkan_CreateSurface(SDL_Window *window,
return _this->Vulkan_CreateSurface(_this, window, instance, allocator, surface);
}
void SDL_Vulkan_DestroySurface(VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator)
{
if (_this && instance && surface && _this->Vulkan_DestroySurface) {
_this->Vulkan_DestroySurface(_this, instance, surface, allocator);
}
}
SDL_MetalView SDL_Metal_CreateView(SDL_Window *window)
{
CHECK_WINDOW_MAGIC(window, NULL);

View file

@ -67,6 +67,17 @@ extern SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface);
/* Platform independent base function for destroying the Vulkan surface. Unlike surface
* creation, surface destruction doesn't require platform specific extensions like
* VK_KHR_wayland_surface, VK_KHR_android_surface or VK_EXT_metal_surface. The only
* necessary extension is cross platform VK_KHR_surface, which is a dependency to all
* WSI platform extensions, so we can handle surface destruction in an platform-independent
* manner. */
extern void SDL_Vulkan_DestroySurface_Internal(void *vkGetInstanceProcAddr,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator);
#else
/* No SDL Vulkan support, just include the header for typedefs */

View file

@ -467,4 +467,21 @@ error:
return SDL_FALSE;
}
void SDL_Vulkan_DestroySurface_Internal(void *vkGetInstanceProcAddr_,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator)
{
PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
(PFN_vkGetInstanceProcAddr)vkGetInstanceProcAddr_;
PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR =
(PFN_vkDestroySurfaceKHR)vkGetInstanceProcAddr(
instance,
"vkDestroySurfaceKHR");
if (vkDestroySurfaceKHR) {
vkDestroySurfaceKHR(instance, surface, allocator);
}
}
#endif

View file

@ -137,6 +137,7 @@ static SDL_VideoDevice *Android_CreateDevice(void)
device->Vulkan_UnloadLibrary = Android_Vulkan_UnloadLibrary;
device->Vulkan_GetInstanceExtensions = Android_Vulkan_GetInstanceExtensions;
device->Vulkan_CreateSurface = Android_Vulkan_CreateSurface;
device->Vulkan_DestroySurface = Android_Vulkan_DestroySurface;
#endif
/* Screensaver */

View file

@ -162,4 +162,14 @@ SDL_bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this,
return SDL_TRUE;
}
void Android_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator)
{
if (_this->vulkan_config.loader_handle) {
SDL_Vulkan_DestroySurface_Internal(_this->vulkan_config.vkGetInstanceProcAddr, instance, surface, allocator);
}
}
#endif

View file

@ -43,6 +43,10 @@ SDL_bool Android_Vulkan_CreateSurface(SDL_VideoDevice *_this,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface);
void Android_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator);
#endif

View file

@ -161,6 +161,7 @@ static SDL_VideoDevice *Cocoa_CreateDevice(void)
device->Vulkan_UnloadLibrary = Cocoa_Vulkan_UnloadLibrary;
device->Vulkan_GetInstanceExtensions = Cocoa_Vulkan_GetInstanceExtensions;
device->Vulkan_CreateSurface = Cocoa_Vulkan_CreateSurface;
device->Vulkan_DestroySurface = Cocoa_Vulkan_DestroySurface;
#endif
#ifdef SDL_VIDEO_METAL

View file

@ -43,6 +43,10 @@ SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface);
void Cocoa_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator);
#endif

View file

@ -221,7 +221,10 @@ static SDL_bool Cocoa_Vulkan_CreateSurfaceViaMetalView(SDL_VideoDevice *_this,
* Metal_DestroyView from. Right now the metal view's ref count is +2 (one
* from returning a new view object in CreateView, and one because it's
* a subview of the window.) If we release the view here to make it +1, it
* will be destroyed when the window is destroyed. */
* will be destroyed when the window is destroyed.
*
* TODO: Now that we have SDL_Vulkan_DestroySurface someone with enough
* knowledge of Metal can proceed. */
CFBridgingRelease(metalview);
return SDL_TRUE;
@ -297,4 +300,15 @@ SDL_bool Cocoa_Vulkan_CreateSurface(SDL_VideoDevice *_this,
return SDL_TRUE;
}
void Cocoa_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator)
{
if (_this->vulkan_config.loader_handle) {
SDL_Vulkan_DestroySurface_Internal(_this->vulkan_config.vkGetInstanceProcAddr, instance, surface, allocator);
/* TODO: Add CFBridgingRelease(metalview) here perhaps? */
}
}
#endif

View file

@ -310,6 +310,7 @@ static SDL_VideoDevice *KMSDRM_CreateDevice(void)
device->Vulkan_UnloadLibrary = KMSDRM_Vulkan_UnloadLibrary;
device->Vulkan_GetInstanceExtensions = KMSDRM_Vulkan_GetInstanceExtensions;
device->Vulkan_CreateSurface = KMSDRM_Vulkan_CreateSurface;
device->Vulkan_DestroySurface = KMSDRM_Vulkan_DestroySurface;
#endif
device->PumpEvents = KMSDRM_PumpEvents;

View file

@ -505,4 +505,14 @@ clean:
return ret;
}
void KMSDRM_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator)
{
if (_this->vulkan_config.loader_handle) {
SDL_Vulkan_DestroySurface_Internal(_this->vulkan_config.vkGetInstanceProcAddr, instance, surface, allocator);
}
}
#endif

View file

@ -43,6 +43,10 @@ SDL_bool KMSDRM_Vulkan_CreateSurface(SDL_VideoDevice *_this,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface);
void KMSDRM_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator);
#endif

View file

@ -123,6 +123,7 @@ static SDL_VideoDevice *UIKit_CreateDevice(void)
device->Vulkan_UnloadLibrary = UIKit_Vulkan_UnloadLibrary;
device->Vulkan_GetInstanceExtensions = UIKit_Vulkan_GetInstanceExtensions;
device->Vulkan_CreateSurface = UIKit_Vulkan_CreateSurface;
device->Vulkan_DestroySurface = UIKit_Vulkan_DestroySurface;
#endif
#ifdef SDL_VIDEO_METAL

View file

@ -43,6 +43,10 @@ SDL_bool UIKit_Vulkan_CreateSurface(SDL_VideoDevice *_this,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface);
void UIKit_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator);
#endif

View file

@ -248,10 +248,24 @@ SDL_bool UIKit_Vulkan_CreateSurface(SDL_VideoDevice *_this,
* Metal_DestroyView from. Right now the metal view's ref count is +2 (one
* from returning a new view object in CreateView, and one because it's
* a subview of the window.) If we release the view here to make it +1, it
* will be destroyed when the window is destroyed. */
* will be destroyed when the window is destroyed.
*
* TODO: Now that we have SDL_Vulkan_DestroySurface someone with enough
* knowledge of Metal can proceed. */
CFBridgingRelease(metalview);
return SDL_TRUE;
}
void UIKit_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator)
{
if (_this->vulkan_config.loader_handle) {
SDL_Vulkan_DestroySurface_Internal(_this->vulkan_config.vkGetInstanceProcAddr, instance, surface, allocator);
/* TODO: Add CFBridgingRelease(metalview) here perhaps? */
}
}
#endif

View file

@ -95,6 +95,7 @@ static SDL_VideoDevice *VIVANTE_Create()
device->Vulkan_UnloadLibrary = VIVANTE_Vulkan_UnloadLibrary;
device->Vulkan_GetInstanceExtensions = VIVANTE_Vulkan_GetInstanceExtensions;
device->Vulkan_CreateSurface = VIVANTE_Vulkan_CreateSurface;
device->Vulkan_DestroySurface = VIVANTE_Vulkan_DestroySurface;
#endif
device->PumpEvents = VIVANTE_PumpEvents;

View file

@ -142,4 +142,14 @@ SDL_bool VIVANTE_Vulkan_CreateSurface(SDL_VideoDevice *_this,
return SDL_Vulkan_Display_CreateSurface(_this->vulkan_config.vkGetInstanceProcAddr, instance, allocator, surface);
}
void VIVANTE_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator)
{
if (_this->vulkan_config.loader_handle) {
SDL_Vulkan_DestroySurface_Internal(_this->vulkan_config.vkGetInstanceProcAddr, instance, surface, allocator);
}
}
#endif

View file

@ -42,6 +42,10 @@ SDL_bool VIVANTE_Vulkan_CreateSurface(SDL_VideoDevice *_this,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface);
void VIVANTE_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator);
#endif

View file

@ -515,6 +515,7 @@ static SDL_VideoDevice *Wayland_CreateDevice(void)
device->Vulkan_UnloadLibrary = Wayland_Vulkan_UnloadLibrary;
device->Vulkan_GetInstanceExtensions = Wayland_Vulkan_GetInstanceExtensions;
device->Vulkan_CreateSurface = Wayland_Vulkan_CreateSurface;
device->Vulkan_DestroySurface = Wayland_Vulkan_DestroySurface;
#endif
device->free = Wayland_DeleteDevice;

View file

@ -169,4 +169,14 @@ SDL_bool Wayland_Vulkan_CreateSurface(SDL_VideoDevice *_this,
return SDL_TRUE;
}
void Wayland_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator)
{
if (_this->vulkan_config.loader_handle) {
SDL_Vulkan_DestroySurface_Internal(_this->vulkan_config.vkGetInstanceProcAddr, instance, surface, allocator);
}
}
#endif

View file

@ -29,7 +29,7 @@
#ifndef SDL_waylandvulkan_h_
#define SDL_waylandvulkan_h_
#include <SDL3/SDL_vulkan.h>
#include "../SDL_vulkan_internal.h"
#include "../SDL_sysvideo.h"
#if defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_WAYLAND)
@ -43,6 +43,10 @@ SDL_bool Wayland_Vulkan_CreateSurface(SDL_VideoDevice *_this,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface);
void Wayland_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator);
#endif

View file

@ -259,6 +259,7 @@ static SDL_VideoDevice *WIN_CreateDevice(void)
device->Vulkan_UnloadLibrary = WIN_Vulkan_UnloadLibrary;
device->Vulkan_GetInstanceExtensions = WIN_Vulkan_GetInstanceExtensions;
device->Vulkan_CreateSurface = WIN_Vulkan_CreateSurface;
device->Vulkan_DestroySurface = WIN_Vulkan_DestroySurface;
#endif
#if !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES)

View file

@ -160,4 +160,14 @@ SDL_bool WIN_Vulkan_CreateSurface(SDL_VideoDevice *_this,
return SDL_TRUE;
}
void WIN_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator)
{
if (_this->vulkan_config.loader_handle) {
SDL_Vulkan_DestroySurface_Internal(_this->vulkan_config.vkGetInstanceProcAddr, instance, surface, allocator);
}
}
#endif

View file

@ -29,11 +29,11 @@
#ifndef SDL_windowsvulkan_h_
#define SDL_windowsvulkan_h_
#if defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_WINDOWS)
#include "../SDL_vulkan_internal.h"
#include "../SDL_sysvideo.h"
#if defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_WINDOWS)
int WIN_Vulkan_LoadLibrary(SDL_VideoDevice *_this, const char *path);
void WIN_Vulkan_UnloadLibrary(SDL_VideoDevice *_this);
char const* const* WIN_Vulkan_GetInstanceExtensions(SDL_VideoDevice *_this,
@ -43,6 +43,10 @@ SDL_bool WIN_Vulkan_CreateSurface(SDL_VideoDevice *_this,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface);
void WIN_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator);
#endif

View file

@ -279,6 +279,7 @@ static SDL_VideoDevice *X11_CreateDevice(void)
device->Vulkan_UnloadLibrary = X11_Vulkan_UnloadLibrary;
device->Vulkan_GetInstanceExtensions = X11_Vulkan_GetInstanceExtensions;
device->Vulkan_CreateSurface = X11_Vulkan_CreateSurface;
device->Vulkan_DestroySurface = X11_Vulkan_DestroySurface;
#endif
#ifdef SDL_USE_LIBDBUS

View file

@ -230,4 +230,14 @@ SDL_bool X11_Vulkan_CreateSurface(SDL_VideoDevice *_this,
}
}
void X11_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator)
{
if (_this->vulkan_config.loader_handle) {
SDL_Vulkan_DestroySurface_Internal(_this->vulkan_config.vkGetInstanceProcAddr, instance, surface, allocator);
}
}
#endif

View file

@ -23,7 +23,8 @@
#ifndef SDL_x11vulkan_h_
#define SDL_x11vulkan_h_
#include <SDL3/SDL_vulkan.h>
#include "../SDL_vulkan_internal.h"
#include "../SDL_sysvideo.h"
#if defined(SDL_VIDEO_VULKAN) && defined(SDL_VIDEO_DRIVER_X11)
@ -39,6 +40,10 @@ SDL_bool X11_Vulkan_CreateSurface(SDL_VideoDevice *_this,
VkInstance instance,
const struct VkAllocationCallbacks *allocator,
VkSurfaceKHR *surface);
void X11_Vulkan_DestroySurface(SDL_VideoDevice *_this,
VkInstance instance,
VkSurfaceKHR surface,
const struct VkAllocationCallbacks *allocator);
#endif