Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Game startup and shutdown fixes #849

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
12 changes: 6 additions & 6 deletions neo/renderer/NVRHI/RenderBackend_NVRHI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,11 @@ static NvrhiContext prevContext;

/*
==================
R_InitOpenGL
idRenderBackend::Init

This function is responsible for initializing a valid OpenGL subsystem
for rendering. This is done by calling the system specific GLimp_Init,
which gives us a working OGL subsystem, then setting all necessary openGL
This function is responsible for initializing a valid DX12/Vulkan subsystem
for rendering. This is done by calling the system specific GLimp_Init/VKimp_Init,
which gives us a working subsystem, then setting all necessary renderer
state, including images, vertex programs, and display lists.

Changes to the vertex cache size or smp state require a vid_restart.
Expand All @@ -154,11 +154,11 @@ and model information functions.
*/
void idRenderBackend::Init()
{
common->Printf( "----- R_InitOpenGL -----\n" );
common->Printf( "----- idRenderBackend::Init -----\n" );

if( tr.IsInitialized() )
{
common->FatalError( "R_InitOpenGL called while active" );
common->FatalError( "idRenderBackend::Init called while active" );
}

// SRS - create deviceManager here to prevent allocation loop via R_SetNewMode( true )
Expand Down
24 changes: 20 additions & 4 deletions neo/renderer/RenderSystem_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,9 +443,8 @@ void R_SetNewMode( const bool fullInit )
idList<vidMode_t> modeList;
if( !R_GetModeListForDisplay( r_fullscreen.GetInteger() - 1, modeList ) )
{
idLib::Printf( "r_fullscreen reset from %i to 1 because mode list failed.\n", r_fullscreen.GetInteger() );
r_fullscreen.SetInteger( 1 );
R_GetModeListForDisplay( r_fullscreen.GetInteger() - 1, modeList );
idLib::Printf( "Going to safe mode because display not found.\n" );
goto safeMode;
}

if( modeList.Num() < 1 )
Expand Down Expand Up @@ -546,8 +545,25 @@ void R_SetNewMode( const bool fullInit )
safeMode:
// if we failed, set everything back to "safe mode"
// and try again

// SRS - get the first display with a non-zero mode list, or fail if not found
int safeDisplay = 0;
idList<vidMode_t> safeList;
for( ; ; safeDisplay++ )
{
if( !R_GetModeListForDisplay( safeDisplay, safeList ) )
{
common->FatalError( "Unable to find a valid display for renderer" );
}
else if( safeList.Num() > 0 )
{
break;
}
}
// SRS end

r_vidMode.SetInteger( 0 );
r_fullscreen.SetInteger( 1 );
r_fullscreen.SetInteger( safeDisplay + 1 );
r_displayRefresh.SetInteger( 0 );
r_antiAliasing.SetInteger( 0 );
}
Expand Down
15 changes: 5 additions & 10 deletions neo/sys/DeviceManager_DX12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ static RefCountPtr<IDXGIAdapter> FindAdapter( const std::wstring& targetName )

return targetAdapter;
}

/* SRS - No longer needed, window centering now done in CreateWindowDeviceAndSwapChain() within win_glimp.cpp
// Adjust window rect so that it is centred on the given adapter. Clamps to fit if it's too big.
static bool MoveWindowOntoAdapter( IDXGIAdapter* targetAdapter, RECT& rect )
{
Expand Down Expand Up @@ -201,7 +201,7 @@ static bool MoveWindowOntoAdapter( IDXGIAdapter* targetAdapter, RECT& rect )

return false;
}

*/
void DeviceManager_DX12::ReportLiveObjects()
{
nvrhi::RefCountPtr<IDXGIDebug> pDebug;
Expand Down Expand Up @@ -297,16 +297,11 @@ bool DeviceManager_DX12::CreateDeviceAndSwapChain()
*/
HRESULT hr = E_FAIL;

RECT clientRect;
GetClientRect( ( HWND )windowHandle, &clientRect );
UINT width = clientRect.right - clientRect.left;
UINT height = clientRect.bottom - clientRect.top;

ZeroMemory( &m_SwapChainDesc, sizeof( m_SwapChainDesc ) );
m_SwapChainDesc.Width = width;
m_SwapChainDesc.Height = height;
m_SwapChainDesc.Width = m_DeviceParams.backBufferWidth;
m_SwapChainDesc.Height = m_DeviceParams.backBufferHeight;
m_SwapChainDesc.SampleDesc.Count = m_DeviceParams.swapChainSampleCount;
m_SwapChainDesc.SampleDesc.Quality = 0;
m_SwapChainDesc.SampleDesc.Quality = m_DeviceParams.swapChainSampleQuality;
m_SwapChainDesc.BufferUsage = m_DeviceParams.swapChainUsage;
m_SwapChainDesc.BufferCount = m_DeviceParams.swapChainBufferCount;
m_SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
Expand Down
146 changes: 38 additions & 108 deletions neo/sys/win32/win_glimp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ static void GLW_CreateWindowClasses()

if( !RegisterClass( &wc ) )
{
common->FatalError( "GLW_CreateWindow: could not register window class" );
common->FatalError( "GLW_CreateWindowClasses: could not register window class" );
}
common->Printf( "...registered window class\n" );

Expand Down Expand Up @@ -219,12 +219,6 @@ static bool GetDisplayCoordinates( const int deviceNum, int& x, int& y, int& wid
{
bool verbose = false;

idStr deviceName = GetDeviceName( deviceNum );
if( deviceName.Length() == 0 )
{
return false;
}

DISPLAY_DEVICE device = {};
device.cb = sizeof( device );
if( !EnumDisplayDevices(
Expand All @@ -239,7 +233,7 @@ static bool GetDisplayCoordinates( const int deviceNum, int& x, int& y, int& wid
DISPLAY_DEVICE monitor;
monitor.cb = sizeof( monitor );
if( !EnumDisplayDevices(
deviceName.c_str(),
device.DeviceName,
0,
&monitor,
0 /* dwFlags */ ) )
Expand All @@ -249,7 +243,7 @@ static bool GetDisplayCoordinates( const int deviceNum, int& x, int& y, int& wid

DEVMODE devmode;
devmode.dmSize = sizeof( devmode );
if( !EnumDisplaySettings( deviceName.c_str(), ENUM_CURRENT_SETTINGS, &devmode ) )
if( !EnumDisplaySettings( device.DeviceName, ENUM_CURRENT_SETTINGS, &devmode ) )
{
return false;
}
Expand Down Expand Up @@ -457,7 +451,10 @@ bool R_GetModeListForDisplay( const int requestedDisplayNum, idList<vidMode_t>&
// get the monitor for this display
if( !( device.StateFlags & ( DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE ) ) )
{
continue;
// SRS - If requested display number is not attached to desktop, skip this device. In this case we
// return true with an empty mode list for this display number. This can result in non-contiguous
// display numbers on Windows, but is better than undefined behaviour for "filled-in" false displays.
return true;
}

DISPLAY_DEVICE monitor;
Expand All @@ -468,7 +465,10 @@ bool R_GetModeListForDisplay( const int requestedDisplayNum, idList<vidMode_t>&
&monitor,
0 /* dwFlags */ ) )
{
continue;
// SRS - If EnumDisplayDevices() returns false for device, no monitor is detected. In this case we
// return true with an empty mode list for this display number. This can result in non-contiguous
// display numbers on Windows, but is better than undefined behaviour for "filled-in" false displays.
return true;
}

DEVMODE devmode;
Expand Down Expand Up @@ -554,17 +554,12 @@ int DisplayMax()
dd.cb = sizeof( DISPLAY_DEVICE );

int deviceNum = 0;
int deviceMax = 0;
int deviceMax = -1;
while( EnumDisplayDevices( NULL, deviceNum, &dd, 0 ) )
{
if( dd.StateFlags & ( DISPLAY_DEVICE_ATTACHED_TO_DESKTOP | DISPLAY_DEVICE_PRIMARY_DEVICE ) )
{
DISPLAY_DEVICE monitor = { 0 };
monitor.cb = sizeof( DISPLAY_DEVICE );
if( EnumDisplayDevices( dd.DeviceName, 0, &monitor, 0 ) )
{
deviceMax = deviceNum;
}
deviceMax = deviceNum;
}
deviceNum++;
}
Expand All @@ -577,20 +572,22 @@ int DisplayPrimary()
dd.cb = sizeof( DISPLAY_DEVICE );

int deviceNum = 0;
int deviceMin = -1;
while( EnumDisplayDevices( NULL, deviceNum, &dd, 0 ) )
{
if( dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE )
{
DISPLAY_DEVICE monitor = { 0 };
monitor.cb = sizeof( DISPLAY_DEVICE );
if( EnumDisplayDevices( dd.DeviceName, 0, &monitor, 0 ) )
{
return deviceNum;
}
return deviceNum;
}

// SRS - save first device attached to desktop as fallback if primary device not found
if( deviceMin < 0 && ( dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP ) )
{
deviceMin = deviceNum;
}
deviceNum++;
}
return 0;
return deviceMin;
}

/*
Expand Down Expand Up @@ -659,7 +656,7 @@ static bool GLW_GetWindowDimensions( const glimpParms_t parms, int& x, int& y, i
{
displayNotFound = true;
displayNum = DisplayPrimary();
common->Warning( "Window position out of bounds, falling back to primary display" );
common->Warning( "Window position out of bounds, falling back to primary display %d", displayNum + 1 );
}

// get the current monitor position and size on the desktop, assuming
Expand Down Expand Up @@ -784,7 +781,7 @@ bool DeviceManager::CreateWindowDeviceAndSwapChain( const glimpParms_t& parms, c

if( !win32.hWnd )
{
common->Printf( "^3GLW_CreateWindow() - Couldn't create window^0\n" );
common->Printf( "^3CreateWindowDeviceAndSwapChain() - Couldn't create window^0\n" );
return false;
}

Expand All @@ -798,15 +795,15 @@ bool DeviceManager::CreateWindowDeviceAndSwapChain( const glimpParms_t& parms, c
win32.hDC = GetDC( win32.hWnd );
if( !win32.hDC )
{
common->Printf( "^3GLW_CreateWindow() - GetDC()failed^0\n" );
common->Printf( "^3CreateWindowDeviceAndSwapChain() - GetDC() failed^0\n" );
return false;
}

// SRS - Get window's client area dimensions to set initial swapchain size
RECT rect;
if( !GetClientRect( win32.hWnd, &rect ) )
{
common->Printf( "^3GLW_CreateWindow() - GetClientRect() failed^0\n" );
common->Printf( "^3CreateWindowDeviceAndSwapChain() - GetClientRect() failed^0\n" );
return false;
}

Expand Down Expand Up @@ -861,74 +858,6 @@ void DeviceManager::UpdateWindowSize( const glimpParms_t& parms )
}
}

/*
=======================
GLW_CreateWindow

Responsible for creating the Win32 window.
If fullscreen, it won't have a border
=======================
*/
static bool GLW_CreateWindow( glimpParms_t parms )
{
int x, y, w, h;
if( !GLW_GetWindowDimensions( parms, x, y, w, h ) )
{
return false;
}

int stylebits;
int exstyle;
if( parms.fullScreen != 0 )
{
exstyle = WS_EX_TOPMOST;
stylebits = WS_POPUP | WS_VISIBLE | WS_SYSMENU;
}
else
{
exstyle = 0;
stylebits = WINDOW_STYLE | WS_SYSMENU;
}

win32.hWnd = CreateWindowEx(
exstyle,
WIN32_WINDOW_CLASS_NAME,
GAME_NAME,
stylebits,
x, y, w, h,
NULL,
NULL,
win32.hInstance,
NULL );

if( !win32.hWnd )
{
common->Printf( "^3GLW_CreateWindow() - Couldn't create window^0\n" );
return false;
}

::SetTimer( win32.hWnd, 0, 100, NULL );

ShowWindow( win32.hWnd, SW_SHOW );
UpdateWindow( win32.hWnd );
common->Printf( "...created window @ %d,%d (%dx%d)\n", x, y, w, h );

// makeCurrent NULL frees the DC, so get another
win32.hDC = GetDC( win32.hWnd );
if( !win32.hDC )
{
common->Printf( "^3GLW_CreateWindow() - GetDC()failed^0\n" );
return false;
}

SetForegroundWindow( win32.hWnd );
SetFocus( win32.hWnd );

glConfig.isFullscreen = parms.fullScreen;

return true;
}

/*
===================
PrintCDSError
Expand Down Expand Up @@ -1134,6 +1063,7 @@ bool GLimp_Init( glimpParms_t parms )
if( !GetClientRect( win32.hWnd, &rect ) )
{
common->Printf( "^3GLimp_Init() - GetClientRect() failed^0\n" );
GLimp_Shutdown();
return false;
}

Expand Down Expand Up @@ -1257,17 +1187,6 @@ void DeviceManager::Shutdown()
windowHandle = nullptr;
win32.hWnd = NULL;
}

// reset display settings
if( win32.cdsFullscreen )
{
common->Printf( "...resetting display\n" );
ChangeDisplaySettings( 0, 0 );
win32.cdsFullscreen = 0;
}

// restore gamma
GLimp_RestoreGamma();
}

/*
Expand All @@ -1284,6 +1203,17 @@ void GLimp_Shutdown()
{
deviceManager->Shutdown();
}

// reset display settings
if( win32.cdsFullscreen )
{
common->Printf( "...resetting display\n" );
ChangeDisplaySettings( 0, 0 );
win32.cdsFullscreen = 0;
}

// restore gamma
GLimp_RestoreGamma();
}


Expand Down