Reference count window claim calls for a given GPU device
Fixes https://github.com/libsdl-org/SDL/issues/14918
This commit is contained in:
@@ -111,7 +111,7 @@
|
|||||||
#define CREATE_DXGI_FACTORY1_FUNC "CreateDXGIFactory1"
|
#define CREATE_DXGI_FACTORY1_FUNC "CreateDXGIFactory1"
|
||||||
#define DXGI_GET_DEBUG_INTERFACE_FUNC "DXGIGetDebugInterface"
|
#define DXGI_GET_DEBUG_INTERFACE_FUNC "DXGIGetDebugInterface"
|
||||||
#define D3D12_GET_DEBUG_INTERFACE_FUNC "D3D12GetDebugInterface"
|
#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 D3D_FEATURE_LEVEL_11_0
|
||||||
#define D3D_FEATURE_LEVEL_CHOICE_STR "11_0"
|
#define D3D_FEATURE_LEVEL_CHOICE_STR "11_0"
|
||||||
#define MAX_ROOT_SIGNATURE_PARAMETERS 64
|
#define MAX_ROOT_SIGNATURE_PARAMETERS 64
|
||||||
@@ -831,6 +831,8 @@ typedef struct D3D12Sampler
|
|||||||
typedef struct D3D12WindowData
|
typedef struct D3D12WindowData
|
||||||
{
|
{
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
|
D3D12Renderer *renderer;
|
||||||
|
int refcount;
|
||||||
#if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
|
#if (defined(SDL_PLATFORM_XBOXONE) || defined(SDL_PLATFORM_XBOXSERIES))
|
||||||
D3D12XBOX_FRAME_PIPELINE_TOKEN frameToken;
|
D3D12XBOX_FRAME_PIPELINE_TOKEN frameToken;
|
||||||
#else
|
#else
|
||||||
@@ -7081,6 +7083,8 @@ static bool D3D12_ClaimWindow(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
windowData->window = window;
|
windowData->window = window;
|
||||||
|
windowData->renderer = renderer;
|
||||||
|
windowData->refcount = 1;
|
||||||
|
|
||||||
if (D3D12_INTERNAL_CreateSwapchain(renderer, windowData, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC)) {
|
if (D3D12_INTERNAL_CreateSwapchain(renderer, windowData, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC)) {
|
||||||
SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
|
SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
|
||||||
@@ -7101,8 +7105,11 @@ static bool D3D12_ClaimWindow(
|
|||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
SDL_free(windowData);
|
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 {
|
} else {
|
||||||
SET_STRING_ERROR_AND_RETURN("Window already claimed", false);
|
SET_STRING_ERROR_AND_RETURN("Window already claimed", false);
|
||||||
}
|
}
|
||||||
@@ -7116,7 +7123,15 @@ static void D3D12_ReleaseWindow(
|
|||||||
D3D12WindowData *windowData = D3D12_INTERNAL_FetchWindowData(window);
|
D3D12WindowData *windowData = D3D12_INTERNAL_FetchWindowData(window);
|
||||||
|
|
||||||
if (windowData == NULL) {
|
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);
|
D3D12_Wait(driverData);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
// Defines
|
// Defines
|
||||||
|
|
||||||
#define METAL_FIRST_VERTEX_BUFFER_SLOT 14
|
#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 SDL_GPU_SHADERSTAGE_COMPUTE 2
|
||||||
|
|
||||||
#define TRACK_RESOURCE(resource, type, array, count, capacity) \
|
#define TRACK_RESOURCE(resource, type, array, count, capacity) \
|
||||||
@@ -423,6 +423,8 @@ static MTLDepthClipMode SDLToMetal_DepthClipMode(
|
|||||||
|
|
||||||
// Structs
|
// Structs
|
||||||
|
|
||||||
|
typedef struct MetalRenderer MetalRenderer;
|
||||||
|
|
||||||
typedef struct MetalTexture
|
typedef struct MetalTexture
|
||||||
{
|
{
|
||||||
id<MTLTexture> handle;
|
id<MTLTexture> handle;
|
||||||
@@ -452,6 +454,8 @@ typedef struct MetalFence
|
|||||||
typedef struct MetalWindowData
|
typedef struct MetalWindowData
|
||||||
{
|
{
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
|
MetalRenderer *renderer;
|
||||||
|
int refcount;
|
||||||
SDL_MetalView view;
|
SDL_MetalView view;
|
||||||
CAMetalLayer *layer;
|
CAMetalLayer *layer;
|
||||||
SDL_GPUPresentMode presentMode;
|
SDL_GPUPresentMode presentMode;
|
||||||
@@ -523,8 +527,6 @@ typedef struct MetalUniformBuffer
|
|||||||
Uint32 drawOffset;
|
Uint32 drawOffset;
|
||||||
} MetalUniformBuffer;
|
} MetalUniformBuffer;
|
||||||
|
|
||||||
typedef struct MetalRenderer MetalRenderer;
|
|
||||||
|
|
||||||
typedef struct MetalCommandBuffer
|
typedef struct MetalCommandBuffer
|
||||||
{
|
{
|
||||||
CommandBufferCommonHeader common;
|
CommandBufferCommonHeader common;
|
||||||
@@ -3645,7 +3647,7 @@ static bool METAL_SupportsSwapchainComposition(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This function assumes that it's called from within an autorelease pool
|
// This function assumes that it's called from within an autorelease pool
|
||||||
static Uint8 METAL_INTERNAL_CreateSwapchain(
|
static bool METAL_INTERNAL_CreateSwapchain(
|
||||||
MetalRenderer *renderer,
|
MetalRenderer *renderer,
|
||||||
MetalWindowData *windowData,
|
MetalWindowData *windowData,
|
||||||
SDL_GPUSwapchainComposition swapchainComposition,
|
SDL_GPUSwapchainComposition swapchainComposition,
|
||||||
@@ -3717,7 +3719,7 @@ static Uint8 METAL_INTERNAL_CreateSwapchain(
|
|||||||
windowData->textureContainer.header.info.width = (Uint32)drawableSize.width;
|
windowData->textureContainer.header.info.width = (Uint32)drawableSize.width;
|
||||||
windowData->textureContainer.header.info.height = (Uint32)drawableSize.height;
|
windowData->textureContainer.header.info.height = (Uint32)drawableSize.height;
|
||||||
|
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool METAL_SupportsPresentMode(
|
static bool METAL_SupportsPresentMode(
|
||||||
@@ -3747,6 +3749,8 @@ static bool METAL_ClaimWindow(
|
|||||||
if (windowData == NULL) {
|
if (windowData == NULL) {
|
||||||
windowData = (MetalWindowData *)SDL_calloc(1, sizeof(MetalWindowData));
|
windowData = (MetalWindowData *)SDL_calloc(1, sizeof(MetalWindowData));
|
||||||
windowData->window = window;
|
windowData->window = window;
|
||||||
|
windowData->renderer = renderer;
|
||||||
|
windowData->refcount = 1;
|
||||||
|
|
||||||
if (METAL_INTERNAL_CreateSwapchain(renderer, windowData, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC)) {
|
if (METAL_INTERNAL_CreateSwapchain(renderer, windowData, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC)) {
|
||||||
SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
|
SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
|
||||||
@@ -3767,10 +3771,13 @@ static bool METAL_ClaimWindow(
|
|||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
SDL_free(windowData);
|
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 {
|
} 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);
|
MetalWindowData *windowData = METAL_INTERNAL_FetchWindowData(window);
|
||||||
|
|
||||||
if (windowData == NULL) {
|
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);
|
METAL_Wait(driverData);
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ typedef struct VulkanExtensions
|
|||||||
#define LARGE_ALLOCATION_INCREMENT 67108864 // 64 MiB
|
#define LARGE_ALLOCATION_INCREMENT 67108864 // 64 MiB
|
||||||
#define MAX_UBO_SECTION_SIZE 4096 // 4 KiB
|
#define MAX_UBO_SECTION_SIZE 4096 // 4 KiB
|
||||||
#define DESCRIPTOR_POOL_SIZE 128
|
#define DESCRIPTOR_POOL_SIZE 128
|
||||||
#define WINDOW_PROPERTY_DATA "SDL_GPUVulkanWindowPropertyData"
|
#define WINDOW_PROPERTY_DATA "SDL.internal.gpu.vulkan.data"
|
||||||
|
|
||||||
#define IDENTITY_SWIZZLE \
|
#define IDENTITY_SWIZZLE \
|
||||||
{ \
|
{ \
|
||||||
@@ -432,6 +432,8 @@ static VkSamplerAddressMode SDLToVK_SamplerAddressMode[] = {
|
|||||||
|
|
||||||
// Structures
|
// Structures
|
||||||
|
|
||||||
|
typedef struct VulkanRenderer VulkanRenderer;
|
||||||
|
typedef struct VulkanCommandPool VulkanCommandPool;
|
||||||
typedef struct VulkanMemoryAllocation VulkanMemoryAllocation;
|
typedef struct VulkanMemoryAllocation VulkanMemoryAllocation;
|
||||||
typedef struct VulkanBuffer VulkanBuffer;
|
typedef struct VulkanBuffer VulkanBuffer;
|
||||||
typedef struct VulkanBufferContainer VulkanBufferContainer;
|
typedef struct VulkanBufferContainer VulkanBufferContainer;
|
||||||
@@ -666,6 +668,8 @@ typedef struct VulkanFramebuffer
|
|||||||
typedef struct WindowData
|
typedef struct WindowData
|
||||||
{
|
{
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
|
VulkanRenderer *renderer;
|
||||||
|
int refcount;
|
||||||
SDL_GPUSwapchainComposition swapchainComposition;
|
SDL_GPUSwapchainComposition swapchainComposition;
|
||||||
SDL_GPUPresentMode presentMode;
|
SDL_GPUPresentMode presentMode;
|
||||||
bool needsSwapchainRecreate;
|
bool needsSwapchainRecreate;
|
||||||
@@ -928,10 +932,6 @@ typedef struct VulkanFencePool
|
|||||||
Uint32 availableFenceCapacity;
|
Uint32 availableFenceCapacity;
|
||||||
} VulkanFencePool;
|
} VulkanFencePool;
|
||||||
|
|
||||||
typedef struct VulkanCommandPool VulkanCommandPool;
|
|
||||||
|
|
||||||
typedef struct VulkanRenderer VulkanRenderer;
|
|
||||||
|
|
||||||
typedef struct VulkanCommandBuffer
|
typedef struct VulkanCommandBuffer
|
||||||
{
|
{
|
||||||
CommandBufferCommonHeader common;
|
CommandBufferCommonHeader common;
|
||||||
@@ -9757,8 +9757,13 @@ static bool VULKAN_ClaimWindow(
|
|||||||
WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
|
WindowData *windowData = VULKAN_INTERNAL_FetchWindowData(window);
|
||||||
|
|
||||||
if (windowData == NULL) {
|
if (windowData == NULL) {
|
||||||
windowData = SDL_calloc(1, sizeof(WindowData));
|
windowData = (WindowData *)SDL_calloc(1, sizeof(WindowData));
|
||||||
|
if (!windowData) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
windowData->window = window;
|
windowData->window = window;
|
||||||
|
windowData->renderer = renderer;
|
||||||
|
windowData->refcount = 1;
|
||||||
windowData->presentMode = SDL_GPU_PRESENTMODE_VSYNC;
|
windowData->presentMode = SDL_GPU_PRESENTMODE_VSYNC;
|
||||||
windowData->swapchainComposition = SDL_GPU_SWAPCHAINCOMPOSITION_SDR;
|
windowData->swapchainComposition = SDL_GPU_SWAPCHAINCOMPOSITION_SDR;
|
||||||
|
|
||||||
@@ -9773,18 +9778,14 @@ static bool VULKAN_ClaimWindow(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
SDL_VideoDevice *videoDevice = SDL_GetVideoDevice();
|
SDL_VideoDevice *videoDevice = SDL_GetVideoDevice();
|
||||||
if (!videoDevice)
|
if (!videoDevice) {
|
||||||
{
|
|
||||||
SDL_SetError("No video device found!");
|
|
||||||
SDL_free(windowData);
|
SDL_free(windowData);
|
||||||
return false;
|
return SDL_SetError("No video device found");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!videoDevice->Vulkan_CreateSurface)
|
if (!videoDevice->Vulkan_CreateSurface) {
|
||||||
{
|
|
||||||
SDL_SetError("Video device does not have Vulkan_CreateSurface implemented!");
|
|
||||||
SDL_free(windowData);
|
SDL_free(windowData);
|
||||||
return false;
|
return SDL_SetError("Video device does not implement Vulkan_CreateSurface");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Each window must have its own surface.
|
// Each window must have its own surface.
|
||||||
@@ -9794,7 +9795,6 @@ static bool VULKAN_ClaimWindow(
|
|||||||
renderer->instance,
|
renderer->instance,
|
||||||
NULL, // FIXME: VAllocationCallbacks
|
NULL, // FIXME: VAllocationCallbacks
|
||||||
&windowData->surface)) {
|
&windowData->surface)) {
|
||||||
SDL_SetError("Failed to create Vulkan surface!");
|
|
||||||
SDL_free(windowData);
|
SDL_free(windowData);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -9830,8 +9830,11 @@ static bool VULKAN_ClaimWindow(
|
|||||||
SDL_free(windowData);
|
SDL_free(windowData);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else if (windowData->renderer == renderer) {
|
||||||
|
++windowData->refcount;
|
||||||
|
return true;
|
||||||
} else {
|
} 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) {
|
if (windowData == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (windowData->renderer != renderer) {
|
||||||
|
SDL_SetError("Window not claimed by this device");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (windowData->refcount > 1) {
|
||||||
|
--windowData->refcount;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
VULKAN_Wait(driverData);
|
VULKAN_Wait(driverData);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user