diff --git a/src/gpu/d3d12/SDL_gpu_d3d12.c b/src/gpu/d3d12/SDL_gpu_d3d12.c index a445b06ccd..62dd797e8f 100644 --- a/src/gpu/d3d12/SDL_gpu_d3d12.c +++ b/src/gpu/d3d12/SDL_gpu_d3d12.c @@ -111,7 +111,7 @@ #define CREATE_DXGI_FACTORY1_FUNC "CreateDXGIFactory1" #define DXGI_GET_DEBUG_INTERFACE_FUNC "DXGIGetDebugInterface" #define D3D12_GET_DEBUG_INTERFACE_FUNC "D3D12GetDebugInterface" -#define WINDOW_PROPERTY_DATA "SDL_GPUD3D12WindowPropertyData" +#define WINDOW_PROPERTY_DATA "SDL.internal.gpu.d3d12.data" #define D3D_FEATURE_LEVEL_CHOICE D3D_FEATURE_LEVEL_11_0 #define D3D_FEATURE_LEVEL_CHOICE_STR "11_0" #define MAX_ROOT_SIGNATURE_PARAMETERS 64 @@ -831,6 +831,8 @@ typedef struct D3D12Sampler typedef struct D3D12WindowData { SDL_Window *window; + D3D12Renderer *renderer; + int refcount; #if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES)) D3D12XBOX_FRAME_PIPELINE_TOKEN frameToken; #else @@ -7081,6 +7083,8 @@ static bool D3D12_ClaimWindow( return false; } windowData->window = window; + windowData->renderer = renderer; + windowData->refcount = 1; if (D3D12_INTERNAL_CreateSwapchain(renderer, windowData, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC)) { SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData); @@ -7101,8 +7105,11 @@ static bool D3D12_ClaimWindow( return true; } else { SDL_free(windowData); - SET_STRING_ERROR_AND_RETURN("Could not create swapchain, failed to claim window!", false); + return false; } + } else if (windowData->renderer == renderer) { + ++windowData->refcount; + return true; } else { SET_STRING_ERROR_AND_RETURN("Window already claimed", false); } @@ -7116,7 +7123,15 @@ static void D3D12_ReleaseWindow( D3D12WindowData *windowData = D3D12_INTERNAL_FetchWindowData(window); if (windowData == NULL) { - SET_STRING_ERROR_AND_RETURN("Window already unclaimed!", ); + return; + } + if (windowData->renderer != renderer) { + SDL_SetError("Window not claimed by this device"); + return; + } + if (windowData->refcount > 1) { + --windowData->refcount; + return; } D3D12_Wait(driverData); diff --git a/src/gpu/metal/SDL_gpu_metal.m b/src/gpu/metal/SDL_gpu_metal.m index d8573f4e44..3bf9d923e9 100644 --- a/src/gpu/metal/SDL_gpu_metal.m +++ b/src/gpu/metal/SDL_gpu_metal.m @@ -31,7 +31,7 @@ // Defines #define METAL_FIRST_VERTEX_BUFFER_SLOT 14 -#define WINDOW_PROPERTY_DATA "SDL_GPUMetalWindowPropertyData" +#define WINDOW_PROPERTY_DATA "SDL.internal.gpu.metal.data" #define SDL_GPU_SHADERSTAGE_COMPUTE 2 #define TRACK_RESOURCE(resource, type, array, count, capacity) \ @@ -423,6 +423,8 @@ static MTLDepthClipMode SDLToMetal_DepthClipMode( // Structs +typedef struct MetalRenderer MetalRenderer; + typedef struct MetalTexture { id handle; @@ -452,6 +454,8 @@ typedef struct MetalFence typedef struct MetalWindowData { SDL_Window *window; + MetalRenderer *renderer; + int refcount; SDL_MetalView view; CAMetalLayer *layer; SDL_GPUPresentMode presentMode; @@ -523,8 +527,6 @@ typedef struct MetalUniformBuffer Uint32 drawOffset; } MetalUniformBuffer; -typedef struct MetalRenderer MetalRenderer; - typedef struct MetalCommandBuffer { CommandBufferCommonHeader common; @@ -3645,7 +3647,7 @@ static bool METAL_SupportsSwapchainComposition( } // This function assumes that it's called from within an autorelease pool -static Uint8 METAL_INTERNAL_CreateSwapchain( +static bool METAL_INTERNAL_CreateSwapchain( MetalRenderer *renderer, MetalWindowData *windowData, SDL_GPUSwapchainComposition swapchainComposition, @@ -3717,7 +3719,7 @@ static Uint8 METAL_INTERNAL_CreateSwapchain( windowData->textureContainer.header.info.width = (Uint32)drawableSize.width; windowData->textureContainer.header.info.height = (Uint32)drawableSize.height; - return 1; + return true; } static bool METAL_SupportsPresentMode( @@ -3747,6 +3749,8 @@ static bool METAL_ClaimWindow( if (windowData == NULL) { windowData = (MetalWindowData *)SDL_calloc(1, sizeof(MetalWindowData)); windowData->window = window; + windowData->renderer = renderer; + windowData->refcount = 1; if (METAL_INTERNAL_CreateSwapchain(renderer, windowData, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC)) { SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData); @@ -3767,10 +3771,13 @@ static bool METAL_ClaimWindow( return true; } else { SDL_free(windowData); - SET_STRING_ERROR_AND_RETURN("Could not create swapchain, failed to claim window", false); + return false; } + } else if (windowData->renderer == renderer) { + ++windowData->refcount; + return true; } else { - SET_ERROR_AND_RETURN("%s", "Window already claimed!", false); + SET_STRING_ERROR_AND_RETURN("Window already claimed", false); } } } @@ -3784,7 +3791,15 @@ static void METAL_ReleaseWindow( MetalWindowData *windowData = METAL_INTERNAL_FetchWindowData(window); if (windowData == NULL) { - SET_STRING_ERROR_AND_RETURN("Window is not claimed by this SDL_GPUDevice", ); + return; + } + if (windowData->renderer != renderer) { + SDL_SetError("Window not claimed by this device"); + return; + } + if (windowData->refcount > 1) { + --windowData->refcount; + return; } METAL_Wait(driverData); diff --git a/src/gpu/vulkan/SDL_gpu_vulkan.c b/src/gpu/vulkan/SDL_gpu_vulkan.c index 693cc5eec7..5d86fc4678 100644 --- a/src/gpu/vulkan/SDL_gpu_vulkan.c +++ b/src/gpu/vulkan/SDL_gpu_vulkan.c @@ -70,7 +70,7 @@ typedef struct VulkanExtensions #define LARGE_ALLOCATION_INCREMENT 67108864 // 64 MiB #define MAX_UBO_SECTION_SIZE 4096 // 4 KiB #define DESCRIPTOR_POOL_SIZE 128 -#define WINDOW_PROPERTY_DATA "SDL_GPUVulkanWindowPropertyData" +#define WINDOW_PROPERTY_DATA "SDL.internal.gpu.vulkan.data" #define IDENTITY_SWIZZLE \ { \ @@ -432,6 +432,8 @@ static VkSamplerAddressMode SDLToVK_SamplerAddressMode[] = { // Structures +typedef struct VulkanRenderer VulkanRenderer; +typedef struct VulkanCommandPool VulkanCommandPool; typedef struct VulkanMemoryAllocation VulkanMemoryAllocation; typedef struct VulkanBuffer VulkanBuffer; typedef struct VulkanBufferContainer VulkanBufferContainer; @@ -666,6 +668,8 @@ typedef struct VulkanFramebuffer typedef struct WindowData { SDL_Window *window; + VulkanRenderer *renderer; + int refcount; SDL_GPUSwapchainComposition swapchainComposition; SDL_GPUPresentMode presentMode; bool needsSwapchainRecreate; @@ -928,10 +932,6 @@ typedef struct VulkanFencePool Uint32 availableFenceCapacity; } VulkanFencePool; -typedef struct VulkanCommandPool VulkanCommandPool; - -typedef struct VulkanRenderer VulkanRenderer; - typedef struct VulkanCommandBuffer { CommandBufferCommonHeader common; @@ -9757,8 +9757,13 @@ static bool VULKAN_ClaimWindow( WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window); if (windowData == NULL) { - windowData = SDL_calloc(1, sizeof(WindowData)); + windowData = (WindowData *)SDL_calloc(1, sizeof(WindowData)); + if (!windowData) { + return false; + } windowData->window = window; + windowData->renderer = renderer; + windowData->refcount = 1; windowData->presentMode = SDL_GPU_PRESENTMODE_VSYNC; windowData->swapchainComposition = SDL_GPU_SWAPCHAINCOMPOSITION_SDR; @@ -9773,18 +9778,14 @@ static bool VULKAN_ClaimWindow( #endif SDL_VideoDevice *videoDevice = SDL_GetVideoDevice(); - if (!videoDevice) - { - SDL_SetError("No video device found!"); + if (!videoDevice) { SDL_free(windowData); - return false; + return SDL_SetError("No video device found"); } - if (!videoDevice->Vulkan_CreateSurface) - { - SDL_SetError("Video device does not have Vulkan_CreateSurface implemented!"); + if (!videoDevice->Vulkan_CreateSurface) { SDL_free(windowData); - return false; + return SDL_SetError("Video device does not implement Vulkan_CreateSurface"); } // Each window must have its own surface. @@ -9794,7 +9795,6 @@ static bool VULKAN_ClaimWindow( renderer->instance, NULL, // FIXME: VAllocationCallbacks &windowData->surface)) { - SDL_SetError("Failed to create Vulkan surface!"); SDL_free(windowData); return false; } @@ -9830,8 +9830,11 @@ static bool VULKAN_ClaimWindow( SDL_free(windowData); return false; } + } else if (windowData->renderer == renderer) { + ++windowData->refcount; + return true; } else { - SET_STRING_ERROR_AND_RETURN("Window already claimed!", false); + SET_STRING_ERROR_AND_RETURN("Window already claimed", false); } } @@ -9846,6 +9849,14 @@ static void VULKAN_ReleaseWindow( if (windowData == NULL) { return; } + if (windowData->renderer != renderer) { + SDL_SetError("Window not claimed by this device"); + return; + } + if (windowData->refcount > 1) { + --windowData->refcount; + return; + } VULKAN_Wait(driverData);