mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-06-02 23:57:45 +08:00
GPU: Swapchain image count respects number of allowed frames in flight
This commit is contained in:
@@ -708,6 +708,8 @@ typedef struct D3D12WindowData
|
|||||||
Uint32 frameCounter;
|
Uint32 frameCounter;
|
||||||
|
|
||||||
D3D12TextureContainer textureContainers[MAX_FRAMES_IN_FLIGHT];
|
D3D12TextureContainer textureContainers[MAX_FRAMES_IN_FLIGHT];
|
||||||
|
Uint32 swapchainTextureCount;
|
||||||
|
|
||||||
SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
|
SDL_GPUFence *inFlightFences[MAX_FRAMES_IN_FLIGHT];
|
||||||
Uint32 width;
|
Uint32 width;
|
||||||
Uint32 height;
|
Uint32 height;
|
||||||
@@ -6256,7 +6258,7 @@ static bool D3D12_INTERNAL_CreateSwapchain(
|
|||||||
createInfo.layer_count_or_depth = 1;
|
createInfo.layer_count_or_depth = 1;
|
||||||
createInfo.num_levels = 1;
|
createInfo.num_levels = 1;
|
||||||
|
|
||||||
for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
|
for (Uint32 i = 0; i < windowData->swapchainTextureCount; i += 1) {
|
||||||
texture = D3D12_INTERNAL_CreateTexture(renderer, &createInfo, true);
|
texture = D3D12_INTERNAL_CreateTexture(renderer, &createInfo, true);
|
||||||
texture->container = &windowData->textureContainers[i];
|
texture->container = &windowData->textureContainers[i];
|
||||||
windowData->textureContainers[i].activeTexture = texture;
|
windowData->textureContainers[i].activeTexture = texture;
|
||||||
@@ -6300,7 +6302,7 @@ static void D3D12_INTERNAL_DestroySwapchain(
|
|||||||
D3D12WindowData *windowData)
|
D3D12WindowData *windowData)
|
||||||
{
|
{
|
||||||
renderer->commandQueue->PresentX(0, NULL, NULL);
|
renderer->commandQueue->PresentX(0, NULL, NULL);
|
||||||
for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
|
for (Uint32 i = 0; i < windowData->swapchainTextureCount; i += 1) {
|
||||||
D3D12_INTERNAL_DestroyTexture(
|
D3D12_INTERNAL_DestroyTexture(
|
||||||
renderer,
|
renderer,
|
||||||
windowData->textureContainers[i].activeTexture);
|
windowData->textureContainers[i].activeTexture);
|
||||||
@@ -6318,7 +6320,7 @@ static bool D3D12_INTERNAL_ResizeSwapchain(
|
|||||||
renderer->commandQueue->PresentX(0, NULL, NULL);
|
renderer->commandQueue->PresentX(0, NULL, NULL);
|
||||||
|
|
||||||
// Clean up the previous swapchain textures
|
// Clean up the previous swapchain textures
|
||||||
for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
|
for (Uint32 i = 0; i < windowData->swapchainTextureCount; i += 1) {
|
||||||
D3D12_INTERNAL_DestroyTexture(
|
D3D12_INTERNAL_DestroyTexture(
|
||||||
renderer,
|
renderer,
|
||||||
windowData->textureContainers[i].activeTexture);
|
windowData->textureContainers[i].activeTexture);
|
||||||
@@ -6458,7 +6460,7 @@ static bool D3D12_INTERNAL_ResizeSwapchain(
|
|||||||
D3D12_Wait((SDL_GPURenderer *)renderer);
|
D3D12_Wait((SDL_GPURenderer *)renderer);
|
||||||
|
|
||||||
// Release views and clean up
|
// Release views and clean up
|
||||||
for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
|
for (Uint32 i = 0; i < windowData->swapchainTextureCount; i += 1) {
|
||||||
D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
|
D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
|
||||||
renderer,
|
renderer,
|
||||||
&windowData->textureContainers[i].activeTexture->srvHandle);
|
&windowData->textureContainers[i].activeTexture->srvHandle);
|
||||||
@@ -6483,7 +6485,7 @@ static bool D3D12_INTERNAL_ResizeSwapchain(
|
|||||||
CHECK_D3D12_ERROR_AND_RETURN("Could not resize swapchain buffers", false)
|
CHECK_D3D12_ERROR_AND_RETURN("Could not resize swapchain buffers", false)
|
||||||
|
|
||||||
// Create texture object for the swapchain
|
// Create texture object for the swapchain
|
||||||
for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
|
for (Uint32 i = 0; i < windowData->swapchainTextureCount; i += 1) {
|
||||||
if (!D3D12_INTERNAL_InitializeSwapchainTexture(
|
if (!D3D12_INTERNAL_InitializeSwapchainTexture(
|
||||||
renderer,
|
renderer,
|
||||||
windowData->swapchain,
|
windowData->swapchain,
|
||||||
@@ -6509,7 +6511,7 @@ static void D3D12_INTERNAL_DestroySwapchain(
|
|||||||
D3D12WindowData *windowData)
|
D3D12WindowData *windowData)
|
||||||
{
|
{
|
||||||
// Release views and clean up
|
// Release views and clean up
|
||||||
for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
|
for (Uint32 i = 0; i < windowData->swapchainTextureCount; i += 1) {
|
||||||
D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
|
D3D12_INTERNAL_ReleaseCpuDescriptorHandle(
|
||||||
renderer,
|
renderer,
|
||||||
&windowData->textureContainers[i].activeTexture->srvHandle);
|
&windowData->textureContainers[i].activeTexture->srvHandle);
|
||||||
@@ -6551,6 +6553,9 @@ static bool D3D12_INTERNAL_CreateSwapchain(
|
|||||||
|
|
||||||
swapchainFormat = SwapchainCompositionToTextureFormat[swapchainComposition];
|
swapchainFormat = SwapchainCompositionToTextureFormat[swapchainComposition];
|
||||||
|
|
||||||
|
// Min swapchain image count is 2
|
||||||
|
windowData->swapchainTextureCount = SDL_clamp(renderer->allowedFramesInFlight, 2, 3);
|
||||||
|
|
||||||
// Initialize the swapchain buffer descriptor
|
// Initialize the swapchain buffer descriptor
|
||||||
swapchainDesc.Width = 0; // use client window width
|
swapchainDesc.Width = 0; // use client window width
|
||||||
swapchainDesc.Height = 0; // use client window height
|
swapchainDesc.Height = 0; // use client window height
|
||||||
@@ -6558,7 +6563,7 @@ static bool D3D12_INTERNAL_CreateSwapchain(
|
|||||||
swapchainDesc.SampleDesc.Count = 1;
|
swapchainDesc.SampleDesc.Count = 1;
|
||||||
swapchainDesc.SampleDesc.Quality = 0;
|
swapchainDesc.SampleDesc.Quality = 0;
|
||||||
swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
swapchainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
swapchainDesc.BufferCount = MAX_FRAMES_IN_FLIGHT;
|
swapchainDesc.BufferCount = windowData->swapchainTextureCount;
|
||||||
swapchainDesc.Scaling = DXGI_SCALING_STRETCH;
|
swapchainDesc.Scaling = DXGI_SCALING_STRETCH;
|
||||||
swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
swapchainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||||
swapchainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
|
swapchainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
|
||||||
@@ -6672,7 +6677,7 @@ static bool D3D12_INTERNAL_CreateSwapchain(
|
|||||||
/* If a you are using a FLIP model format you can't create the swapchain as DXGI_FORMAT_B8G8R8A8_UNORM_SRGB.
|
/* If a you are using a FLIP model format you can't create the swapchain as DXGI_FORMAT_B8G8R8A8_UNORM_SRGB.
|
||||||
* You have to create the swapchain as DXGI_FORMAT_B8G8R8A8_UNORM and then set the render target view's format to DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
|
* You have to create the swapchain as DXGI_FORMAT_B8G8R8A8_UNORM and then set the render target view's format to DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
|
||||||
*/
|
*/
|
||||||
for (Uint32 i = 0; i < MAX_FRAMES_IN_FLIGHT; i += 1) {
|
for (Uint32 i = 0; i < windowData->swapchainTextureCount; i += 1) {
|
||||||
if (!D3D12_INTERNAL_InitializeSwapchainTexture(
|
if (!D3D12_INTERNAL_InitializeSwapchainTexture(
|
||||||
renderer,
|
renderer,
|
||||||
swapchain3,
|
swapchain3,
|
||||||
@@ -6820,7 +6825,29 @@ static bool D3D12_SetAllowedFramesInFlight(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Destroy all swapchains
|
||||||
|
for (Uint32 i = 0; i < renderer->claimedWindowCount; i += 1) {
|
||||||
|
D3D12WindowData *windowData = renderer->claimedWindows[i];
|
||||||
|
|
||||||
|
D3D12_INTERNAL_DestroySwapchain(renderer, windowData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the frames in flight value
|
||||||
renderer->allowedFramesInFlight = allowedFramesInFlight;
|
renderer->allowedFramesInFlight = allowedFramesInFlight;
|
||||||
|
|
||||||
|
// Recreate all swapchains
|
||||||
|
for (Uint32 i = 0; i < renderer->claimedWindowCount; i += 1) {
|
||||||
|
D3D12WindowData *windowData = renderer->claimedWindows[i];
|
||||||
|
|
||||||
|
if (!D3D12_INTERNAL_CreateSwapchain(
|
||||||
|
renderer,
|
||||||
|
windowData,
|
||||||
|
windowData->swapchainComposition,
|
||||||
|
windowData->present_mode)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8510,7 +8537,7 @@ static SDL_GPUDevice *D3D12_CreateDevice(bool debugMode, bool preferLowPower, SD
|
|||||||
res = renderer->device->SetFrameIntervalX(
|
res = renderer->device->SetFrameIntervalX(
|
||||||
NULL,
|
NULL,
|
||||||
D3D12XBOX_FRAME_INTERVAL_60_HZ,
|
D3D12XBOX_FRAME_INTERVAL_60_HZ,
|
||||||
MAX_FRAMES_IN_FLIGHT - 1,
|
renderer->allowedFramesInFlight - 1,
|
||||||
D3D12XBOX_FRAME_INTERVAL_FLAG_NONE);
|
D3D12XBOX_FRAME_INTERVAL_FLAG_NONE);
|
||||||
if (FAILED(res)) {
|
if (FAILED(res)) {
|
||||||
D3D12_INTERNAL_DestroyRenderer(renderer);
|
D3D12_INTERNAL_DestroyRenderer(renderer);
|
||||||
@@ -8864,7 +8891,7 @@ void SDL_GDKResumeGPU(SDL_GPUDevice *device)
|
|||||||
res = renderer->device->SetFrameIntervalX(
|
res = renderer->device->SetFrameIntervalX(
|
||||||
NULL,
|
NULL,
|
||||||
D3D12XBOX_FRAME_INTERVAL_60_HZ,
|
D3D12XBOX_FRAME_INTERVAL_60_HZ,
|
||||||
MAX_FRAMES_IN_FLIGHT - 1,
|
renderer->allowedFramesInFlight - 1,
|
||||||
D3D12XBOX_FRAME_INTERVAL_FLAG_NONE);
|
D3D12XBOX_FRAME_INTERVAL_FLAG_NONE);
|
||||||
if (FAILED(res)) {
|
if (FAILED(res)) {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not set frame interval: %X", res);
|
SDL_LogError(SDL_LOG_CATEGORY_GPU, "Could not set frame interval: %X", res);
|
||||||
|
|||||||
@@ -4556,7 +4556,7 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
|
|||||||
return VULKAN_INTERNAL_TRY_AGAIN;
|
return VULKAN_INTERNAL_TRY_AGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
windowData->imageCount = MAX_FRAMES_IN_FLIGHT;
|
Uint32 requestedImageCount = renderer->allowedFramesInFlight;
|
||||||
|
|
||||||
#ifdef SDL_PLATFORM_APPLE
|
#ifdef SDL_PLATFORM_APPLE
|
||||||
windowData->width = swapchainSupportDetails.capabilities.currentExtent.width;
|
windowData->width = swapchainSupportDetails.capabilities.currentExtent.width;
|
||||||
@@ -4572,12 +4572,12 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (swapchainSupportDetails.capabilities.maxImageCount > 0 &&
|
if (swapchainSupportDetails.capabilities.maxImageCount > 0 &&
|
||||||
windowData->imageCount > swapchainSupportDetails.capabilities.maxImageCount) {
|
requestedImageCount > swapchainSupportDetails.capabilities.maxImageCount) {
|
||||||
windowData->imageCount = swapchainSupportDetails.capabilities.maxImageCount;
|
requestedImageCount = swapchainSupportDetails.capabilities.maxImageCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (windowData->imageCount < swapchainSupportDetails.capabilities.minImageCount) {
|
if (requestedImageCount < swapchainSupportDetails.capabilities.minImageCount) {
|
||||||
windowData->imageCount = swapchainSupportDetails.capabilities.minImageCount;
|
requestedImageCount = swapchainSupportDetails.capabilities.minImageCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (windowData->presentMode == SDL_GPU_PRESENTMODE_MAILBOX) {
|
if (windowData->presentMode == SDL_GPU_PRESENTMODE_MAILBOX) {
|
||||||
@@ -4587,14 +4587,14 @@ static Uint32 VULKAN_INTERNAL_CreateSwapchain(
|
|||||||
* images, it's not real mailbox support, so let it fail hard.
|
* images, it's not real mailbox support, so let it fail hard.
|
||||||
* -flibit
|
* -flibit
|
||||||
*/
|
*/
|
||||||
windowData->imageCount = SDL_max(windowData->imageCount, 3);
|
requestedImageCount = SDL_max(requestedImageCount, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||||
swapchainCreateInfo.pNext = NULL;
|
swapchainCreateInfo.pNext = NULL;
|
||||||
swapchainCreateInfo.flags = 0;
|
swapchainCreateInfo.flags = 0;
|
||||||
swapchainCreateInfo.surface = windowData->surface;
|
swapchainCreateInfo.surface = windowData->surface;
|
||||||
swapchainCreateInfo.minImageCount = windowData->imageCount;
|
swapchainCreateInfo.minImageCount = requestedImageCount;
|
||||||
swapchainCreateInfo.imageFormat = windowData->format;
|
swapchainCreateInfo.imageFormat = windowData->format;
|
||||||
swapchainCreateInfo.imageColorSpace = windowData->colorSpace;
|
swapchainCreateInfo.imageColorSpace = windowData->colorSpace;
|
||||||
swapchainCreateInfo.imageExtent.width = windowData->width;
|
swapchainCreateInfo.imageExtent.width = windowData->width;
|
||||||
@@ -9906,11 +9906,20 @@ static bool VULKAN_SetAllowedFramesInFlight(
|
|||||||
{
|
{
|
||||||
VulkanRenderer *renderer = (VulkanRenderer *)driverData;
|
VulkanRenderer *renderer = (VulkanRenderer *)driverData;
|
||||||
|
|
||||||
if (!VULKAN_Wait(driverData)) {
|
renderer->allowedFramesInFlight = allowedFramesInFlight;
|
||||||
return false;
|
|
||||||
|
for (Uint32 i = 0; i < renderer->claimedWindowCount; i += 1) {
|
||||||
|
WindowData *windowData = renderer->claimedWindows[i];
|
||||||
|
|
||||||
|
Uint32 recreateResult = VULKAN_INTERNAL_RecreateSwapchain(renderer, windowData);
|
||||||
|
if (!recreateResult) {
|
||||||
|
return false;
|
||||||
|
} else if (recreateResult == VULKAN_INTERNAL_TRY_AGAIN) {
|
||||||
|
// Edge case, swapchain extent is (0, 0) but this is not an error
|
||||||
|
windowData->needsSwapchainRecreate = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer->allowedFramesInFlight = allowedFramesInFlight;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user