Fix SDL window vs. Vulkan swapchain extent errors, align SDL vs. Win32 window handling & error logic

This commit is contained in:
Stephen Saunders 2023-06-09 14:48:36 -04:00
parent db79692287
commit 078eb4e779
3 changed files with 84 additions and 46 deletions

View file

@ -567,6 +567,8 @@ bool DeviceManager_VK::pickPhysicalDevice()
m_DeviceParams.swapChainBufferCount = Max( surfaceCaps.minImageCount, m_DeviceParams.swapChainBufferCount );
m_DeviceParams.swapChainBufferCount = surfaceCaps.maxImageCount > 0 ? Min( m_DeviceParams.swapChainBufferCount, surfaceCaps.maxImageCount ) : m_DeviceParams.swapChainBufferCount;
/* SRS - Don't check extent here since window manager surfaceCaps may restrict extent to something smaller than requested
- Instead, check and clamp extent to window manager surfaceCaps during swap chain creation inside createSwapChain()
if( surfaceCaps.minImageExtent.width > requestedExtent.width ||
surfaceCaps.minImageExtent.height > requestedExtent.height ||
surfaceCaps.maxImageExtent.width < requestedExtent.width ||
@ -578,6 +580,7 @@ bool DeviceManager_VK::pickPhysicalDevice()
errorStream << " - " << surfaceCaps.maxImageExtent.width << "x" << surfaceCaps.maxImageExtent.height;
deviceIsGood = false;
}
*/
bool surfaceFormatPresent = false;
for( const vk::SurfaceFormatKHR& surfaceFmt : surfaceFmts )
@ -999,6 +1002,11 @@ bool DeviceManager_VK::createSwapChain()
vk::ColorSpaceKHR::eSrgbNonlinear
};
// SRS - Clamp swap chain extent within the range supported by the device / window surface
auto surfaceCaps = m_VulkanPhysicalDevice.getSurfaceCapabilitiesKHR( m_WindowSurface );
m_DeviceParams.backBufferWidth = idMath::ClampInt( surfaceCaps.minImageExtent.width, surfaceCaps.maxImageExtent.width, m_DeviceParams.backBufferWidth );
m_DeviceParams.backBufferHeight = idMath::ClampInt( surfaceCaps.minImageExtent.height, surfaceCaps.maxImageExtent.height, m_DeviceParams.backBufferHeight );
vk::Extent2D extent = vk::Extent2D( m_DeviceParams.backBufferWidth, m_DeviceParams.backBufferHeight );
std::unordered_set<uint32_t> uniqueQueues =

View file

@ -135,6 +135,10 @@ void DeviceManager::UpdateWindowSize( const glimpParms_t& parms )
m_DeviceParams.vsyncEnabled = m_RequestedVSync;
ResizeSwapChain();
// SRS - Get actual swapchain dimensions to set new render size
deviceManager->GetWindowDimensions( glConfig.nativeScreenWidth, glConfig.nativeScreenHeight );
BackBufferResized();
}
else
@ -195,7 +199,8 @@ static int GetDisplayIndex( glimpParms_t parms )
{
SDL_Rect rect;
SDL_GetDisplayBounds( i, &rect );
if( windowPosX >= rect.x && windowPosX < ( rect.x + rect.w ) && windowPosY >= rect.y && windowPosY < ( rect.y + rect.h ) )
if( ( windowPosX >= rect.x && windowPosX < ( rect.x + rect.w ) && windowPosY >= rect.y && windowPosY < ( rect.y + rect.h ) ) ||
( parms.x == SDL_WINDOWPOS_CENTERED_DISPLAY( i ) && parms.y == SDL_WINDOWPOS_CENTERED_DISPLAY( i ) ) )
{
displayIdx = i;
break;
@ -206,11 +211,18 @@ static int GetDisplayIndex( glimpParms_t parms )
return displayIdx;
}
// SRS - Function to get display frequency of monitor hosting the current window
// SRS - Function to get display frequency of monitor corresponding to the window position
static int GetDisplayFrequency( glimpParms_t parms )
{
int displayIndex = GetDisplayIndex( parms );
if( displayIndex < 0 )
{
// SRS - window is out of bounds for desktop, fall back to primary display
displayIndex = 0;
}
SDL_DisplayMode m = {0};
if( SDL_GetWindowDisplayMode( window, &m ) < 0 )
if( SDL_GetCurrentDisplayMode( displayIndex, &m ) )
{
common->Warning( "Couldn't get display refresh rate, reason: %s", SDL_GetError() );
return parms.displayHz;
@ -255,8 +267,9 @@ bool VKimp_Init( glimpParms_t parms )
}
else if( GetDisplayIndex( parms ) < 0 ) // verify window position for -1 and -2 borderless modes
{
// SRS - window is out of bounds for desktop, startup on default display instead
createParms.x = createParms.y = SDL_WINDOWPOS_UNDEFINED;
// SRS - window is out of bounds for desktop, startup on primary display instead
createParms.x = createParms.y = SDL_WINDOWPOS_CENTERED;
common->Warning( "Window position out of bounds, falling back to primary display" );
}
if( !deviceManager->CreateWindowDeviceAndSwapChain( createParms, GAME_NAME ) )
@ -280,7 +293,7 @@ bool VKimp_Init( glimpParms_t parms )
}
}
// SRS - Move to fullscreen mode after window creation to avoid SDL platform differences
// SRS - Switch into fullscreen mode after window creation to avoid SDL platform differences
if( SDL_SetWindowFullscreen( window, SDL_WINDOW_FULLSCREEN ) < 0 )
{
common->Warning( "Couldn't switch to fullscreen mode, reason: %s", SDL_GetError() );
@ -288,16 +301,28 @@ bool VKimp_Init( glimpParms_t parms )
}
else if( parms.fullScreen == -2 )
{
// SRS - Move to borderless fullscreen mode after window creation
// SRS - Switch into borderless fullscreen mode after window creation
if( SDL_SetWindowFullscreen( window, SDL_WINDOW_FULLSCREEN_DESKTOP ) < 0 )
{
common->Warning( "Couldn't switch to borderless fullscreen mode, reason: %s", SDL_GetError() );
}
}
else if( parms.fullScreen == -1 )
{
// SRS - Make sure custom borderless window is in position after window creation
SDL_SetWindowPosition( window, createParms.x, createParms.y );
}
// RB begin
SDL_GetWindowSize( window, &glConfig.nativeScreenWidth, &glConfig.nativeScreenHeight );
// RB end
if( parms.fullScreen )
{
// SRS - Get window's client area dimensions to set initial render size for fullscreen modes
SDL_GetWindowSize( window, &glConfig.nativeScreenWidth, &glConfig.nativeScreenHeight );
}
else
{
// SRS - Get actual swapchain dimensions to set initial render size for windowed mode
deviceManager->GetWindowDimensions( glConfig.nativeScreenWidth, glConfig.nativeScreenHeight );
}
// SRS - Detect and save actual fullscreen state supporting all modes (-2, -1, 0, 1, ...)
glConfig.isFullscreen = ( SDL_GetWindowFlags( window ) & SDL_WINDOW_FULLSCREEN ) || ( parms.fullScreen == -1 ) ? parms.fullScreen : 0;
@ -371,9 +396,10 @@ static int ScreenParmsHandleDisplayIndex( glimpParms_t parms )
int windowPosX = parms.x, windowPosY = parms.y;
if( displayIdx < 0 )
{
// SRS - window is out of bounds for desktop, reposition onto default display
windowPosX = windowPosY = SDL_WINDOWPOS_UNDEFINED;
// SRS - window is out of bounds for desktop, reposition onto primary display
displayIdx = 0;
windowPosX = windowPosY = SDL_WINDOWPOS_CENTERED;
common->Warning( "Window position out of bounds, falling back to primary display" );
}
// move window to the specified desktop position
@ -434,8 +460,9 @@ static bool SetScreenParmsWindowed( glimpParms_t parms )
int windowPosX = parms.x, windowPosY = parms.y;
if( GetDisplayIndex( parms ) < 0 )
{
// SRS - window is out of bounds for desktop, reposition onto default display
windowPosX = windowPosY = SDL_WINDOWPOS_UNDEFINED;
// SRS - window is out of bounds for desktop, reposition onto primary display
windowPosX = windowPosY = SDL_WINDOWPOS_CENTERED;
common->Warning( "Window position out of bounds, falling back to primary display" );
}
// SRS - handle differences in WM behaviour: for macOS set position first, for linux set it last
@ -496,8 +523,10 @@ bool VKimp_SetScreenParms( glimpParms_t parms )
glConfig.isFullscreen = parms.fullScreen;
glConfig.isStereoPixelFormat = parms.stereo;
glConfig.nativeScreenWidth = parms.width;
glConfig.nativeScreenHeight = parms.height;
// SRS - Get window's client area dimensions to set new render size
SDL_GetWindowSize( window, &glConfig.nativeScreenWidth, &glConfig.nativeScreenHeight );
glConfig.displayFrequency = GetDisplayFrequency( parms );
glConfig.multisamples = parms.multiSamples;

View file

@ -659,7 +659,7 @@ static bool GLW_GetWindowDimensions( const glimpParms_t parms, int& x, int& y, i
{
displayNotFound = true;
displayNum = DisplayPrimary();
idLib::Printf( "Can't find display for specified window position, falling back to display %i\n", displayNum + 1 );
common->Warning( "Window position out of bounds, falling back to primary display" );
}
// get the current monitor position and size on the desktop, assuming
@ -802,19 +802,17 @@ bool DeviceManager::CreateWindowDeviceAndSwapChain( const glimpParms_t& parms, c
return false;
}
// SRS - For fullscreen borderless windowed mode == -2 need to use actual display dimensions
if( parms.fullScreen == -2 )
// SRS - Get window's client area dimensions to set initial swapchain size
RECT rect;
if( !GetClientRect( win32.hWnd, &rect ) )
{
m_DeviceParams.backBufferWidth = w;
m_DeviceParams.backBufferHeight = h;
}
// otherwise use parms
else
{
m_DeviceParams.backBufferWidth = parms.width;
m_DeviceParams.backBufferHeight = parms.height;
common->Printf( "^3GLW_CreateWindow() - GetClientRect() failed^0\n" );
return false;
}
m_DeviceParams.backBufferWidth = rect.right - rect.left;
m_DeviceParams.backBufferHeight = rect.bottom - rect.top;
// RB
m_DeviceParams.backBufferSampleCount = parms.multiSamples;
m_DeviceParams.vsyncEnabled = m_RequestedVSync;
@ -851,6 +849,10 @@ void DeviceManager::UpdateWindowSize( const glimpParms_t& parms )
m_DeviceParams.vsyncEnabled = m_RequestedVSync;
ResizeSwapChain();
// SRS - Get actual swapchain dimensions to set new render size
deviceManager->GetWindowDimensions( glConfig.nativeScreenWidth, glConfig.nativeScreenHeight );
BackBufferResized();
}
else
@ -1129,22 +1131,23 @@ bool GLimp_Init( glimpParms_t parms )
glConfig.isFullscreen = parms.fullScreen;
glConfig.isStereoPixelFormat = parms.stereo;
// SRS - For fullscreen borderless windowed mode == -2 need to use actual display dimensions
if( parms.fullScreen == -2 )
if( parms.fullScreen )
{
int x, y, w, h;
if( !GLW_GetWindowDimensions( parms, x, y, w, h ) )
// SRS - Get window's client area dimensions to set initial render size for fullscreen modes
RECT rect;
if( !GetClientRect( win32.hWnd, &rect ) )
{
common->Printf( "^3GLimp_Init() - GetClientRect() failed^0\n" );
return false;
}
glConfig.nativeScreenWidth = w;
glConfig.nativeScreenHeight = h;
glConfig.nativeScreenWidth = rect.right - rect.left;
glConfig.nativeScreenHeight = rect.bottom - rect.top;
}
// otherwise use parms
else
{
glConfig.nativeScreenWidth = parms.width;
glConfig.nativeScreenHeight = parms.height;
// SRS - Get actual swapchain dimensions to set initial render size for windowed mode
deviceManager->GetWindowDimensions( glConfig.nativeScreenWidth, glConfig.nativeScreenHeight );
}
glConfig.displayFrequency = GetDisplayFrequency( parms );
@ -1219,19 +1222,17 @@ bool GLimp_SetScreenParms( glimpParms_t parms )
glConfig.isStereoPixelFormat = parms.stereo;
// SRS - For fullscreen borderless windowed mode == -2 need to use actual display dimensions
if( parms.fullScreen == -2 )
// SRS - Get window's client area dimensions to set new render size
RECT rect;
if( !GetClientRect( win32.hWnd, &rect ) )
{
glConfig.nativeScreenWidth = w;
glConfig.nativeScreenHeight = h;
}
// otherwise use parms
else
{
glConfig.nativeScreenWidth = parms.width;
glConfig.nativeScreenHeight = parms.height;
common->Printf( "^3GLimp_SetScreenParms() - GetClientRect() failed^0\n" );
return false;
}
glConfig.nativeScreenWidth = rect.right - rect.left;
glConfig.nativeScreenHeight = rect.bottom - rect.top;
glConfig.displayFrequency = GetDisplayFrequency( parms );
glConfig.multisamples = parms.multiSamples;