GPU: recreate swapchain on window pixel size change event (#10985)
This commit is contained in:
@@ -3263,7 +3263,7 @@ extern SDL_DECLSPEC bool SDLCALL SDL_WindowSupportsGPUPresentMode(
|
|||||||
* Claims a window, creating a swapchain structure for it.
|
* Claims a window, creating a swapchain structure for it.
|
||||||
*
|
*
|
||||||
* This must be called before SDL_AcquireGPUSwapchainTexture is called using
|
* This must be called before SDL_AcquireGPUSwapchainTexture is called using
|
||||||
* the window.
|
* the window. You should only call this function from the thread that created the window.
|
||||||
*
|
*
|
||||||
* The swapchain will be created with SDL_GPU_SWAPCHAINCOMPOSITION_SDR and
|
* The swapchain will be created with SDL_GPU_SWAPCHAINCOMPOSITION_SDR and
|
||||||
* SDL_GPU_PRESENTMODE_VSYNC. If you want to have different swapchain
|
* SDL_GPU_PRESENTMODE_VSYNC. If you want to have different swapchain
|
||||||
|
|||||||
@@ -482,6 +482,7 @@ typedef struct D3D11WindowData
|
|||||||
DXGI_COLOR_SPACE_TYPE swapchainColorSpace;
|
DXGI_COLOR_SPACE_TYPE swapchainColorSpace;
|
||||||
SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
|
SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
|
||||||
Uint32 frameCounter;
|
Uint32 frameCounter;
|
||||||
|
bool needsSwapchainRecreate;
|
||||||
} D3D11WindowData;
|
} D3D11WindowData;
|
||||||
|
|
||||||
typedef struct D3D11Shader
|
typedef struct D3D11Shader
|
||||||
@@ -5021,6 +5022,18 @@ static D3D11WindowData *D3D11_INTERNAL_FetchWindowData(
|
|||||||
return (D3D11WindowData *)SDL_GetPointerProperty(properties, WINDOW_PROPERTY_DATA, NULL);
|
return (D3D11WindowData *)SDL_GetPointerProperty(properties, WINDOW_PROPERTY_DATA, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool D3D11_INTERNAL_OnWindowResize(void *userdata, SDL_Event *e)
|
||||||
|
{
|
||||||
|
SDL_Window *w = (SDL_Window *)userdata;
|
||||||
|
D3D11WindowData *data;
|
||||||
|
if (e->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED && e->window.windowID == SDL_GetWindowID(w)) {
|
||||||
|
data = D3D11_INTERNAL_FetchWindowData(w);
|
||||||
|
data->needsSwapchainRecreate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool D3D11_INTERNAL_InitializeSwapchainTexture(
|
static bool D3D11_INTERNAL_InitializeSwapchainTexture(
|
||||||
D3D11Renderer *renderer,
|
D3D11Renderer *renderer,
|
||||||
IDXGISwapChain *swapchain,
|
IDXGISwapChain *swapchain,
|
||||||
@@ -5089,7 +5102,6 @@ static bool D3D11_INTERNAL_CreateSwapchain(
|
|||||||
SDL_GPUPresentMode presentMode)
|
SDL_GPUPresentMode presentMode)
|
||||||
{
|
{
|
||||||
HWND dxgiHandle;
|
HWND dxgiHandle;
|
||||||
int width, height;
|
|
||||||
Uint32 i;
|
Uint32 i;
|
||||||
DXGI_SWAP_CHAIN_DESC swapchainDesc;
|
DXGI_SWAP_CHAIN_DESC swapchainDesc;
|
||||||
DXGI_FORMAT swapchainFormat;
|
DXGI_FORMAT swapchainFormat;
|
||||||
@@ -5105,9 +5117,6 @@ static bool D3D11_INTERNAL_CreateSwapchain(
|
|||||||
dxgiHandle = (HWND)windowData->window;
|
dxgiHandle = (HWND)windowData->window;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Get the window size
|
|
||||||
SDL_GetWindowSize(windowData->window, &width, &height);
|
|
||||||
|
|
||||||
swapchainFormat = SwapchainCompositionToTextureFormat[swapchainComposition];
|
swapchainFormat = SwapchainCompositionToTextureFormat[swapchainComposition];
|
||||||
|
|
||||||
// Initialize the swapchain buffer descriptor
|
// Initialize the swapchain buffer descriptor
|
||||||
@@ -5216,6 +5225,10 @@ static bool D3D11_INTERNAL_CreateSwapchain(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int w, h;
|
||||||
|
SDL_SyncWindow(windowData->window);
|
||||||
|
SDL_GetWindowSizeInPixels(windowData->window, &w, &h);
|
||||||
|
|
||||||
// Initialize dummy container, width/height will be filled out in AcquireSwapchainTexture
|
// Initialize dummy container, width/height will be filled out in AcquireSwapchainTexture
|
||||||
SDL_zerop(&windowData->textureContainer);
|
SDL_zerop(&windowData->textureContainer);
|
||||||
windowData->textureContainer.textures = SDL_calloc(1, sizeof(D3D11Texture *));
|
windowData->textureContainer.textures = SDL_calloc(1, sizeof(D3D11Texture *));
|
||||||
@@ -5231,6 +5244,8 @@ static bool D3D11_INTERNAL_CreateSwapchain(
|
|||||||
windowData->textureContainer.header.info.num_levels = 1;
|
windowData->textureContainer.header.info.num_levels = 1;
|
||||||
windowData->textureContainer.header.info.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
windowData->textureContainer.header.info.sample_count = SDL_GPU_SAMPLECOUNT_1;
|
||||||
windowData->textureContainer.header.info.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
|
windowData->textureContainer.header.info.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
|
||||||
|
windowData->textureContainer.header.info.width = w;
|
||||||
|
windowData->textureContainer.header.info.height = h;
|
||||||
|
|
||||||
windowData->texture.container = &windowData->textureContainer;
|
windowData->texture.container = &windowData->textureContainer;
|
||||||
windowData->texture.containerIndex = 0;
|
windowData->texture.containerIndex = 0;
|
||||||
@@ -5240,32 +5255,41 @@ static bool D3D11_INTERNAL_CreateSwapchain(
|
|||||||
|
|
||||||
static bool D3D11_INTERNAL_ResizeSwapchain(
|
static bool D3D11_INTERNAL_ResizeSwapchain(
|
||||||
D3D11Renderer *renderer,
|
D3D11Renderer *renderer,
|
||||||
D3D11WindowData *windowData,
|
D3D11WindowData *windowData)
|
||||||
Sint32 width,
|
|
||||||
Sint32 height)
|
|
||||||
{
|
{
|
||||||
|
D3D11_Wait((SDL_GPURenderer *)renderer);
|
||||||
|
|
||||||
// Release the old RTV
|
// Release the old RTV
|
||||||
ID3D11RenderTargetView_Release(windowData->texture.subresources[0].colorTargetViews[0]);
|
ID3D11RenderTargetView_Release(windowData->texture.subresources[0].colorTargetViews[0]);
|
||||||
SDL_free(windowData->texture.subresources[0].colorTargetViews);
|
SDL_free(windowData->texture.subresources[0].colorTargetViews);
|
||||||
SDL_free(windowData->texture.subresources);
|
SDL_free(windowData->texture.subresources);
|
||||||
|
|
||||||
|
int w, h;
|
||||||
|
SDL_SyncWindow(windowData->window);
|
||||||
|
SDL_GetWindowSizeInPixels(windowData->window, &w, &h);
|
||||||
|
|
||||||
// Resize the swapchain
|
// Resize the swapchain
|
||||||
HRESULT res = IDXGISwapChain_ResizeBuffers(
|
HRESULT res = IDXGISwapChain_ResizeBuffers(
|
||||||
windowData->swapchain,
|
windowData->swapchain,
|
||||||
0, // Keep buffer count the same
|
0, // Keep buffer count the same
|
||||||
width,
|
w,
|
||||||
height,
|
h,
|
||||||
DXGI_FORMAT_UNKNOWN, // Keep the old format
|
DXGI_FORMAT_UNKNOWN, // Keep the old format
|
||||||
renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
|
renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
|
||||||
CHECK_D3D11_ERROR_AND_RETURN("Could not resize swapchain buffers", false);
|
CHECK_D3D11_ERROR_AND_RETURN("Could not resize swapchain buffers", false);
|
||||||
|
|
||||||
// Create the texture object for the swapchain
|
// Create the texture object for the swapchain
|
||||||
return D3D11_INTERNAL_InitializeSwapchainTexture(
|
bool result = D3D11_INTERNAL_InitializeSwapchainTexture(
|
||||||
renderer,
|
renderer,
|
||||||
windowData->swapchain,
|
windowData->swapchain,
|
||||||
windowData->swapchainFormat,
|
windowData->swapchainFormat,
|
||||||
(windowData->swapchainComposition == SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : windowData->swapchainFormat,
|
(windowData->swapchainComposition == SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR) ? DXGI_FORMAT_B8G8R8A8_UNORM_SRGB : windowData->swapchainFormat,
|
||||||
&windowData->texture);
|
&windowData->texture);
|
||||||
|
|
||||||
|
windowData->textureContainer.header.info.width = w;
|
||||||
|
windowData->textureContainer.header.info.height = h;
|
||||||
|
windowData->needsSwapchainRecreate = !result;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool D3D11_SupportsSwapchainComposition(
|
static bool D3D11_SupportsSwapchainComposition(
|
||||||
@@ -5350,14 +5374,13 @@ static bool D3D11_ClaimWindow(
|
|||||||
D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window);
|
D3D11WindowData *windowData = D3D11_INTERNAL_FetchWindowData(window);
|
||||||
|
|
||||||
if (windowData == NULL) {
|
if (windowData == NULL) {
|
||||||
windowData = (D3D11WindowData *)SDL_malloc(sizeof(D3D11WindowData));
|
windowData = (D3D11WindowData *)SDL_calloc(1, sizeof(D3D11WindowData));
|
||||||
windowData->window = window;
|
windowData->window = window;
|
||||||
|
|
||||||
if (D3D11_INTERNAL_CreateSwapchain(renderer, windowData, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC)) {
|
if (D3D11_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);
|
||||||
|
|
||||||
SDL_LockMutex(renderer->windowLock);
|
SDL_LockMutex(renderer->windowLock);
|
||||||
|
|
||||||
if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
|
if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
|
||||||
renderer->claimedWindowCapacity *= 2;
|
renderer->claimedWindowCapacity *= 2;
|
||||||
renderer->claimedWindows = SDL_realloc(
|
renderer->claimedWindows = SDL_realloc(
|
||||||
@@ -5366,9 +5389,10 @@ static bool D3D11_ClaimWindow(
|
|||||||
}
|
}
|
||||||
renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
|
renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
|
||||||
renderer->claimedWindowCount += 1;
|
renderer->claimedWindowCount += 1;
|
||||||
|
|
||||||
SDL_UnlockMutex(renderer->windowLock);
|
SDL_UnlockMutex(renderer->windowLock);
|
||||||
|
|
||||||
|
SDL_AddEventWatch(D3D11_INTERNAL_OnWindowResize, window);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
SDL_free(windowData);
|
SDL_free(windowData);
|
||||||
@@ -5439,6 +5463,7 @@ static void D3D11_ReleaseWindow(
|
|||||||
SDL_free(windowData);
|
SDL_free(windowData);
|
||||||
|
|
||||||
SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA);
|
SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA);
|
||||||
|
SDL_RemoveEventWatch(D3D11_INTERNAL_OnWindowResize, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool D3D11_AcquireSwapchainTexture(
|
static bool D3D11_AcquireSwapchainTexture(
|
||||||
@@ -5449,8 +5474,6 @@ static bool D3D11_AcquireSwapchainTexture(
|
|||||||
D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
|
D3D11CommandBuffer *d3d11CommandBuffer = (D3D11CommandBuffer *)commandBuffer;
|
||||||
D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
|
D3D11Renderer *renderer = (D3D11Renderer *)d3d11CommandBuffer->renderer;
|
||||||
D3D11WindowData *windowData;
|
D3D11WindowData *windowData;
|
||||||
DXGI_SWAP_CHAIN_DESC swapchainDesc;
|
|
||||||
int windowW, windowH;
|
|
||||||
HRESULT res;
|
HRESULT res;
|
||||||
|
|
||||||
*swapchainTexture = NULL;
|
*swapchainTexture = NULL;
|
||||||
@@ -5460,16 +5483,8 @@ static bool D3D11_AcquireSwapchainTexture(
|
|||||||
SET_STRING_ERROR_AND_RETURN("Cannot acquire a swapchain texture from an unclaimed window!", false)
|
SET_STRING_ERROR_AND_RETURN("Cannot acquire a swapchain texture from an unclaimed window!", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for window size changes and resize the swapchain if needed.
|
if (windowData->needsSwapchainRecreate) {
|
||||||
IDXGISwapChain_GetDesc(windowData->swapchain, &swapchainDesc);
|
if (!D3D11_INTERNAL_ResizeSwapchain(renderer, windowData)) {
|
||||||
SDL_GetWindowSize(window, &windowW, &windowH);
|
|
||||||
|
|
||||||
if ((UINT)windowW != swapchainDesc.BufferDesc.Width || (UINT)windowH != swapchainDesc.BufferDesc.Height) {
|
|
||||||
if (!D3D11_INTERNAL_ResizeSwapchain(
|
|
||||||
renderer,
|
|
||||||
windowData,
|
|
||||||
windowW,
|
|
||||||
windowH)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5511,10 +5526,6 @@ static bool D3D11_AcquireSwapchainTexture(
|
|||||||
(void **)&windowData->texture.handle);
|
(void **)&windowData->texture.handle);
|
||||||
CHECK_D3D11_ERROR_AND_RETURN("Could not acquire swapchain!", false);
|
CHECK_D3D11_ERROR_AND_RETURN("Could not acquire swapchain!", false);
|
||||||
|
|
||||||
// Update the texture container dimensions
|
|
||||||
windowData->textureContainer.header.info.width = windowW;
|
|
||||||
windowData->textureContainer.header.info.height = windowH;
|
|
||||||
|
|
||||||
// Set up presentation
|
// Set up presentation
|
||||||
if (d3d11CommandBuffer->windowDataCount == d3d11CommandBuffer->windowDataCapacity) {
|
if (d3d11CommandBuffer->windowDataCount == d3d11CommandBuffer->windowDataCapacity) {
|
||||||
d3d11CommandBuffer->windowDataCapacity += 1;
|
d3d11CommandBuffer->windowDataCapacity += 1;
|
||||||
|
|||||||
@@ -544,7 +544,6 @@ typedef struct D3D12WindowData
|
|||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
#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;
|
||||||
Uint32 swapchainWidth, swapchainHeight;
|
|
||||||
#else
|
#else
|
||||||
IDXGISwapChain3 *swapchain;
|
IDXGISwapChain3 *swapchain;
|
||||||
#endif
|
#endif
|
||||||
@@ -555,6 +554,7 @@ typedef struct D3D12WindowData
|
|||||||
|
|
||||||
D3D12TextureContainer textureContainers[MAX_FRAMES_IN_FLIGHT];
|
D3D12TextureContainer textureContainers[MAX_FRAMES_IN_FLIGHT];
|
||||||
SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
|
SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
|
||||||
|
bool needsSwapchainRecreate;
|
||||||
} D3D12WindowData;
|
} D3D12WindowData;
|
||||||
|
|
||||||
typedef struct D3D12PresentData
|
typedef struct D3D12PresentData
|
||||||
@@ -5973,6 +5973,18 @@ static D3D12WindowData *D3D12_INTERNAL_FetchWindowData(
|
|||||||
return (D3D12WindowData *)SDL_GetPointerProperty(properties, WINDOW_PROPERTY_DATA, NULL);
|
return (D3D12WindowData *)SDL_GetPointerProperty(properties, WINDOW_PROPERTY_DATA, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool D3D12_INTERNAL_OnWindowResize(void *userdata, SDL_Event *e)
|
||||||
|
{
|
||||||
|
SDL_Window *w = (SDL_Window *)userdata;
|
||||||
|
D3D12WindowData *data;
|
||||||
|
if (e->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED && e->window.windowID == SDL_GetWindowID(w)) {
|
||||||
|
data = D3D12_INTERNAL_FetchWindowData(w);
|
||||||
|
data->needsSwapchainRecreate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool D3D12_SupportsSwapchainComposition(
|
static bool D3D12_SupportsSwapchainComposition(
|
||||||
SDL_GPURenderer *driverData,
|
SDL_GPURenderer *driverData,
|
||||||
SDL_Window *window,
|
SDL_Window *window,
|
||||||
@@ -6063,7 +6075,8 @@ static bool D3D12_INTERNAL_CreateSwapchain(
|
|||||||
D3D12Texture *texture;
|
D3D12Texture *texture;
|
||||||
|
|
||||||
// Get the swapchain size
|
// Get the swapchain size
|
||||||
SDL_GetWindowSize(windowData->window, &width, &height);
|
SDL_SyncWindow(windowData->window);
|
||||||
|
SDL_GetWindowSizeInPixels(windowData->window, &width, &height);
|
||||||
|
|
||||||
// Create the swapchain textures
|
// Create the swapchain textures
|
||||||
SDL_zero(createInfo);
|
SDL_zero(createInfo);
|
||||||
@@ -6091,8 +6104,6 @@ static bool D3D12_INTERNAL_CreateSwapchain(
|
|||||||
windowData->swapchainComposition = swapchain_composition;
|
windowData->swapchainComposition = swapchain_composition;
|
||||||
windowData->swapchainColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
|
windowData->swapchainColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709;
|
||||||
windowData->frameCounter = 0;
|
windowData->frameCounter = 0;
|
||||||
windowData->swapchainWidth = width;
|
|
||||||
windowData->swapchainHeight = height;
|
|
||||||
|
|
||||||
// Precache blit pipelines for the swapchain format
|
// Precache blit pipelines for the swapchain format
|
||||||
for (Uint32 i = 0; i < 5; i += 1) {
|
for (Uint32 i = 0; i < 5; i += 1) {
|
||||||
@@ -6126,35 +6137,31 @@ static void D3D12_INTERNAL_DestroySwapchain(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool D3D12_INTERNAL_ResizeSwapchainIfNeeded(
|
static bool D3D12_INTERNAL_ResizeSwapchain(
|
||||||
D3D12Renderer *renderer,
|
D3D12Renderer *renderer,
|
||||||
D3D12WindowData *windowData)
|
D3D12WindowData *windowData)
|
||||||
{
|
{
|
||||||
int w, h;
|
// Wait so we don't release in-flight views
|
||||||
SDL_GetWindowSize(windowData->window, &w, &h);
|
D3D12_Wait((SDL_GPURenderer *)renderer);
|
||||||
|
|
||||||
if (w != windowData->swapchainWidth || h != windowData->swapchainHeight) {
|
// Present a black screen
|
||||||
// Wait so we don't release in-flight views
|
renderer->commandQueue->PresentX(0, NULL, NULL);
|
||||||
D3D12_Wait((SDL_GPURenderer *)renderer);
|
|
||||||
|
|
||||||
// Present a black screen
|
// Clean up the previous swapchain textures
|
||||||
renderer->commandQueue->PresentX(0, NULL, NULL);
|
for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
|
||||||
|
D3D12_INTERNAL_DestroyTexture(
|
||||||
// Clean up the previous swapchain textures
|
|
||||||
for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
|
|
||||||
D3D12_INTERNAL_DestroyTexture(
|
|
||||||
renderer,
|
|
||||||
windowData->textureContainers[i].activeTexture);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new swapchain
|
|
||||||
D3D12_INTERNAL_CreateSwapchain(
|
|
||||||
renderer,
|
renderer,
|
||||||
windowData,
|
windowData->textureContainers[i].activeTexture);
|
||||||
windowData->swapchainComposition,
|
|
||||||
windowData->present_mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a new swapchain
|
||||||
|
D3D12_INTERNAL_CreateSwapchain(
|
||||||
|
renderer,
|
||||||
|
windowData,
|
||||||
|
windowData->swapchainComposition,
|
||||||
|
windowData->present_mode);
|
||||||
|
|
||||||
|
windowData->needsSwapchainRecreate = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -6273,58 +6280,58 @@ static bool D3D12_INTERNAL_InitializeSwapchainTexture(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool D3D12_INTERNAL_ResizeSwapchainIfNeeded(
|
static bool D3D12_INTERNAL_ResizeSwapchain(
|
||||||
D3D12Renderer *renderer,
|
D3D12Renderer *renderer,
|
||||||
D3D12WindowData *windowData)
|
D3D12WindowData *windowData)
|
||||||
{
|
{
|
||||||
DXGI_SWAP_CHAIN_DESC swapchainDesc;
|
// Wait so we don't release in-flight views
|
||||||
|
D3D12_Wait((SDL_GPURenderer *)renderer);
|
||||||
|
|
||||||
|
// Release views and clean up
|
||||||
|
for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
|
||||||
|
D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
|
||||||
|
renderer,
|
||||||
|
&windowData->textureContainers[i].activeTexture->srvHandle);
|
||||||
|
D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
|
||||||
|
renderer,
|
||||||
|
&windowData->textureContainers[i].activeTexture->subresources[0].rtvHandles[0]);
|
||||||
|
|
||||||
|
SDL_free(windowData->textureContainers[i].activeTexture->subresources[0].rtvHandles);
|
||||||
|
SDL_free(windowData->textureContainers[i].activeTexture->subresources);
|
||||||
|
SDL_free(windowData->textureContainers[i].activeTexture);
|
||||||
|
SDL_free(windowData->textureContainers[i].textures);
|
||||||
|
}
|
||||||
|
|
||||||
int w, h;
|
int w, h;
|
||||||
|
SDL_SyncWindow(windowData->window);
|
||||||
|
SDL_GetWindowSizeInPixels(
|
||||||
|
windowData->window,
|
||||||
|
&w,
|
||||||
|
&h);
|
||||||
|
|
||||||
IDXGISwapChain_GetDesc(windowData->swapchain, &swapchainDesc);
|
// Resize the swapchain
|
||||||
SDL_GetWindowSize(windowData->window, &w, &h);
|
HRESULT res = IDXGISwapChain_ResizeBuffers(
|
||||||
|
windowData->swapchain,
|
||||||
|
0, // Keep buffer count the same
|
||||||
|
w,
|
||||||
|
h,
|
||||||
|
DXGI_FORMAT_UNKNOWN, // Keep the old format
|
||||||
|
renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
|
||||||
|
CHECK_D3D12_ERROR_AND_RETURN("Could not resize swapchain buffers", false)
|
||||||
|
|
||||||
if ((UINT)w != swapchainDesc.BufferDesc.Width || (UINT)h != swapchainDesc.BufferDesc.Height) {
|
// Create texture object for the swapchain
|
||||||
// Wait so we don't release in-flight views
|
for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
|
||||||
D3D12_Wait((SDL_GPURenderer *)renderer);
|
if (!D3D12_INTERNAL_InitializeSwapchainTexture(
|
||||||
|
|
||||||
// Release views and clean up
|
|
||||||
for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
|
|
||||||
D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
|
|
||||||
renderer,
|
renderer,
|
||||||
&windowData->textureContainers[i].activeTexture->srvHandle);
|
windowData->swapchain,
|
||||||
D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
|
windowData->swapchainComposition,
|
||||||
renderer,
|
i,
|
||||||
&windowData->textureContainers[i].activeTexture->subresources[0].rtvHandles[0]);
|
&windowData->textureContainers[i])) {
|
||||||
|
return false;
|
||||||
SDL_free(windowData->textureContainers[i].activeTexture->subresources[0].rtvHandles);
|
|
||||||
SDL_free(windowData->textureContainers[i].activeTexture->subresources);
|
|
||||||
SDL_free(windowData->textureContainers[i].activeTexture);
|
|
||||||
SDL_free(windowData->textureContainers[i].textures);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resize the swapchain
|
|
||||||
HRESULT res = IDXGISwapChain_ResizeBuffers(
|
|
||||||
windowData->swapchain,
|
|
||||||
0, // Keep buffer count the same
|
|
||||||
w,
|
|
||||||
h,
|
|
||||||
DXGI_FORMAT_UNKNOWN, // Keep the old format
|
|
||||||
renderer->supportsTearing ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
|
|
||||||
CHECK_D3D12_ERROR_AND_RETURN("Could not resize swapchain buffers", false)
|
|
||||||
|
|
||||||
// Create texture object for the swapchain
|
|
||||||
for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
|
|
||||||
if (!D3D12_INTERNAL_InitializeSwapchainTexture(
|
|
||||||
renderer,
|
|
||||||
windowData->swapchain,
|
|
||||||
windowData->swapchainComposition,
|
|
||||||
i,
|
|
||||||
&windowData->textureContainers[i])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
windowData->needsSwapchainRecreate = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6358,7 +6365,6 @@ static bool D3D12_INTERNAL_CreateSwapchain(
|
|||||||
SDL_GPUPresentMode presentMode)
|
SDL_GPUPresentMode presentMode)
|
||||||
{
|
{
|
||||||
HWND dxgiHandle;
|
HWND dxgiHandle;
|
||||||
int width, height;
|
|
||||||
DXGI_SWAP_CHAIN_DESC1 swapchainDesc;
|
DXGI_SWAP_CHAIN_DESC1 swapchainDesc;
|
||||||
DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreenDesc;
|
DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreenDesc;
|
||||||
DXGI_FORMAT swapchainFormat;
|
DXGI_FORMAT swapchainFormat;
|
||||||
@@ -6374,9 +6380,6 @@ static bool D3D12_INTERNAL_CreateSwapchain(
|
|||||||
dxgiHandle = (HWND)windowData->window;
|
dxgiHandle = (HWND)windowData->window;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Get the window size
|
|
||||||
SDL_GetWindowSize(windowData->window, &width, &height);
|
|
||||||
|
|
||||||
swapchainFormat = SwapchainCompositionToTextureFormat[swapchainComposition];
|
swapchainFormat = SwapchainCompositionToTextureFormat[swapchainComposition];
|
||||||
|
|
||||||
// Initialize the swapchain buffer descriptor
|
// Initialize the swapchain buffer descriptor
|
||||||
@@ -6529,7 +6532,6 @@ static bool D3D12_ClaimWindow(
|
|||||||
SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
|
SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
|
||||||
|
|
||||||
SDL_LockMutex(renderer->windowLock);
|
SDL_LockMutex(renderer->windowLock);
|
||||||
|
|
||||||
if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
|
if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
|
||||||
renderer->claimedWindowCapacity *= 2;
|
renderer->claimedWindowCapacity *= 2;
|
||||||
renderer->claimedWindows = (D3D12WindowData **)SDL_realloc(
|
renderer->claimedWindows = (D3D12WindowData **)SDL_realloc(
|
||||||
@@ -6538,9 +6540,10 @@ static bool D3D12_ClaimWindow(
|
|||||||
}
|
}
|
||||||
renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
|
renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
|
||||||
renderer->claimedWindowCount += 1;
|
renderer->claimedWindowCount += 1;
|
||||||
|
|
||||||
SDL_UnlockMutex(renderer->windowLock);
|
SDL_UnlockMutex(renderer->windowLock);
|
||||||
|
|
||||||
|
SDL_AddEventWatch(D3D12_INTERNAL_OnWindowResize, window);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
SDL_free(windowData);
|
SDL_free(windowData);
|
||||||
@@ -6589,6 +6592,7 @@ static void D3D12_ReleaseWindow(
|
|||||||
|
|
||||||
SDL_free(windowData);
|
SDL_free(windowData);
|
||||||
SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA);
|
SDL_ClearProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA);
|
||||||
|
SDL_RemoveEventWatch(D3D12_INTERNAL_OnWindowResize, window);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool D3D12_SetSwapchainParameters(
|
static bool D3D12_SetSwapchainParameters(
|
||||||
@@ -6918,10 +6922,11 @@ static bool D3D12_AcquireSwapchainTexture(
|
|||||||
SET_STRING_ERROR_AND_RETURN("Cannot acquire swapchain texture from an unclaimed window!", false)
|
SET_STRING_ERROR_AND_RETURN("Cannot acquire swapchain texture from an unclaimed window!", false)
|
||||||
}
|
}
|
||||||
|
|
||||||
res = D3D12_INTERNAL_ResizeSwapchainIfNeeded(
|
if (windowData->needsSwapchainRecreate) {
|
||||||
renderer,
|
if (!D3D12_INTERNAL_ResizeSwapchain(renderer, windowData)) {
|
||||||
windowData);
|
return false;
|
||||||
CHECK_D3D12_ERROR_AND_RETURN("Could not resize swapchain", false);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
|
if (windowData->inFlightFences[windowData->frameCounter] != NULL) {
|
||||||
if (windowData->present_mode == SDL_GPU_PRESENTMODE_VSYNC) {
|
if (windowData->present_mode == SDL_GPU_PRESENTMODE_VSYNC) {
|
||||||
@@ -6932,7 +6937,7 @@ static bool D3D12_AcquireSwapchainTexture(
|
|||||||
&windowData->inFlightFences[windowData->frameCounter],
|
&windowData->inFlightFences[windowData->frameCounter],
|
||||||
1)) {
|
1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!D3D12_QueryFence(
|
if (!D3D12_QueryFence(
|
||||||
(SDL_GPURenderer *)renderer,
|
(SDL_GPURenderer *)renderer,
|
||||||
|
|||||||
@@ -1159,6 +1159,7 @@ struct VulkanRenderer
|
|||||||
SDL_Mutex *acquireUniformBufferLock;
|
SDL_Mutex *acquireUniformBufferLock;
|
||||||
SDL_Mutex *renderPassFetchLock;
|
SDL_Mutex *renderPassFetchLock;
|
||||||
SDL_Mutex *framebufferFetchLock;
|
SDL_Mutex *framebufferFetchLock;
|
||||||
|
SDL_Mutex *windowLock;
|
||||||
|
|
||||||
Uint8 defragInProgress;
|
Uint8 defragInProgress;
|
||||||
|
|
||||||
@@ -4493,35 +4494,6 @@ static bool VULKAN_INTERNAL_CreateSwapchain(
|
|||||||
&drawableWidth,
|
&drawableWidth,
|
||||||
&drawableHeight);
|
&drawableHeight);
|
||||||
|
|
||||||
if (drawableWidth < (Sint32)swapchainSupportDetails.capabilities.minImageExtent.width ||
|
|
||||||
drawableWidth > (Sint32)swapchainSupportDetails.capabilities.maxImageExtent.width ||
|
|
||||||
drawableHeight < (Sint32)swapchainSupportDetails.capabilities.minImageExtent.height ||
|
|
||||||
drawableHeight > (Sint32)swapchainSupportDetails.capabilities.maxImageExtent.height) {
|
|
||||||
if (swapchainSupportDetails.capabilities.currentExtent.width != SDL_MAX_UINT32) {
|
|
||||||
drawableWidth = VULKAN_INTERNAL_clamp(
|
|
||||||
drawableWidth,
|
|
||||||
(Sint32)swapchainSupportDetails.capabilities.minImageExtent.width,
|
|
||||||
(Sint32)swapchainSupportDetails.capabilities.maxImageExtent.width);
|
|
||||||
drawableHeight = VULKAN_INTERNAL_clamp(
|
|
||||||
drawableHeight,
|
|
||||||
(Sint32)swapchainSupportDetails.capabilities.minImageExtent.height,
|
|
||||||
(Sint32)swapchainSupportDetails.capabilities.maxImageExtent.height);
|
|
||||||
} else {
|
|
||||||
renderer->vkDestroySurfaceKHR(
|
|
||||||
renderer->instance,
|
|
||||||
swapchainData->surface,
|
|
||||||
NULL);
|
|
||||||
if (swapchainSupportDetails.formatsLength > 0) {
|
|
||||||
SDL_free(swapchainSupportDetails.formats);
|
|
||||||
}
|
|
||||||
if (swapchainSupportDetails.presentModesLength > 0) {
|
|
||||||
SDL_free(swapchainSupportDetails.presentModes);
|
|
||||||
}
|
|
||||||
SDL_free(swapchainData);
|
|
||||||
SET_STRING_ERROR_AND_RETURN("No fallback swapchain size available!", false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
swapchainData->imageCount = MAX_FRAMES_IN_FLIGHT;
|
swapchainData->imageCount = MAX_FRAMES_IN_FLIGHT;
|
||||||
|
|
||||||
if (swapchainSupportDetails.capabilities.maxImageCount > 0 &&
|
if (swapchainSupportDetails.capabilities.maxImageCount > 0 &&
|
||||||
@@ -4833,6 +4805,7 @@ static void VULKAN_DestroyDevice(
|
|||||||
SDL_DestroyMutex(renderer->acquireUniformBufferLock);
|
SDL_DestroyMutex(renderer->acquireUniformBufferLock);
|
||||||
SDL_DestroyMutex(renderer->renderPassFetchLock);
|
SDL_DestroyMutex(renderer->renderPassFetchLock);
|
||||||
SDL_DestroyMutex(renderer->framebufferFetchLock);
|
SDL_DestroyMutex(renderer->framebufferFetchLock);
|
||||||
|
SDL_DestroyMutex(renderer->windowLock);
|
||||||
|
|
||||||
renderer->vkDestroyDevice(renderer->logicalDevice, NULL);
|
renderer->vkDestroyDevice(renderer->logicalDevice, NULL);
|
||||||
renderer->vkDestroyInstance(renderer->instance, NULL);
|
renderer->vkDestroyInstance(renderer->instance, NULL);
|
||||||
@@ -9356,7 +9329,7 @@ static bool VULKAN_INTERNAL_OnWindowResize(void *userdata, SDL_Event *e)
|
|||||||
{
|
{
|
||||||
SDL_Window *w = (SDL_Window *)userdata;
|
SDL_Window *w = (SDL_Window *)userdata;
|
||||||
WindowData *data;
|
WindowData *data;
|
||||||
if (e->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) {
|
if (e->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED && e->window.windowID == SDL_GetWindowID(w)) {
|
||||||
data = VULKAN_INTERNAL_FetchWindowData(w);
|
data = VULKAN_INTERNAL_FetchWindowData(w);
|
||||||
data->needsSwapchainRecreate = true;
|
data->needsSwapchainRecreate = true;
|
||||||
}
|
}
|
||||||
@@ -9460,6 +9433,7 @@ static bool VULKAN_ClaimWindow(
|
|||||||
if (VULKAN_INTERNAL_CreateSwapchain(renderer, windowData)) {
|
if (VULKAN_INTERNAL_CreateSwapchain(renderer, windowData)) {
|
||||||
SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
|
SDL_SetPointerProperty(SDL_GetWindowProperties(window), WINDOW_PROPERTY_DATA, windowData);
|
||||||
|
|
||||||
|
SDL_LockMutex(renderer->windowLock);
|
||||||
if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
|
if (renderer->claimedWindowCount >= renderer->claimedWindowCapacity) {
|
||||||
renderer->claimedWindowCapacity *= 2;
|
renderer->claimedWindowCapacity *= 2;
|
||||||
renderer->claimedWindows = SDL_realloc(
|
renderer->claimedWindows = SDL_realloc(
|
||||||
@@ -9469,6 +9443,7 @@ static bool VULKAN_ClaimWindow(
|
|||||||
|
|
||||||
renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
|
renderer->claimedWindows[renderer->claimedWindowCount] = windowData;
|
||||||
renderer->claimedWindowCount += 1;
|
renderer->claimedWindowCount += 1;
|
||||||
|
SDL_UnlockMutex(renderer->windowLock);
|
||||||
|
|
||||||
SDL_AddEventWatch(VULKAN_INTERNAL_OnWindowResize, window);
|
SDL_AddEventWatch(VULKAN_INTERNAL_OnWindowResize, window);
|
||||||
|
|
||||||
@@ -9511,6 +9486,7 @@ static void VULKAN_ReleaseWindow(
|
|||||||
windowData);
|
windowData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_LockMutex(renderer->windowLock);
|
||||||
for (i = 0; i < renderer->claimedWindowCount; i += 1) {
|
for (i = 0; i < renderer->claimedWindowCount; i += 1) {
|
||||||
if (renderer->claimedWindows[i]->window == window) {
|
if (renderer->claimedWindows[i]->window == window) {
|
||||||
renderer->claimedWindows[i] = renderer->claimedWindows[renderer->claimedWindowCount - 1];
|
renderer->claimedWindows[i] = renderer->claimedWindows[renderer->claimedWindowCount - 1];
|
||||||
@@ -9518,6 +9494,7 @@ static void VULKAN_ReleaseWindow(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SDL_UnlockMutex(renderer->windowLock);
|
||||||
|
|
||||||
SDL_free(windowData);
|
SDL_free(windowData);
|
||||||
|
|
||||||
@@ -9619,7 +9596,10 @@ static bool VULKAN_AcquireSwapchainTexture(
|
|||||||
|
|
||||||
// If window data marked as needing swapchain recreate, try to recreate
|
// If window data marked as needing swapchain recreate, try to recreate
|
||||||
if (windowData->needsSwapchainRecreate) {
|
if (windowData->needsSwapchainRecreate) {
|
||||||
VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
|
if (!VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
swapchainData = windowData->swapchainData;
|
swapchainData = windowData->swapchainData;
|
||||||
|
|
||||||
if (swapchainData == NULL) {
|
if (swapchainData == NULL) {
|
||||||
@@ -11340,6 +11320,7 @@ static SDL_GPUDevice *VULKAN_CreateDevice(bool debugMode, bool preferLowPower, S
|
|||||||
renderer->acquireUniformBufferLock = SDL_CreateMutex();
|
renderer->acquireUniformBufferLock = SDL_CreateMutex();
|
||||||
renderer->renderPassFetchLock = SDL_CreateMutex();
|
renderer->renderPassFetchLock = SDL_CreateMutex();
|
||||||
renderer->framebufferFetchLock = SDL_CreateMutex();
|
renderer->framebufferFetchLock = SDL_CreateMutex();
|
||||||
|
renderer->windowLock = SDL_CreateMutex();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create submitted command buffer list
|
* Create submitted command buffer list
|
||||||
|
|||||||
Reference in New Issue
Block a user