diff --git a/doomclassic/doom/g_game.cpp b/doomclassic/doom/g_game.cpp index a84d9c69..137bf41b 100644 --- a/doomclassic/doom/g_game.cpp +++ b/doomclassic/doom/g_game.cpp @@ -593,8 +593,8 @@ void G_DoLoadLevel () ::g->joyxmove = ::g->joyymove = 0; ::g->mousex = ::g->mousey = 0; ::g->sendpause = ::g->sendsave = ::g->paused = false; - memset (::g->mousebuttons, 0, sizeof(::g->mousebuttons)); - memset (::g->joybuttons, 0, sizeof(::g->joybuttons)); + memset (::g->mousebuttons, 0, sizeof(::g->mousebuttons[0])*3); // SRS - mousebuttons[0] points at mousearray[1] to mousearray[3], [-1] allowed + memset (::g->joybuttons, 0, sizeof(::g->joybuttons[0])*4); // SRS - joybuttons[0] points at joyarray[1] to joyarray[4], [-1] allowed } // diff --git a/doomclassic/doom/vars.h b/doomclassic/doom/vars.h index aaca3e92..8fde42d7 100644 --- a/doomclassic/doom/vars.h +++ b/doomclassic/doom/vars.h @@ -820,7 +820,7 @@ int reloadlump; // w_wad.vars end // // z_zone.vars begin // int sizes[NUM_ZONES+1]; -memzone_t* zones[NUM_ZONES] ; +memzone_t* zones[NUM_ZONES+1] ; // SRS - Added +1 so NUM_ZONES index is not beyond end of array int NumAlloc ; // z_zone.vars end // // info vars begin // diff --git a/neo/CMakeLists.txt b/neo/CMakeLists.txt index a3fbd6bb..d1b0636a 100644 --- a/neo/CMakeLists.txt +++ b/neo/CMakeLists.txt @@ -33,6 +33,9 @@ option(USE_VULKAN option(SPIRV_SHADERC "Compile SPIR-V shader byte code using shaderc instead of using Glslang directly" OFF) +option(USE_MoltenVK + "Use MoltenVK library instead of Vulkan library on macOS" OFF) + option(ONATIVE "Optimize for the host CPU" OFF) @@ -84,7 +87,8 @@ endif() if (FORCE_COLOR_OUTPUT) if (CMAKE_COMPILER_IS_GNUCC) add_compile_options(-fdiagnostics-color=always) - elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang") + # SRS - Add test for AppleClang + elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang") add_compile_options(-fcolor-diagnostics) endif () endif () @@ -112,7 +116,8 @@ else() message(STATUS CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}) endif() -if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang") +# SRS - Add test for AppleClang +if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang") add_definitions(-pipe) #add_definitions(-Wall) add_definitions(-Werror=format-security) @@ -153,11 +158,14 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang") add_definitions(-DUSE_EXCEPTIONS) #endif() - add_compile_options(-Wno-pragmas -Wno-unused-variable -Wno-switch -Wno-unused-value -Winvalid-pch -Wno-multichar) - if(CMAKE_C_COMPILER_ID STREQUAL "Clang") + # SRS - Change add_compile_options to add_definitions so options propagate to pre-compiled header build settings + add_definitions(-Wno-pragmas -Wno-unused-variable -Wno-switch -Wno-unused-value -Winvalid-pch -Wno-multichar) + # SRS - Add test for AppleClang + if(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang") # add clang-specific settings for warnings (the second one make sure clang doesn't complain # about unknown -W flags, like -Wno-unused-but-set-variable) - add_compile_options(-Wno-local-type-template-args -Wno-unknown-warning-option -Wno-inline-new-delete -Wno-switch-enum) + # SRS - Add -Wno-deprecated-register and -Wno-expansion-to-defined to list of warning settings + add_definitions(-Wno-local-type-template-args -Wno-unknown-warning-option -Wno-inline-new-delete -Wno-switch-enum -Wno-deprecated-register -Wno-expansion-to-defined) endif() if(NOT CMAKE_CROSSCOMPILING AND ONATIVE) @@ -168,11 +176,28 @@ if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang") endif() endif() - add_compile_options(-fno-strict-aliasing) + # SRS - Change add_compile_options to add_definitions so options propagate to pre-compiled header build settings + add_definitions(-fno-strict-aliasing) - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG -O0 -ggdb") - #set(CMAKE_C_FLAGS_DEBUGALL "${CMAKE_C_FLAGS_DEBUGALL} -g -ggdb -D_DEBUG") - #set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_PROFILE} -g -ggdb -D_DEBUG -O1 -fno-omit-frame-pointer") + # SRS - Make sure OSX can find system headers and add support for minimum OSX runtime version + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + # SRS - Also add -fasm-blocks otherwise Xcode complains + add_definitions(-fasm-blocks -isysroot "${CMAKE_OSX_SYSROOT}") + if("${CMAKE_OSX_DEPLOYMENT_TARGET}") + add_definitions(-mmacosx-version-min="${CMAKE_OSX_DEPLOYMENT_TARGET}") + endif() + endif() + + #SRS - some #ifdef _DEBUG code can cause game to crash on OSX, remove -D_DEBUG for now and fix later + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb -O0") + #set(CMAKE_C_FLAGS_DEBUGALL "${CMAKE_C_FLAGS_DEBUGALL} -g -ggdb") + #set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_PROFILE} -g -ggdb -O1 -fno-omit-frame-pointer") + else() + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -ggdb -D_DEBUG -O0") + #set(CMAKE_C_FLAGS_DEBUGALL "${CMAKE_C_FLAGS_DEBUGALL} -g -ggdb -D_DEBUG") + #set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_PROFILE} -g -ggdb -D_DEBUG -O1 -fno-omit-frame-pointer") + endif() set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -ffast-math -fno-unsafe-math-optimizations -fomit-frame-pointer") set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -g -O3 -ffast-math -fno-unsafe-math-optimizations -fomit-frame-pointer") set(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -Os -ffast-math -fno-unsafe-math-optimizations -fomit-frame-pointer") @@ -333,7 +358,8 @@ if(USE_VULKAN) if(SPIRV_SHADERC) add_definitions(-DSPIRV_SHADERC) - if(CMAKE_CL_64) + # SRS - Add case for UNIX/OSX + if(CMAKE_CL_64 OR UNIX) link_directories($ENV{VULKAN_SDK}/Lib) else() link_directories($ENV{VULKAN_SDK}/Lib32) @@ -374,7 +400,13 @@ if(USE_VULKAN) if(NOT Vulkan_FOUND) message(FATAL_ERROR "Could not find Vulkan library!") else() - message(STATUS ${Vulkan_LIBRARY}) + # SRS - Optionally use MoltenVK headers/library for runtime config functions on OSX + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND USE_MoltenVK) + add_definitions(-DUSE_MoltenVK) + include_directories($ENV{VULKAN_SDK}/../MoltenVK/include) + set(Vulkan_LIBRARY $ENV{VULKAN_SDK}/lib/libMoltenVK.dylib) + endif() + message(STATUS "Using Vulkan: " ${Vulkan_LIBRARY}) endif() add_definitions(-DUSE_VULKAN) @@ -386,7 +418,12 @@ if(USE_VULKAN) if(X11_XCB_FOUND) add_definitions(-DHAVE_X11_XCB) list(APPEND SUBSYSTEMS [X11]) - include_directories(${X11_XCB_INCLUDE_DIRS}) + # SRS - Added PKG_ preface to X11_XCB_INCLUDE_DIRS for OSX, not sure about UNIX + if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + include_directories(${PKG_X11_XCB_INCLUDE_DIRS}) + else() + include_directories(${X11_XCB_INCLUDE_DIRS}) + endif() endif() add_definitions(-DVK_USE_PLATFORM_XLIB_KHR) elseif(WIN32) @@ -1701,9 +1738,14 @@ else() set(Vulkan_LIBRARIES ${Vulkan_LIBRARY} ${X11_XCB_LIBRARIES} - glslang - SPIRV - ) + ) + + # SRS - Added UNIX/OSX support for shaderc + if(SPIRV_SHADERC) + list(APPEND Vulkan_LIBRARIES shaderc_combined) + else() + list(APPEND Vulkan_LIBRARIES glslang SPIRV) + endif() if(ENABLE_GLSLANG_BINARIES) list(APPEND Vulkan_LIBRARIES glslang-default-resource-limits) diff --git a/neo/cmake-macos-opengl-debug.sh b/neo/cmake-macos-opengl-debug.sh new file mode 100755 index 00000000..26bf73f1 --- /dev/null +++ b/neo/cmake-macos-opengl-debug.sh @@ -0,0 +1,5 @@ +cd .. +rm -rf build +mkdir build +cd build +cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_OSX_DEPLOYMENT_TARGET=10.12 -DSDL2=ON -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include ../neo diff --git a/neo/cmake-macos-opengl-release.sh b/neo/cmake-macos-opengl-release.sh new file mode 100755 index 00000000..764ed5f7 --- /dev/null +++ b/neo/cmake-macos-opengl-release.sh @@ -0,0 +1,5 @@ +cd .. +rm -rf build +mkdir build +cd build +cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.12 -DSDL2=ON -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include ../neo diff --git a/neo/cmake-macos-opengl-retail.sh b/neo/cmake-macos-opengl-retail.sh new file mode 100755 index 00000000..7e52521e --- /dev/null +++ b/neo/cmake-macos-opengl-retail.sh @@ -0,0 +1,5 @@ +cd .. +rm -rf build +mkdir build +cd build +cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS_RELEASE="-DID_RETAIL" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.12 -DSDL2=ON -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include ../neo diff --git a/neo/cmake-macos-vulkan-debug.sh b/neo/cmake-macos-vulkan-debug.sh index 453bb03d..db89d46c 100755 --- a/neo/cmake-macos-vulkan-debug.sh +++ b/neo/cmake-macos-vulkan-debug.sh @@ -2,4 +2,4 @@ cd .. rm -rf build mkdir build cd build -cmake -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DSDL2=ON -DUSE_VULKAN=ON -DSPIRV_SHADERC=OFF ../neo -Wno-dev -Wexpansion-to-defined \ No newline at end of file +cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug -DCMAKE_OSX_DEPLOYMENT_TARGET=10.12 -DSDL2=ON -DUSE_VULKAN=ON -DSPIRV_SHADERC=OFF -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include ../neo -Wno-dev \ No newline at end of file diff --git a/neo/cmake-macos-vulkan-release.sh b/neo/cmake-macos-vulkan-release.sh index 4d62fb24..19157f2f 100755 --- a/neo/cmake-macos-vulkan-release.sh +++ b/neo/cmake-macos-vulkan-release.sh @@ -2,4 +2,4 @@ cd .. rm -rf build mkdir build cd build -cmake -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DSDL2=ON -DUSE_VULKAN=ON -DSPIRV_SHADERC=OFF ../neo +cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.12 -DSDL2=ON -DUSE_VULKAN=ON -DSPIRV_SHADERC=OFF -DUSE_MoltenVK=ON -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include ../neo -Wno-dev diff --git a/neo/cmake-macos-vulkan-retail.sh b/neo/cmake-macos-vulkan-retail.sh new file mode 100755 index 00000000..26bfd5c7 --- /dev/null +++ b/neo/cmake-macos-vulkan-retail.sh @@ -0,0 +1,5 @@ +cd .. +rm -rf build +mkdir build +cd build +cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS_RELEASE="-DID_RETAIL" -DCMAKE_OSX_DEPLOYMENT_TARGET=10.12 -DSDL2=ON -DUSE_VULKAN=ON -DSPIRV_SHADERC=OFF -DUSE_MoltenVK=ON -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include ../neo -Wno-dev diff --git a/neo/cmake-xcode-opengl-debug.sh b/neo/cmake-xcode-opengl-debug.sh new file mode 100755 index 00000000..247a3d61 --- /dev/null +++ b/neo/cmake-xcode-opengl-debug.sh @@ -0,0 +1,5 @@ +cd .. +rm -rf xcode-opengl-debug +mkdir xcode-opengl-debug +cd xcode-opengl-debug +cmake -G Xcode -DCMAKE_BUILD_TYPE=Debug -DSDL2=ON -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include ../neo diff --git a/neo/cmake-xcode-opengl-release.sh b/neo/cmake-xcode-opengl-release.sh new file mode 100755 index 00000000..fa3fdc1f --- /dev/null +++ b/neo/cmake-xcode-opengl-release.sh @@ -0,0 +1,5 @@ +cd .. +rm -rf xcode-opengl-release +mkdir xcode-opengl-release +cd xcode-opengl-release +cmake -G Xcode -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.12 -DSDL2=ON -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include ../neo diff --git a/neo/cmake-xcode-vulkan-debug.sh b/neo/cmake-xcode-vulkan-debug.sh new file mode 100755 index 00000000..dc00933c --- /dev/null +++ b/neo/cmake-xcode-vulkan-debug.sh @@ -0,0 +1,5 @@ +cd .. +rm -rf xcode-vulkan-debug +mkdir xcode-vulkan-debug +cd xcode-vulkan-debug +cmake -G Xcode -DCMAKE_BUILD_TYPE=Debug -DSDL2=ON -DUSE_VULKAN=ON -DSPIRV_SHADERC=OFF -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include ../neo -Wno-dev diff --git a/neo/cmake-xcode-vulkan-release.sh b/neo/cmake-xcode-vulkan-release.sh new file mode 100755 index 00000000..907a6880 --- /dev/null +++ b/neo/cmake-xcode-vulkan-release.sh @@ -0,0 +1,5 @@ +cd .. +rm -rf xcode-vulkan-release +mkdir xcode-vulkan-release +cd xcode-vulkan-release +cmake -G Xcode -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.12 -DSDL2=ON -DUSE_VULKAN=ON -DSPIRV_SHADERC=OFF -DUSE_MoltenVK=ON -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include ../neo -Wno-dev diff --git a/neo/d3xp/menus/MenuHandler_HUD.cpp b/neo/d3xp/menus/MenuHandler_HUD.cpp index 9bdfb28c..5b9e2796 100644 --- a/neo/d3xp/menus/MenuHandler_HUD.cpp +++ b/neo/d3xp/menus/MenuHandler_HUD.cpp @@ -184,7 +184,7 @@ idMenuHandler_HUD::ShowTip */ void idMenuHandler_HUD::ShowTip( const char* title, const char* tip, bool autoHide ) { - autoHideTip = autoHideTip; + autoHideTip = autoHide; // SRS - Changed to assign autoHide to autoHideTip vs. assign autoHideTip to itself tipStartTime = gameLocal.time; hiding = false; idMenuScreen_HUD* screen = GetHud(); diff --git a/neo/d3xp/menus/MenuWidget_Scrollbar.cpp b/neo/d3xp/menus/MenuWidget_Scrollbar.cpp index aef26ef8..2dbc56ac 100644 --- a/neo/d3xp/menus/MenuWidget_Scrollbar.cpp +++ b/neo/d3xp/menus/MenuWidget_Scrollbar.cpp @@ -268,7 +268,7 @@ bool idMenuWidget_ScrollBar::HandleAction( idWidgetAction& action, const idWidge CalculatePosition( x, y ); return true; } - case WIDGET_ACTION_EVENT_DRAG_STOP: + case ( widgetAction_t ) WIDGET_ACTION_EVENT_DRAG_STOP: // SRS - Cast actionHandler_t to widgetAction_t { dragging = false; return true; diff --git a/neo/d3xp/script/Script_Program.cpp b/neo/d3xp/script/Script_Program.cpp index e5c80501..2a6ff0b6 100644 --- a/neo/d3xp/script/Script_Program.cpp +++ b/neo/d3xp/script/Script_Program.cpp @@ -764,7 +764,7 @@ idVarDef::SetObject void idVarDef::SetObject( idScriptObject* object ) { assert( typeDef ); - initialized = initialized; + initialized = initializedConstant; // SRS - Set initialized to initializedConstant vs self-assignment assert( typeDef->Inherits( &type_object ) ); *value.objectPtrPtr = object; } diff --git a/neo/framework/CmdSystem.cpp b/neo/framework/CmdSystem.cpp index 14476e93..3a072807 100644 --- a/neo/framework/CmdSystem.cpp +++ b/neo/framework/CmdSystem.cpp @@ -75,8 +75,9 @@ public: virtual void BufferCommandText( cmdExecution_t exec, const char* text ); virtual void ExecuteCommandBuffer(); - - virtual void ArgCompletion_FolderExtension( const idCmdArgs& args, void( *callback )( const char* s ), const char* folder, bool stripFolder, ... ); + + virtual void ArgCompletion_FolderExtension( const idCmdArgs& args, void( *callback )( const char* s ), const char* folder, int stripFolder, ... ); + // SRS - Changed stripFolder type from bool to int for compatibility with va_start() virtual void ArgCompletion_DeclName( const idCmdArgs& args, void( *callback )( const char* s ), int type ); virtual void BufferCommandArgs( cmdExecution_t exec, const idCmdArgs& args ); @@ -796,7 +797,8 @@ void idCmdSystemLocal::ExecuteCommandBuffer() idCmdSystemLocal::ArgCompletion_FolderExtension ============ */ -void idCmdSystemLocal::ArgCompletion_FolderExtension( const idCmdArgs& args, void( *callback )( const char* s ), const char* folder, bool stripFolder, ... ) +void idCmdSystemLocal::ArgCompletion_FolderExtension( const idCmdArgs& args, void( *callback )( const char* s ), const char* folder, int stripFolder, ... ) + // SRS - Changed stripFolder type from bool to int for compatibility with va_start() { int i; idStr string; diff --git a/neo/framework/CmdSystem.h b/neo/framework/CmdSystem.h index 06c7737b..1d2a5e46 100644 --- a/neo/framework/CmdSystem.h +++ b/neo/framework/CmdSystem.h @@ -170,7 +170,8 @@ public: virtual void ExecuteCommandBuffer() = 0; // Base for path/file auto-completion. - virtual void ArgCompletion_FolderExtension( const idCmdArgs& args, void( *callback )( const char* s ), const char* folder, bool stripFolder, ... ) = 0; + virtual void ArgCompletion_FolderExtension( const idCmdArgs& args, void( *callback )( const char* s ), const char* folder, int stripFolder, ... ) = 0; + // SRS - Changed stripFolder type from bool to int for compatibility with va_start() // Base for decl name auto-completion. virtual void ArgCompletion_DeclName( const idCmdArgs& args, void( *callback )( const char* s ), int type ) = 0; diff --git a/neo/framework/Common.cpp b/neo/framework/Common.cpp index be14d261..c851bbc3 100644 --- a/neo/framework/Common.cpp +++ b/neo/framework/Common.cpp @@ -76,7 +76,7 @@ idCVar com_forceGenericSIMD( "com_forceGenericSIMD", "0", CVAR_BOOL | CVAR_SYSTE idCVar com_developer( "developer", "0", CVAR_BOOL | CVAR_SYSTEM | CVAR_NOCHEAT, "developer mode" ); idCVar com_speeds( "com_speeds", "0", CVAR_BOOL | CVAR_SYSTEM | CVAR_NOCHEAT, "show engine timings" ); // DG: support "com_showFPS 1" for fps-only view like in classic doom3 => make it CVAR_INTEGER -idCVar com_showFPS( "com_showFPS", "0", CVAR_INTEGER | CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT, "show frames rendered per second. 0: off 1: default bfg values, 2: only show FPS (classic view)" ); +idCVar com_showFPS( "com_showFPS", "0", CVAR_INTEGER | CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_NOCHEAT, "show frames rendered per second. 0: off, 1: only show FPS (classic view), 2: default bfg values" ); // DG end idCVar com_showMemoryUsage( "com_showMemoryUsage", "0", CVAR_BOOL | CVAR_SYSTEM | CVAR_NOCHEAT, "show total and per frame memory usage" ); idCVar com_updateLoadSize( "com_updateLoadSize", "0", CVAR_BOOL | CVAR_SYSTEM | CVAR_NOCHEAT, "update the load size after loading a map" ); @@ -1338,7 +1338,8 @@ void idCommonLocal::Init( int argc, const char* const* argv, const char* cmdline // display the legal splash screen // No clue why we have to render this twice to show up... RenderSplash(); - //RenderSplash(); + // SRS - OSX needs this for some OpenGL drivers, otherwise renders leftover image before splash + RenderSplash(); } @@ -1420,7 +1421,8 @@ void idCommonLocal::Init( int argc, const char* const* argv, const char* cmdline AddStartupCommands(); StartMenu( true ); -#ifndef ID_RETAIL +// SRS - changed ifndef to ifdef since legalMinTime should apply to retail builds, not dev builds +#ifdef ID_RETAIL while( Sys_Milliseconds() - legalStartTime < legalMinTime ) { RenderSplash(); @@ -1792,7 +1794,8 @@ idCommonLocal::ProcessEvent bool idCommonLocal::ProcessEvent( const sysEvent_t* event ) { // hitting escape anywhere brings up the menu - if( game && game->IsInGame() ) + // SRS - allow escape during demo playback to cancel + if( game && ( game->IsInGame() || readDemo ) ) { if( event->evType == SE_KEY && event->evValue2 == 1 && ( event->evValue == K_ESCAPE || event->evValue == K_JOY9 ) ) { @@ -1812,8 +1815,16 @@ bool idCommonLocal::ProcessEvent( const sysEvent_t* event ) } console->Close(); - - StartMenu(); + + // SRS - cancel demo playback and return to the main menu + if ( readDemo ) + { + LeaveGame(); + } + else + { + StartMenu(); + } return true; } else diff --git a/neo/framework/Common_demos.cpp b/neo/framework/Common_demos.cpp index ef444fa3..b32aa218 100644 --- a/neo/framework/Common_demos.cpp +++ b/neo/framework/Common_demos.cpp @@ -55,7 +55,7 @@ static idStr FindUnusedFileName( const char* format ) return filename; } -extern idCVar com_smp; +//extern idCVar com_smp; // SRS - No longer require non-smp mode for demos void WriteDeclCache( idDemoFile* f, int demoCategory, int demoCode, declType_t declType ) { @@ -106,7 +106,7 @@ void idCommonLocal::StartRecordingRenderDemo( const char* demoName ) console->Close(); - com_smp.SetInteger( 0 ); +// com_smp.SetInteger( 0 ); // SRS - No longer require non-smp mode for demos writeDemo = new( TAG_SYSTEM ) idDemoFile; if( !writeDemo->OpenForWriting( demoName ) ) @@ -146,7 +146,7 @@ void idCommonLocal::StopRecordingRenderDemo() common->Printf( "stopped recording %s.\n", writeDemo->GetName() ); delete writeDemo; writeDemo = NULL; - com_smp.SetInteger( 1 ); // motorsep 12-30-2014; turn multithreading back on +// com_smp.SetInteger( 1 ); // motorsep 12-30-2014; turn multithreading back on; SRS - No longer require non-smp mode for demos } /* @@ -193,7 +193,7 @@ void idCommonLocal::StopPlayingRenderDemo() timeDemo = TD_NO; } - com_smp.SetInteger( 1 ); // motorsep 12-30-2014; turn multithreading back on +// com_smp.SetInteger( 1 ); // motorsep 12-30-2014; turn multithreading back on; SRS - No longer require non-smp mode for demos } /* @@ -227,7 +227,7 @@ void idCommonLocal::StartPlayingRenderDemo( idStr demoName ) return; } - com_smp.SetInteger( 0 ); +// com_smp.SetInteger( 0 ); // SRS - No longer require non-smp mode for demos // make sure localSound / GUI intro music shuts up soundWorld->StopAllSounds(); @@ -248,7 +248,8 @@ void idCommonLocal::StartPlayingRenderDemo( idStr demoName ) common->Printf( "couldn't open %s\n", demoName.c_str() ); delete readDemo; readDemo = NULL; - Stop(); + + CreateMainMenu(); // SRS - drop back to main menu if demo playback fails StartMenu(); return; } @@ -258,8 +259,11 @@ void idCommonLocal::StartPlayingRenderDemo( idStr demoName ) if( opcode != DS_VERSION ) { common->Printf( "StartPlayingRenderDemo invalid demo file\n" ); - - Stop(); + readDemo->Close(); + delete readDemo; + readDemo = NULL; + + CreateMainMenu(); // SRS - drop back to main menu if demo playback fails StartMenu(); return; } @@ -268,22 +272,35 @@ void idCommonLocal::StartPlayingRenderDemo( idStr demoName ) if( demoVersion != RENDERDEMO_VERSION ) { common->Printf( "StartPlayingRenderDemo got version %d, expected version %d\n", demoVersion, RENDERDEMO_VERSION ); + readDemo->Close(); + delete readDemo; + readDemo = NULL; - Stop(); + CreateMainMenu(); // SRS - drop back to main menu if demo playback fails StartMenu(); return; } + + numDemoFrames = 0; // SRS - Moved ahead of first call to AdvanceRenderDemo to properly handle demoshots + numShotFrames = 0; // SRS - Initialize count of demoShot frames to play before timeout to main menu - AdvanceRenderDemo( true ); + renderSystem->BeginLevelLoad(); // SRS - Free static data from previous level before loading demo assets + soundSystem->BeginLevelLoad(); // SRS - Free sound media from previous level before loading demo assets + declManager->BeginLevelLoad(); // SRS - Clear declaration manager data before loading demo assets + uiManager->BeginLevelLoad(); // SRS - Clear gui manager data before loading demo assets - Game()->StartDemoPlayback( renderWorld ); + AdvanceRenderDemo( true ); // SRS - Call AdvanceRenderDemo() once to load map and initial assets (like level load) + + renderSystem->EndLevelLoad(); // SRS - Define static data for use by RB_StencilShadowPass if stencil shadows enabled + soundSystem->EndLevelLoad(); + declManager->EndLevelLoad(); + uiManager->EndLevelLoad( "" ); // SRS - FIXME: No gui assets are currently saved/reloaded in demo file, fix later? - renderWorld->GenerateAllInteractions(); - - const bool captureToImage = false; - UpdateScreen( captureToImage ); - - numDemoFrames = 1; + Game()->StartDemoPlayback( renderWorld ); + + renderWorld->GenerateAllInteractions(); + + soundSystem->SetPlayingSoundWorld( soundWorld ); timeDemoStartTime = Sys_Milliseconds(); } @@ -301,11 +318,15 @@ void idCommonLocal::TimeRenderDemo( const char* demoName, bool twice, bool quit if( twice && readDemo ) { - while( readDemo ) + timeDemo = TD_YES; // SRS - Set timeDemo to TD_YES to disable time demo playback pause when window not in focus + + while( readDemo ) { - const bool captureToImage = false; - UpdateScreen( captureToImage ); - AdvanceRenderDemo( true ); +// const bool captureToImage = false; +// UpdateScreen( captureToImage ); + BusyWait(); // SRS - Call BusyWait() vs. UpdateScreen() to avoid Pump() timeout messages in console + AdvanceRenderDemo( true ); + eventLoop->RunEventLoop(); // SRS - Run event loop to allow keyboard escape to cancel first pass of the demo } StartPlayingRenderDemo( demo ); @@ -314,6 +335,7 @@ void idCommonLocal::TimeRenderDemo( const char* demoName, bool twice, bool quit if( !readDemo ) { + timeDemo = TD_NO; // SRS - Make sure timeDemo flag is off if readDemo is NULL return; } @@ -499,14 +521,15 @@ void idCommonLocal::AdvanceRenderDemo( bool singleFrameOnly ) switch( ds ) { case DS_FINISHED: - if( numDemoFrames != 1 ) + if( numDemoFrames == 1 ) { - // if the demo has a single frame (a demoShot), continuously replay - // the renderView that has already been read - Stop(); - StartMenu(); - } - return; + // if the demo has a single frame (a demoShot), continuously replay + // the renderView that has already been read + if ( numShotFrames++ < com_engineHz_latched*10 ) // SRS - play demoShot for min 10 sec then timeout + return; + } + LeaveGame(); // SRS - drop back to main menu after demo playback is finished + return; case DS_RENDER: if( renderWorld->ProcessDemoCommand( readDemo, ¤tDemoRenderView, &demoTimeOffset ) ) { @@ -527,12 +550,14 @@ void idCommonLocal::AdvanceRenderDemo( bool singleFrameOnly ) } } +// SRS - Changed macro from CONSOLE_COMMAND to CONSOLE_COMMAND_SHIP for demo-related commands - i.e. include in release builds + /* ================ Common_DemoShot_f ================ */ -CONSOLE_COMMAND( demoShot, "writes a screenshot as a demo", NULL ) +CONSOLE_COMMAND_SHIP( demoShot, "writes a screenshot as a demo", NULL ) { if( args.Argc() != 2 ) { @@ -550,7 +575,7 @@ CONSOLE_COMMAND( demoShot, "writes a screenshot as a demo", NULL ) Common_RecordDemo_f ================ */ -CONSOLE_COMMAND( recordDemo, "records a demo", NULL ) +CONSOLE_COMMAND_SHIP( recordDemo, "records a demo", NULL ) { if( args.Argc() != 2 ) { @@ -568,7 +593,7 @@ CONSOLE_COMMAND( recordDemo, "records a demo", NULL ) Common_CompressDemo_f ================ */ -CONSOLE_COMMAND( compressDemo, "compresses a demo file", idCmdSystem::ArgCompletion_DemoName ) +CONSOLE_COMMAND_SHIP( compressDemo, "compresses a demo file", idCmdSystem::ArgCompletion_DemoName ) { if( args.Argc() == 2 ) { @@ -589,7 +614,7 @@ CONSOLE_COMMAND( compressDemo, "compresses a demo file", idCmdSystem::ArgComplet Common_StopRecordingDemo_f ================ */ -CONSOLE_COMMAND( stopRecording, "stops demo recording", NULL ) +CONSOLE_COMMAND_SHIP( stopRecording, "stops demo recording", NULL ) { commonLocal.StopRecordingRenderDemo(); } @@ -599,7 +624,7 @@ CONSOLE_COMMAND( stopRecording, "stops demo recording", NULL ) Common_PlayDemo_f ================ */ -CONSOLE_COMMAND( playDemo, "plays back a demo", idCmdSystem::ArgCompletion_DemoName ) +CONSOLE_COMMAND_SHIP( playDemo, "plays back a demo", idCmdSystem::ArgCompletion_DemoName ) { if( args.Argc() >= 2 ) { @@ -612,7 +637,7 @@ CONSOLE_COMMAND( playDemo, "plays back a demo", idCmdSystem::ArgCompletion_DemoN Common_TimeDemo_f ================ */ -CONSOLE_COMMAND( timeDemo, "times a demo", idCmdSystem::ArgCompletion_DemoName ) +CONSOLE_COMMAND_SHIP( timeDemo, "times a demo", idCmdSystem::ArgCompletion_DemoName ) { if( args.Argc() >= 2 ) { @@ -625,9 +650,9 @@ CONSOLE_COMMAND( timeDemo, "times a demo", idCmdSystem::ArgCompletion_DemoName ) Common_TimeDemoQuit_f ================ */ -CONSOLE_COMMAND( timeDemoQuit, "times a demo and quits", idCmdSystem::ArgCompletion_DemoName ) +CONSOLE_COMMAND_SHIP( timeDemoQuit, "times a demo and quits", idCmdSystem::ArgCompletion_DemoName ) { - commonLocal.TimeRenderDemo( va( "demos/%s", args.Argv( 1 ) ), true ); + commonLocal.TimeRenderDemo( va( "demos/%s", args.Argv( 1 ) ), ( args.Argc() > 2 ), true ); // SRS - fixed missing "twice" argument } /* @@ -635,7 +660,7 @@ CONSOLE_COMMAND( timeDemoQuit, "times a demo and quits", idCmdSystem::ArgComplet Common_AVIDemo_f ================ */ -CONSOLE_COMMAND( aviDemo, "writes AVIs for a demo", idCmdSystem::ArgCompletion_DemoName ) +CONSOLE_COMMAND_SHIP( aviDemo, "writes AVIs for a demo", idCmdSystem::ArgCompletion_DemoName ) { commonLocal.AVIRenderDemo( va( "demos/%s", args.Argv( 1 ) ) ); } @@ -645,7 +670,7 @@ CONSOLE_COMMAND( aviDemo, "writes AVIs for a demo", idCmdSystem::ArgCompletion_D Common_AVIGame_f ================ */ -CONSOLE_COMMAND( aviGame, "writes AVIs for the current game", NULL ) +CONSOLE_COMMAND_SHIP( aviGame, "writes AVIs for the current game", NULL ) { commonLocal.AVIGame( args.Argv( 1 ) ); } diff --git a/neo/framework/Common_local.h b/neo/framework/Common_local.h index 7367a6a1..1359cef0 100644 --- a/neo/framework/Common_local.h +++ b/neo/framework/Common_local.h @@ -547,6 +547,7 @@ private: timeDemo_t timeDemo; int timeDemoStartTime; int numDemoFrames; // for timeDemo and demoShot + int numShotFrames; // SRS - for demoShot playback timeout int demoTimeOffset; renderView_t currentDemoRenderView; diff --git a/neo/framework/common_frame.cpp b/neo/framework/common_frame.cpp index f31e0e99..7ccd949b 100644 --- a/neo/framework/common_frame.cpp +++ b/neo/framework/common_frame.cpp @@ -195,7 +195,7 @@ gameReturn_t idGameThread::RunGameAndDraw( int numGameFrames_, idUserCmdMgr& use // start the thread going // foresthale 2014-05-12: also check com_editors as many of them are not particularly thread-safe (editLights for example) - if( com_smp.GetBool() == false || com_editors != 0 ) + if( com_smp.GetInteger() <= 0 || com_editors != 0 ) { // run it in the main thread so PIX profiling catches everything Run(); @@ -347,7 +347,8 @@ void idCommonLocal::Draw() } else if( readDemo ) { - AdvanceRenderDemo( true ); + // SRS - Advance demo inside Frame() instead of Draw() to support smp mode playback + // AdvanceRenderDemo( true ); renderWorld->RenderScene( ¤tDemoRenderView ); renderSystem->DrawDemoPics(); } @@ -563,7 +564,8 @@ void idCommonLocal::Frame() // RB end, DG end { // RB: don't release the mouse when opening a PDA or menu - if( console->Active() || ImGuiTools::ReleaseMouseForTools() ) + // SRS - don't release when console open in a game (otherwise may be out of frame on return) but always release at main menu + if( ( console->Active() && !game ) || !mapSpawned || ImGuiTools::ReleaseMouseForTools() ) { Sys_GrabMouseCursor( false ); } @@ -679,7 +681,8 @@ void idCommonLocal::Frame() // don't run any frames when paused // jpcy: the game is paused when playing a demo, but playDemo should wait like the game does - if( pauseGame && !( readDemo && !timeDemo ) ) + // SRS - don't wait if window not in focus and playDemo itself paused + if( pauseGame && ( !( readDemo && !timeDemo ) || session->IsSystemUIShowing() || com_pause.GetInteger() ) ) { gameFrame++; gameTimeResidual = 0; @@ -766,6 +769,11 @@ void idCommonLocal::Frame() ExecuteMapChange(); mapSpawnData.savegameFile = NULL; mapSpawnData.persistentPlayerInfo.Clear(); + // SRS - If in Doom 3 mode (com_smp = -1) on map change, must obey fence before returning to avoid command buffer sync issues + if( com_smp.GetInteger() < 0 ) + { + renderSystem->SwapCommandBuffers_FinishRendering( &time_frontend, &time_backend, &time_shadows, &time_gpu, &stats_backend, &stats_frontend ); + } return; } else if( session->GetState() != idSession::INGAME && mapSpawned ) @@ -788,7 +796,19 @@ void idCommonLocal::Frame() // send frame and mouse events to active guis GuiFrameEvents(); - + + // SRS - Advance demos inside Frame() vs. Draw() to support smp mode playback + // SRS - Pause playDemo (but not timeDemo) when window not in focus + if ( readDemo && ( !( session->IsSystemUIShowing() || com_pause.GetInteger() ) || timeDemo ) ) + { + AdvanceRenderDemo( true ); + if( !readDemo ) + { + // SRS - Important to return after demo playback is finished to avoid command buffer sync issues + return; + } + } + //-------------------------------------------- // Prepare usercmds and kick off the game processing // in a background thread @@ -839,7 +859,8 @@ void idCommonLocal::Frame() // RB begin #if defined(USE_DOOMCLASSIC) // If we're in Doom or Doom 2, run tics and upload the new texture. - if( ( GetCurrentGame() == DOOM_CLASSIC || GetCurrentGame() == DOOM2_CLASSIC ) && !( Dialog().IsDialogPausing() || session->IsSystemUIShowing() ) ) + // SRS - Add check for com_pause cvar to make sure window is in focus - if not classic game should be paused (FIXME: but classic music still plays in background) + if( ( GetCurrentGame() == DOOM_CLASSIC || GetCurrentGame() == DOOM2_CLASSIC ) && !( Dialog().IsDialogPausing() || session->IsSystemUIShowing() || com_pause.GetInteger() ) ) { RunDoomClassicFrame(); } @@ -850,12 +871,7 @@ void idCommonLocal::Frame() gameReturn_t ret = gameThread.RunGameAndDraw( numGameFrames, userCmdMgr, IsClient(), gameFrame - numGameFrames ); // foresthale 2014-05-12: also check com_editors as many of them are not particularly thread-safe (editLights for example) - if( com_smp.GetInteger() < 0 ) - { - // RB: this is the same as Doom 3 renderSystem->EndFrame() - renderSystem->SwapCommandBuffers_FinishRendering( &time_frontend, &time_backend, &time_shadows, &time_gpu, &stats_backend, &stats_frontend ); - } - else if( com_smp.GetInteger() == 0 || com_editors != 0 ) + if( com_smp.GetInteger() == 0 || com_editors != 0 ) { // in non-smp mode, run the commands we just generated, instead of // frame-delayed ones from a background thread @@ -875,6 +891,13 @@ void idCommonLocal::Frame() } frameTiming.finishRenderTime = Sys_Microseconds(); + // SRS - If in Doom 3 mode (com_smp = -1), must sync after RenderCommandBuffers() otherwise get artifacts due to improper command buffer swap timing + if( com_smp.GetInteger() < 0 ) + { + // RB: this is the same as Doom 3 renderSystem->EndFrame() + renderSystem->SwapCommandBuffers_FinishRendering( &time_frontend, &time_backend, &time_shadows, &time_gpu, &stats_backend, &stats_frontend ); + } + // make sure the game / draw thread has completed // This may block if the game is taking longer than the render back end gameThread.WaitForThread(); @@ -888,7 +911,8 @@ void idCommonLocal::Frame() SendSnapshots(); // Render the sound system using the latest commands from the game thread - if( pauseGame ) + // SRS - Enable sound during normal playDemo playback but not during timeDemo + if( pauseGame && !( readDemo && !timeDemo ) ) { soundWorld->Pause(); soundSystem->SetPlayingSoundWorld( menuSoundWorld ); @@ -898,6 +922,10 @@ void idCommonLocal::Frame() soundWorld->UnPause(); soundSystem->SetPlayingSoundWorld( soundWorld ); } + // SRS - Play silence when dialog waiting or window not in focus + if ( Dialog().IsDialogPausing() || session->IsSystemUIShowing() || com_pause.GetInteger() ) + soundSystem->SetPlayingSoundWorld( NULL ); + soundSystem->Render(); // process the game return for map changes, etc diff --git a/neo/idlib/Heap.h b/neo/idlib/Heap.h index 65ceeb67..9cf4fc4b 100644 --- a/neo/idlib/Heap.h +++ b/neo/idlib/Heap.h @@ -72,7 +72,8 @@ ID_INLINE void* operator new( size_t s ) return Mem_Alloc( s, TAG_NEW ); } -ID_INLINE void operator delete( void* p ) +// SRS - Added noexcept to silence build-time warning +ID_INLINE void operator delete( void* p ) noexcept { Mem_Free( p ); } @@ -81,7 +82,8 @@ ID_INLINE void* operator new[]( size_t s ) return Mem_Alloc( s, TAG_NEW ); } -ID_INLINE void operator delete[]( void* p ) +// SRS - Added noexcept to silence build-time warning +ID_INLINE void operator delete[]( void* p ) noexcept { Mem_Free( p ); } @@ -352,7 +354,7 @@ ID_INLINE _type_* idBlockAlloc<_type_, _blockSize_, memTag>::Alloc() _type_ * t = ( _type_* ) element->buffer; if( clearAllocs ) { - memset( t, 0, sizeof( _type_ ) ); + memset( (void*)t, 0, sizeof( _type_ ) ); // SRS - Added (void*) cast to silence build-time warning } new( t ) _type_; return t; diff --git a/neo/idlib/Lib.cpp b/neo/idlib/Lib.cpp index fb3d7b0e..2aaf6cc5 100644 --- a/neo/idlib/Lib.cpp +++ b/neo/idlib/Lib.cpp @@ -197,6 +197,8 @@ void idLib::FatalError( const char* fmt, ... ) va_end( argptr ); common->FatalError( "%s", text ); + + exit(EXIT_FAILURE); // SRS - Added exit to silence build warning since FatalError has attribute noreturn } /* @@ -214,6 +216,8 @@ void idLib::Error( const char* fmt, ... ) va_end( argptr ); common->Error( "%s", text ); + + exit(EXIT_FAILURE); // SRS - Added exit to silence build warning since Error has attribute noreturn } /* diff --git a/neo/idlib/containers/StaticList.h b/neo/idlib/containers/StaticList.h index 574c81ef..036c61e9 100644 --- a/neo/idlib/containers/StaticList.h +++ b/neo/idlib/containers/StaticList.h @@ -150,8 +150,9 @@ Note: The data is merely moved around the list, so any pointers to data within t template< class type, int size > ID_INLINE void idStaticList::Sort( const idSort& sort ) { - if( list == NULL ) - { +/* if( list == NULL ) */ + if( Num() <= 0 ) // SRS - Instead of checking this->list for NULL, check this->Num() for empty list + { return; } sort.Sort( Ptr(), Num() ); diff --git a/neo/idlib/containers/StrPool.h b/neo/idlib/containers/StrPool.h index 524df41c..e1a7aab9 100644 --- a/neo/idlib/containers/StrPool.h +++ b/neo/idlib/containers/StrPool.h @@ -181,14 +181,20 @@ ID_INLINE void idStrPool::FreeString( const idPoolStr* poolStr ) * we're shutting down (at this point) just get rid of the following assertion: * assert( poolStr->numUsers >= 1 ); */ - if( poolStr->numUsers < 1 ) - { - return; - } + //if( poolStr->numUsers < 1 ) // SRS - This test does not work if idStrPool is empty and poolStr->numUsers is undefined + //{ + // return; + //} // DG end + if( pool.Num() <= 0 ) // SRS - Instead, check for empty idStrPool and return to prevent segfaulting on shutdown + { + return; + } + assert( poolStr->pool == this ); - + assert( poolStr->numUsers >= 1 ); // SRS - Reestablish assertion + poolStr->numUsers--; if( poolStr->numUsers <= 0 ) { diff --git a/neo/idlib/math/Simd.h b/neo/idlib/math/Simd.h index da6ce66f..e8b189df 100644 --- a/neo/idlib/math/Simd.h +++ b/neo/idlib/math/Simd.h @@ -93,7 +93,9 @@ public: } cpuid_t cpuid; - + + virtual ~idSIMDProcessor() {} // SRS - Added virtual destructor + virtual const char* VPCALL GetName() const = 0; virtual void VPCALL MinMax( float& min, float& max, const float* src, const int count ) = 0; diff --git a/neo/idlib/precompiled.h b/neo/idlib/precompiled.h index 80d734fb..d2f554be 100644 --- a/neo/idlib/precompiled.h +++ b/neo/idlib/precompiled.h @@ -87,7 +87,12 @@ const int MAX_EXPRESSION_REGISTERS = 4096; // everything that is needed by the backend needs // to be double buffered to allow it to run in // parallel on a dual cpu machine -const uint32 NUM_FRAME_DATA = 2; +#if defined(__APPLE__) && defined(USE_VULKAN) +// SRS - macOS MoltenVK/Metal needs triple buffering for full screen to work properly +const uint32 NUM_FRAME_DATA = 3; +#else +const uint32 NUM_FRAME_DATA = 2; +#endif #if defined(USE_VULKAN) #include "../renderer/Vulkan/qvk.h" diff --git a/neo/idlib/sys/sys_types.h b/neo/idlib/sys/sys_types.h index 98fc1bde..8b17ef0c 100644 --- a/neo/idlib/sys/sys_types.h +++ b/neo/idlib/sys/sys_types.h @@ -165,8 +165,11 @@ ID_INLINE void WriteIndexPair( triIndex_t* dest, const triIndex_t a, const triIn #else #ifdef _MSVC #define NODEFAULT default: __assume( 0 ) - #else // not _MSVC + #elif defined(__GNUC__) // TODO: is that __assume an important optimization? if so, is there a gcc equivalent? + // SRS - The gcc equivalent is __builtin_unreachable() + #define NODEFAULT default: __builtin_unreachable() + #else // not _MSVC and not __GNUC__ #define NODEFAULT #endif #endif diff --git a/neo/libs/jpeg-6/jconfig.h b/neo/libs/jpeg-6/jconfig.h index 7d2f733b..642a0e27 100644 --- a/neo/libs/jpeg-6/jconfig.h +++ b/neo/libs/jpeg-6/jconfig.h @@ -8,7 +8,10 @@ /* #define const */ #define CHAR_IS_UNSIGNED #define HAVE_STDDEF_H +// SRS - don't redefine HAVE_STDLIB_H if already defined +#ifndef HAVE_STDLIB_H #define HAVE_STDLIB_H +#endif #undef NEED_BSD_STRINGS #undef NEED_SYS_TYPES_H #undef NEED_FAR_POINTERS /* Watcom uses flat 32-bit addressing */ diff --git a/neo/libs/jpeg-6/jdapimin.cpp b/neo/libs/jpeg-6/jdapimin.cpp index 7fdc4be6..3f9ddbc2 100644 --- a/neo/libs/jpeg-6/jdapimin.cpp +++ b/neo/libs/jpeg-6/jdapimin.cpp @@ -369,8 +369,8 @@ jpeg_has_multiple_scans( j_decompress_ptr cinfo ) { GLOBAL boolean jpeg_finish_decompress( j_decompress_ptr cinfo ) { - if ( ( ( cinfo->global_state == DSTATE_SCANNING ) || - ( cinfo->global_state == DSTATE_RAW_OK ) && !cinfo->buffered_image ) ) { + if ( ( cinfo->global_state == DSTATE_SCANNING ) || + ( ( cinfo->global_state == DSTATE_RAW_OK ) && !cinfo->buffered_image ) ) { // SRS - Relocated parentheses to surround && expression /* Terminate final pass of non-buffered mode */ if ( cinfo->output_scanline < cinfo->output_height ) { ERREXIT( cinfo, JERR_TOO_LITTLE_DATA ); diff --git a/neo/libs/jpeg-6/jdhuff.cpp b/neo/libs/jpeg-6/jdhuff.cpp index e2512c40..96fa93f0 100644 --- a/neo/libs/jpeg-6/jdhuff.cpp +++ b/neo/libs/jpeg-6/jdhuff.cpp @@ -381,11 +381,12 @@ static const int extend_test[16] = /* entry n is 2**(n-1) */ { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; -static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ -{ 0, ( ( -1 ) << 1 ) + 1, ( ( -1 ) << 2 ) + 1, ( ( -1 ) << 3 ) + 1, ( ( -1 ) << 4 ) + 1, - ( ( -1 ) << 5 ) + 1, ( ( -1 ) << 6 ) + 1, ( ( -1 ) << 7 ) + 1, ( ( -1 ) << 8 ) + 1, - ( ( -1 ) << 9 ) + 1, ( ( -1 ) << 10 ) + 1, ( ( -1 ) << 11 ) + 1, ( ( -1 ) << 12 ) + 1, - ( ( -1 ) << 13 ) + 1, ( ( -1 ) << 14 ) + 1, ( ( -1 ) << 15 ) + 1 }; +static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ // SRS - Cast to unsigned int +{ 0, static_cast(( (unsigned int)( -1 ) << 1 ) + 1), static_cast(( (unsigned int)( -1 ) << 2 ) + 1), static_cast(( (unsigned int)( -1 ) << 3 ) + 1), + static_cast(( (unsigned int)( -1 ) << 4 ) + 1), static_cast(( (unsigned int)( -1 ) << 5 ) + 1), static_cast(( (unsigned int)( -1 ) << 6 ) + 1), + static_cast(( (unsigned int)( -1 ) << 7 ) + 1), static_cast(( (unsigned int)( -1 ) << 8 ) + 1), static_cast(( (unsigned int)( -1 ) << 9 ) + 1), + static_cast(( (unsigned int)( -1 ) << 10 ) + 1), static_cast(( (unsigned int)( -1 ) << 11 ) + 1), static_cast(( (unsigned int)( -1 ) << 12 ) + 1), + static_cast(( (unsigned int)( -1 ) << 13 ) + 1), static_cast(( (unsigned int)( -1 ) << 14 ) + 1), static_cast(( (unsigned int)( -1 ) << 15 ) + 1) }; #endif /* AVOID_TABLES */ diff --git a/neo/libs/zlib/gzguts.h b/neo/libs/zlib/gzguts.h index ee3f281a..0ff3479d 100644 --- a/neo/libs/zlib/gzguts.h +++ b/neo/libs/zlib/gzguts.h @@ -33,6 +33,8 @@ #if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) # include +#elif defined(__GNUC__) +# include // SRS - For explicit declaration of lseek, read, write, close #endif #ifdef NO_DEFLATE /* for compatibility with old definition */ diff --git a/neo/libs/zlib/inflate.c b/neo/libs/zlib/inflate.c index 47418a1e..5bd48453 100644 --- a/neo/libs/zlib/inflate.c +++ b/neo/libs/zlib/inflate.c @@ -1488,7 +1488,7 @@ z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; + if (strm == Z_NULL || strm->state == Z_NULL) return (unsigned long)(-1L) << 16; // SRS - Cast to unsigned long state = (struct inflate_state FAR *)strm->state; return ((long)(state->back) << 16) + (state->mode == COPY ? state->length : diff --git a/neo/renderer/BinaryImage.cpp b/neo/renderer/BinaryImage.cpp index 07a2bd82..aee2fac6 100644 --- a/neo/renderer/BinaryImage.cpp +++ b/neo/renderer/BinaryImage.cpp @@ -896,16 +896,64 @@ bool idBinaryImage::LoadFromGeneratedFile( idFile* bFile, ID_TIME_T sourceTimeSt // sizes are still retained, so the stored data size may be larger than // just the multiplication of dimensions assert( img.dataSize >= img.width * img.height * BitsForFormat( ( textureFormat_t )fileData.format ) / 8 ); - img.Alloc( img.dataSize ); +#if defined(__APPLE__) && defined(USE_VULKAN) + int imgfile_dataSize = img.dataSize; + // SRS - Allocate 2x memory to prepare for in-place conversion from FMT_RGB565 to FMT_RGBA8 + if( ( textureFormat_t )fileData.format == FMT_RGB565 ) + { + img.Alloc( img.dataSize * 2 ); + } + else + { + img.Alloc( img.dataSize ); + } if( img.data == NULL ) { return false; } - if( bFile->Read( img.data, img.dataSize ) <= 0 ) + // SRS - Read image data using actual on-disk data size + if( bFile->Read( img.data, imgfile_dataSize ) <= 0 ) { return false; } + + // SRS - Convert FMT_RGB565 16-bits to FMT_RGBA8 32-bits in place using pre-allocated space + if( ( textureFormat_t )fileData.format == FMT_RGB565 ) + { + //SRS - Make sure we have an integer number of RGBA8 storage slots + assert( img.dataSize % 4 == 0 ); + for( int pixelIndex = img.dataSize/2 - 2; pixelIndex >= 0; pixelIndex -= 2 ) + { +#if 1 + // SRS - Option 1: Scale and shift algorithm + uint16 pixelValue_rgb565 = img.data[pixelIndex + 0] << 8 | img.data[pixelIndex + 1]; + img.data[pixelIndex*2 + 0] = ( ( ( pixelValue_rgb565 ) >> 11 ) * 527 + 23 ) >> 6; + img.data[pixelIndex*2 + 1] = ( ( ( pixelValue_rgb565 & 0x07E0 ) >> 5 ) * 259 + 33 ) >> 6; + img.data[pixelIndex*2 + 2] = ( ( ( pixelValue_rgb565 & 0x001F ) ) * 527 + 23 ) >> 6; +#else + // SRS - Option 2: Shift and combine algorithm - is this faster? + uint8 pixelValue_rgb565_hi = img.data[pixelIndex + 0]; + uint8 pixelValue_rgb565_lo = img.data[pixelIndex + 1]; + img.data[pixelIndex*2 + 0] = ( pixelValue_rgb565_hi & 0xF8 ) | ( pixelValue_rgb565_hi >> 5 ); + img.data[pixelIndex*2 + 1] = ( pixelValue_rgb565_hi << 5 ) | ( ( pixelValue_rgb565_lo & 0xE0 ) >> 3 ) | ( ( pixelValue_rgb565_hi & 0x07 ) >> 1 ); + img.data[pixelIndex*2 + 2] = ( pixelValue_rgb565_lo << 3 ) | ( ( pixelValue_rgb565_lo & 0x1F ) >> 2 ); +#endif + img.data[pixelIndex*2 + 3] = 0xFF; + } + } +#else + img.Alloc( img.dataSize ); + if( img.data == NULL ) + { + return false; + } + + if( bFile->Read( img.data, img.dataSize ) <= 0 ) + { + return false; + } +#endif } return true; diff --git a/neo/renderer/Image.h b/neo/renderer/Image.h index 537257ca..6a57c69d 100644 --- a/neo/renderer/Image.h +++ b/neo/renderer/Image.h @@ -455,6 +455,9 @@ private: #if defined( USE_VULKAN ) void CreateSampler(); + // SRS - added method to set image layout + void SetImageLayout( VkImage image, VkImageSubresourceRange subresourceRange, VkImageLayout oldImageLayout, VkImageLayout newImageLayout ); + // SRS End bool bIsSwapChainImage; VkFormat internalFormat; diff --git a/neo/renderer/Image_load.cpp b/neo/renderer/Image_load.cpp index 928ae1f0..ca26b9d1 100644 --- a/neo/renderer/Image_load.cpp +++ b/neo/renderer/Image_load.cpp @@ -399,7 +399,12 @@ void idImage::ActuallyLoadImage( bool fromBackEnd ) if( ( fileSystem->InProductionMode() && binaryFileTime != FILE_NOT_FOUND_TIMESTAMP ) || ( ( binaryFileTime != FILE_NOT_FOUND_TIMESTAMP ) && ( header.colorFormat == opts.colorFormat ) +#if defined(__APPLE__) && defined(USE_VULKAN) + // SRS - Handle case when image read is cached and RGB565 format conversion is already done + && ( header.format == opts.format || ( header.format == FMT_RGB565 && opts.format == FMT_RGBA8 ) ) +#else && ( header.format == opts.format ) +#endif && ( header.textureType == opts.textureType ) ) ) { @@ -407,7 +412,17 @@ void idImage::ActuallyLoadImage( bool fromBackEnd ) opts.height = header.height; opts.numLevels = header.numLevels; opts.colorFormat = ( textureColor_t )header.colorFormat; - opts.format = ( textureFormat_t )header.format; +#if defined(__APPLE__) && defined(USE_VULKAN) + // SRS - Set in-memory format to FMT_RGBA8 for converted FMT_RGB565 image + if( header.format == FMT_RGB565 ) + { + opts.format = FMT_RGBA8; + } + else +#endif + { + opts.format = ( textureFormat_t )header.format; + } opts.textureType = ( textureType_t )header.textureType; if( cvarSystem->GetCVarBool( "fs_buildresources" ) ) { @@ -791,6 +806,28 @@ void idImage::GenerateImage( const byte* pic, int width, int height, textureFilt if( pic == NULL || opts.textureType == TT_2D_MULTISAMPLE ) { AllocImage(); + +#if defined(USE_VULKAN) + // SRS - update layout of Ambient Occlusion image otherwise get Vulkan validation layer errors with SSAO enabled + if( imgName == "_ao0" || imgName == "_ao1" ) + { + VkImageSubresourceRange subresourceRange; + if( internalFormat == VK_FORMAT_D32_SFLOAT_S8_UINT || opts.format == FMT_DEPTH ) + { + subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; + } + else + { + subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + } + subresourceRange.baseMipLevel = 0; + subresourceRange.levelCount = opts.numLevels; + subresourceRange.baseArrayLayer = 0; + subresourceRange.layerCount = 1; + + SetImageLayout( image, subresourceRange, VK_IMAGE_LAYOUT_UNDEFINED, layout ); + } +#endif } else { diff --git a/neo/renderer/OpenGL/Image_GL.cpp b/neo/renderer/OpenGL/Image_GL.cpp index 80a8dad4..cf790bd2 100644 --- a/neo/renderer/OpenGL/Image_GL.cpp +++ b/neo/renderer/OpenGL/Image_GL.cpp @@ -551,13 +551,13 @@ void idImage::SetTexParameters() } // RB: disabled use of unreliable extension that can make the game look worse - /* + // SRS - Try with feature turned back on using r_lodBias CVAR vs. hardcoded value if( glConfig.textureLODBiasAvailable && ( usage != TD_FONT ) ) { // use a blurring LOD bias in combination with high anisotropy to fix our aliasing grate textures... - glTexParameterf( target, GL_TEXTURE_LOD_BIAS_EXT, 0.5 ); //r_lodBias.GetFloat() ); + glTexParameterf( target, GL_TEXTURE_LOD_BIAS_EXT, /*0.5*/ r_lodBias.GetFloat() ); } - */ + // RB end // set the wrap/clamp modes diff --git a/neo/renderer/OpenGL/RenderBackend_GL.cpp b/neo/renderer/OpenGL/RenderBackend_GL.cpp index 0329538f..7f46ca4a 100644 --- a/neo/renderer/OpenGL/RenderBackend_GL.cpp +++ b/neo/renderer/OpenGL/RenderBackend_GL.cpp @@ -31,6 +31,19 @@ If you have questions concerning this license or the applicable additional terms #pragma hdrstop #include "precompiled.h" +// SRS - Include SDL headers to enable vsync changes without restart for UNIX-like OSs +#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) +// SRS - Don't seem to need these #undefs (at least on macOS), are they needed for Linux, etc? +// DG: SDL.h somehow needs the following functions, so #undef those silly +// "don't use" #defines from Str.h +//#undef strncmp +//#undef strcasecmp +//#undef vsnprintf +// DG end +#include +#endif +// SRS end + #include "../RenderCommon.h" #include "../RenderBackend.h" #include "../../framework/Common_local.h" @@ -339,10 +352,13 @@ static void R_CheckPortableExtensions() // GL_ARB_occlusion_query glConfig.occlusionQueryAvailable = GLEW_ARB_occlusion_query != 0; - // GL_ARB_timer_query using the DSA interface - //glConfig.timerQueryAvailable = ( GLEW_ARB_timer_query != 0 || GLEW_EXT_timer_query != 0 ) && ( glConfig.vendor != VENDOR_INTEL || r_skipIntelWorkarounds.GetBool() ) && glConfig.driverType != GLDRV_OPENGL_MESA; - +#if defined(__APPLE__) + // SRS - DSA not available in Apple OpenGL 4.1, but enable for OSX anyways since elapsed time query will be used to get timing info instead + glConfig.timerQueryAvailable = ( GLEW_ARB_timer_query != 0 || GLEW_EXT_timer_query != 0 ) && ( glConfig.vendor != VENDOR_INTEL || r_skipIntelWorkarounds.GetBool() ) && glConfig.driverType != GLDRV_OPENGL_MESA; +#else + // GL_ARB_timer_query using the DSA interface glConfig.timerQueryAvailable = ( GLEW_ARB_direct_state_access != 0 && GLEW_ARB_timer_query != 0 ); +#endif // GREMEDY_string_marker glConfig.gremedyStringMarkerAvailable = GLEW_GREMEDY_string_marker != 0; @@ -1534,6 +1550,23 @@ void idRenderBackend::CheckCVars() } } + // SRS - Enable SDL-driven vync changes without restart for UNIX-like OSs +#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) + extern idCVar r_swapInterval; + if( r_swapInterval.IsModified() ) + { + r_swapInterval.ClearModified(); +#if SDL_VERSION_ATLEAST(2, 0, 0) + if( SDL_GL_SetSwapInterval( r_swapInterval.GetInteger() ) < 0 ) + common->Warning( "Vsync changes not supported without restart" ); +#else + if( SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, r_swapInterval.GetInteger() ) < 0 ) + common->Warning( "Vsync changes not supported without restart" ); +#endif + } +#endif + // SRS end + if( r_antiAliasing.IsModified() ) { switch( r_antiAliasing.GetInteger() ) diff --git a/neo/renderer/OpenGL/RenderDebug_GL.cpp b/neo/renderer/OpenGL/RenderDebug_GL.cpp index d893e379..aff375d2 100644 --- a/neo/renderer/OpenGL/RenderDebug_GL.cpp +++ b/neo/renderer/OpenGL/RenderDebug_GL.cpp @@ -785,7 +785,7 @@ void idRenderBackend::DBG_ShowTris( drawSurf_t** drawSurfs, int numDrawSurfs ) if( r_showTris.GetInteger() == 3 ) { - GL_State( glStateBits & ~( GLS_CULL_MASK ) | GLS_CULL_TWOSIDED ); + GL_State( (glStateBits & ~( GLS_CULL_MASK )) | GLS_CULL_TWOSIDED ); // SRS - Added parens to silence build warnings } GL_Color( color ); @@ -794,7 +794,7 @@ void idRenderBackend::DBG_ShowTris( drawSurf_t** drawSurfs, int numDrawSurfs ) if( r_showTris.GetInteger() == 3 ) { - GL_State( glStateBits & ~( GLS_CULL_MASK ) | GLS_CULL_FRONTSIDED ); + GL_State( (glStateBits & ~( GLS_CULL_MASK )) | GLS_CULL_FRONTSIDED ); // SRS - Added parens to silence build warnings } } diff --git a/neo/renderer/OpenGL/RenderProgs_GL.cpp b/neo/renderer/OpenGL/RenderProgs_GL.cpp index 392c0493..c5ad4bdf 100644 --- a/neo/renderer/OpenGL/RenderProgs_GL.cpp +++ b/neo/renderer/OpenGL/RenderProgs_GL.cpp @@ -128,8 +128,14 @@ void idRenderProgManager::LoadShader( shader_t& shader ) default: { - outFileGLSL.Format( "renderprogs/glsl-4_50/%s%s", shader.name.c_str(), shader.nameOutSuffix.c_str() ); - outFileUniforms.Format( "renderprogs/glsl-4_50/%s%s", shader.name.c_str(), shader.nameOutSuffix.c_str() ); + //SRS - OSX supports only up to GLSL 4.1 + #if defined(__APPLE__) + outFileGLSL.Format( "renderprogs/glsl-4_10/%s%s", shader.name.c_str(), shader.nameOutSuffix.c_str() ); + outFileUniforms.Format( "renderprogs/glsl-4_10/%s%s", shader.name.c_str(), shader.nameOutSuffix.c_str() ); + #else + outFileGLSL.Format( "renderprogs/glsl-4_50/%s%s", shader.name.c_str(), shader.nameOutSuffix.c_str() ); + outFileUniforms.Format( "renderprogs/glsl-4_50/%s%s", shader.name.c_str(), shader.nameOutSuffix.c_str() ); + #endif } } diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 96f1f59b..c62aa33b 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -2050,7 +2050,7 @@ void idRenderBackend::RenderInteractions( const drawSurf_t* surfList, const view case SL_SPECULAR: { // ignore stage that fails the condition - if( !surfaceRegs[ surfaceStage->conditionRegister ] ) + if( !surfaceRegs[ surfaceStage->conditionRegister ] || vLight->lightDef->parms.noSpecular ) // SRS - From RB forums { break; } diff --git a/neo/renderer/RenderBackend.h b/neo/renderer/RenderBackend.h index 097c0a98..b40b4546 100644 --- a/neo/renderer/RenderBackend.h +++ b/neo/renderer/RenderBackend.h @@ -113,7 +113,8 @@ void RB_SetVertexColorParms( stageVertexColor_t svc ); #if defined( USE_VULKAN ) -#if defined(__linux__) +//SRS - Add OSX case +#if defined(__linux__) || defined(__APPLE__) #include #include #endif @@ -133,7 +134,8 @@ struct gpuInfo_t struct vulkanContext_t { // Eric: If on linux, use this to pass SDL_Window pointer to the SDL_Vulkan_* methods not in sdl_vkimp.cpp file. -#if defined(__linux__) + // SRS - Add OSX case +#if defined(__linux__) || defined(__APPLE__) SDL_Window* sdlWindow = nullptr; #endif uint64 frameCounter; diff --git a/neo/renderer/RenderCommon.h b/neo/renderer/RenderCommon.h index 31974653..a2381609 100644 --- a/neo/renderer/RenderCommon.h +++ b/neo/renderer/RenderCommon.h @@ -978,6 +978,9 @@ extern idCVar r_windowHeight; extern idCVar r_debugContext; // enable various levels of context debug extern idCVar r_glDriver; // "opengl32", etc +// SRS - Added cvar to control workarounds for AMD OSX driver bugs when shadow mapping enabled +extern idCVar r_skipAMDWorkarounds; // skip work arounds for AMD driver bugs +// SRS end extern idCVar r_skipIntelWorkarounds; // skip work arounds for Intel driver bugs extern idCVar r_vidMode; // video mode number extern idCVar r_displayRefresh; // optional display refresh rate option for vid mode @@ -1241,7 +1244,8 @@ struct glimpParms_t }; // Eric: If on Linux using Vulkan use the sdl_vkimp.cpp methods -#if defined(__linux__) && defined(USE_VULKAN) +// SRS - Add OSX case +#if ( defined(__linux__) || defined(__APPLE__) ) && defined(USE_VULKAN) #include #define CLAMP(x, lo, hi) ((x) < (lo) ? (lo) : (x) > (hi) ? (hi) : (x)) diff --git a/neo/renderer/RenderLog.cpp b/neo/renderer/RenderLog.cpp index 5f0376fb..3b96909d 100644 --- a/neo/renderer/RenderLog.cpp +++ b/neo/renderer/RenderLog.cpp @@ -617,17 +617,31 @@ void idRenderLog::OpenMainBlock( renderLogMainBlock_t block ) uint32 queryIndex = vkcontext.queryAssignedIndex[ vkcontext.frameParity ][ mainBlock * 2 + 0 ] = vkcontext.queryIndex[ vkcontext.frameParity ]++; vkCmdWriteTimestamp( commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, queryPool, queryIndex ); +// SRS - For OSX use elapsed time query for Apple OpenGL 4.1 using GL_TIME_ELAPSED vs GL_TIMESTAMP (which is not implemented on OSX) +#elif defined(__APPLE__) + + // SRS - OSX AMD drivers have a rendering bug (flashing colours) with an elasped time query when Shadow Mapping is on - turn off query for that case unless r_skipAMDWorkarounds is set + if( glConfig.timerQueryAvailable && ( !r_useShadowMapping.GetBool() || glConfig.vendor != VENDOR_AMD || r_skipAMDWorkarounds.GetBool() ) ) + { + if( glcontext.renderLogMainBlockTimeQueryIds[ glcontext.frameParity ][ mainBlock * 2 + 1 ] == 0 ) + { + glGenQueries( 1, &glcontext.renderLogMainBlockTimeQueryIds[ glcontext.frameParity ][ mainBlock * 2 + 1 ] ); + } + + glBeginQuery( GL_TIME_ELAPSED_EXT, glcontext.renderLogMainBlockTimeQueryIds[ glcontext.frameParity ][ mainBlock * 2 + 1 ] ); + } + #else if( glConfig.timerQueryAvailable ) { - if( glcontext.renderLogMainBlockTimeQueryIds[ glcontext.frameParity ][ block * 2 ] == 0 ) + if( glcontext.renderLogMainBlockTimeQueryIds[ glcontext.frameParity ][ mainBlock * 2 ] == 0 ) { - glCreateQueries( GL_TIMESTAMP, 2, &glcontext.renderLogMainBlockTimeQueryIds[ glcontext.frameParity ][ block * 2 ] ); + glCreateQueries( GL_TIMESTAMP, 2, &glcontext.renderLogMainBlockTimeQueryIds[ glcontext.frameParity ][ mainBlock * 2 ] ); } - glQueryCounter( glcontext.renderLogMainBlockTimeQueryIds[ glcontext.frameParity ][ block * 2 + 0 ], GL_TIMESTAMP ); - glcontext.renderLogMainBlockTimeQueryIssued[ glcontext.frameParity ][ block * 2 + 0 ]++; + glQueryCounter( glcontext.renderLogMainBlockTimeQueryIds[ glcontext.frameParity ][ mainBlock * 2 + 0 ], GL_TIMESTAMP ); + glcontext.renderLogMainBlockTimeQueryIssued[ glcontext.frameParity ][ mainBlock * 2 + 0 ]++; } #endif } @@ -651,7 +665,17 @@ void idRenderLog::CloseMainBlock() uint32 queryIndex = vkcontext.queryAssignedIndex[ vkcontext.frameParity ][ mainBlock * 2 + 1 ] = vkcontext.queryIndex[ vkcontext.frameParity ]++; vkCmdWriteTimestamp( commandBuffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, queryPool, queryIndex ); + +// SRS - For OSX use elapsed time query for Apple OpenGL 4.1 using GL_TIME_ELAPSED vs GL_TIMESTAMP (which is not implemented on OSX) +#elif defined(__APPLE__) + // SRS - OSX AMD drivers have a rendering bug (flashing colours) with an elasped time query when Shadow Mapping is on - turn off query for that case unless r_skipAMDWorkarounds is set + if( glConfig.timerQueryAvailable && ( !r_useShadowMapping.GetBool() || glConfig.vendor != VENDOR_AMD || r_skipAMDWorkarounds.GetBool() ) ) + { + glEndQuery( GL_TIME_ELAPSED_EXT ); + glcontext.renderLogMainBlockTimeQueryIssued[ glcontext.frameParity ][ mainBlock * 2 + 1 ]++; + } + #else if( glConfig.timerQueryAvailable ) diff --git a/neo/renderer/RenderProgs_GLSL.cpp b/neo/renderer/RenderProgs_GLSL.cpp index a86e773e..a3385a01 100644 --- a/neo/renderer/RenderProgs_GLSL.cpp +++ b/neo/renderer/RenderProgs_GLSL.cpp @@ -771,7 +771,12 @@ struct typeConversion_t const char* vertexInsert = { +// SRS - OSX OpenGL only supports up to GLSL 4.1, but current RenderProgs shaders seem to work as-is on OSX OpenGL drivers +#if defined(__APPLE__) && !defined(USE_VULKAN) + "#version 410\n" +#else "#version 450\n" +#endif "#pragma shader_stage( vertex )\n" "#extension GL_ARB_separate_shader_objects : enable\n" //"#define PC\n" @@ -786,7 +791,12 @@ const char* vertexInsert = const char* fragmentInsert = { - "#version 450\n" +// SRS - OSX OpenGL only supports up to GLSL 4.1, but current RenderProgs shaders seem to work as-is on OSX OpenGL drivers +#if defined(__APPLE__) && !defined(USE_VULKAN) + "#version 410\n" +#else + "#version 450\n" +#endif "#pragma shader_stage( fragment )\n" "#extension GL_ARB_separate_shader_objects : enable\n" //"#define PC\n" @@ -1502,7 +1512,7 @@ idStr idRenderProgManager::ConvertCG2GLSL( const idStr& in, const char* name, rp idStr filenameHint = "// filename " + idStr( name ) + "\n"; // RB: changed to allow multiple versions of GLSL - if( ( stage == SHADER_STAGE_VERTEX ) ) + if( stage == SHADER_STAGE_VERTEX ) // SRS - Remove extra parens { switch( glConfig.driverType ) { @@ -1551,7 +1561,7 @@ idStr idRenderProgManager::ConvertCG2GLSL( const idStr& in, const char* name, rp if( vkGLSL ) { out += "\n"; - if( ( stage == SHADER_STAGE_VERTEX ) ) + if( stage == SHADER_STAGE_VERTEX ) // SRS - Remove extra parens { out += "layout( binding = 0 ) uniform UBOV {\n"; } diff --git a/neo/renderer/RenderSystem.cpp b/neo/renderer/RenderSystem.cpp index 7fe87b4e..423645c3 100644 --- a/neo/renderer/RenderSystem.cpp +++ b/neo/renderer/RenderSystem.cpp @@ -130,7 +130,8 @@ void idRenderSystemLocal::RenderCommandBuffers( const emptyCommand_t* const cmdH // draw 2D graphics if( !r_skipBackEnd.GetBool() ) { -#if !defined(USE_VULKAN) +// SRS - For OSX skip total rendering time query due to missing GL_TIMESTAMP support in Apple OpenGL 4.1, will calculate it inside SwapCommandBuffers_FinishRendering instead +#if !defined(USE_VULKAN) && !defined(__APPLE__) if( glConfig.timerQueryAvailable ) { if( glcontext.renderLogMainBlockTimeQueryIds[ glcontext.frameParity ][ MRB_GPU_TIME ] == 0 ) @@ -741,6 +742,16 @@ void idRenderSystemLocal::SwapCommandBuffers_FinishRendering( backend.pc.gpuPostProcessingMicroSec = ( gpuEndNanoseconds - gpuStartNanoseconds ) / 1000; } + +// SRS - For OSX OpenGL calculate total rendering time vs direct measurement due to missing GL_TIMESTAMP support in Apple OpenGL 4.1 +#if defined(__APPLE__) + backend.pc.gpuMicroSec = backend.pc.gpuDepthMicroSec + backend.pc.gpuScreenSpaceAmbientOcclusionMicroSec + backend.pc.gpuAmbientPassMicroSec + backend.pc.gpuInteractionsMicroSec + backend.pc.gpuShaderPassMicroSec + backend.pc.gpuPostProcessingMicroSec + commonLocal.GetRendererIdleMicroseconds(); + + if( gpuMicroSec != NULL ) + { + *gpuMicroSec = backend.pc.gpuMicroSec; + } +#endif for( int i = 0; i < MRB_TOTAL_QUERIES; i++ ) { diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index a2124dee..e9210e93 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -56,7 +56,15 @@ glconfig_t glConfig; idCVar r_requestStereoPixelFormat( "r_requestStereoPixelFormat", "1", CVAR_RENDERER, "Ask for a stereo GL pixel format on startup" ); idCVar r_debugContext( "r_debugContext", "0", CVAR_RENDERER, "Enable various levels of context debug." ); idCVar r_glDriver( "r_glDriver", "", CVAR_RENDERER, "\"opengl32\", etc." ); +// SRS - Added workaround for AMD OSX driver bugs caused by GL_EXT_timer_query when shadow mapping enabled; Intel bugs not present on OSX +#if defined(__APPLE__) +idCVar r_skipIntelWorkarounds( "r_skipIntelWorkarounds", "1", CVAR_RENDERER | CVAR_BOOL, "skip workarounds for Intel driver bugs" ); +idCVar r_skipAMDWorkarounds( "r_skipAMDWorkarounds", "0", CVAR_RENDERER | CVAR_BOOL, "skip workarounds for AMD driver bugs" ); +#else idCVar r_skipIntelWorkarounds( "r_skipIntelWorkarounds", "0", CVAR_RENDERER | CVAR_BOOL, "skip workarounds for Intel driver bugs" ); +idCVar r_skipAMDWorkarounds( "r_skipAMDWorkarounds", "1", CVAR_RENDERER | CVAR_BOOL, "skip workarounds for AMD driver bugs" ); +#endif +// SRS end // RB: disabled 16x MSAA idCVar r_antiAliasing( "r_antiAliasing", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, " 0 = None\n 1 = SMAA 1x\n 2 = MSAA 2x\n 3 = MSAA 4x\n 4 = MSAA 8x\n", 0, ANTI_ALIASING_MSAA_8X ); // RB end @@ -90,7 +98,8 @@ idCVar r_useSRGB( "r_useSRGB", "0", CVAR_RENDERER | CVAR_INTEGER | CVAR_ARCHIVE, idCVar r_maxAnisotropicFiltering( "r_maxAnisotropicFiltering", "8", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "limit aniso filtering" ); idCVar r_useTrilinearFiltering( "r_useTrilinearFiltering", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "Extra quality filtering" ); // RB: not used anymore -idCVar r_lodBias( "r_lodBias", "0.5", CVAR_RENDERER | CVAR_ARCHIVE, "UNUSED: image lod bias" ); +// SRS - Reenabled LODBIAS +idCVar r_lodBias( "r_lodBias", "0.5", CVAR_RENDERER | CVAR_ARCHIVE, /*"UNUSED: */"image lod bias" ); // RB end idCVar r_useStateCaching( "r_useStateCaching", "1", CVAR_RENDERER | CVAR_BOOL, "avoid redundant state changes in GL_*() calls" ); @@ -428,7 +437,8 @@ void R_SetNewMode( const bool fullInit ) if( fullInit ) { // create the context as well as setting up the window -#if defined(__linux__) && defined(USE_VULKAN) +// SRS - Add OSX case +#if ( defined(__linux__) || defined(__APPLE__) ) && defined(USE_VULKAN) if( VKimp_Init( parms ) ) #else if( GLimp_Init( parms ) ) @@ -445,7 +455,8 @@ void R_SetNewMode( const bool fullInit ) else { // just rebuild the window -#if defined(__linux__) && defined(USE_VULKAN) +// SRS - Add OSX case +#if ( defined(__linux__) || defined(__APPLE__) ) && defined(USE_VULKAN) if( VKimp_SetScreenParms( parms ) ) #else if( GLimp_SetScreenParms( parms ) ) @@ -1399,7 +1410,8 @@ void R_SetColorMappings() int inf = idMath::Ftoi( 0xffff * pow( j / 255.0f, invg ) + 0.5f ); tr.gammaTable[i] = idMath::ClampInt( 0, 0xFFFF, inf ); } -#if defined(__linux__) && defined(USE_VULKAN) +// SRS - Add OSX case +#if ( defined(__linux__) || defined(__APPLE__) ) && defined(USE_VULKAN) VKimp_SetGamma( tr.gammaTable, tr.gammaTable, tr.gammaTable ); #else GLimp_SetGamma( tr.gammaTable, tr.gammaTable, tr.gammaTable ); @@ -2105,6 +2117,9 @@ void idRenderSystemLocal::Shutdown() R_ShutdownFrameData(); UnbindBufferObjects(); + + // SRS - wait for fence to hit before freeing any resources the GPU may be using, otherwise get Vulkan validation layer errors on shutdown + backend.GL_BlockingSwapBuffers(); // free the vertex cache, which should have nothing allocated now vertexCache.Shutdown(); diff --git a/neo/renderer/VertexCache.cpp b/neo/renderer/VertexCache.cpp index 8d5f19da..8c9ed98c 100644 --- a/neo/renderer/VertexCache.cpp +++ b/neo/renderer/VertexCache.cpp @@ -156,6 +156,11 @@ void idVertexCache::Shutdown() frameData[i].indexBuffer.FreeBufferObject(); frameData[i].jointBuffer.FreeBufferObject(); } + + // SRS - free static buffers to avoid Vulkan validation layer errors on shutdown + staticData.vertexBuffer.FreeBufferObject(); + staticData.indexBuffer.FreeBufferObject(); + staticData.jointBuffer.FreeBufferObject(); } /* diff --git a/neo/renderer/Vulkan/Allocator_VK.cpp b/neo/renderer/Vulkan/Allocator_VK.cpp index e5f192b8..950969eb 100644 --- a/neo/renderer/Vulkan/Allocator_VK.cpp +++ b/neo/renderer/Vulkan/Allocator_VK.cpp @@ -167,7 +167,8 @@ idVulkanBlock::Init */ bool idVulkanBlock::Init() { - if( memoryTypeIndex == UINT64_MAX ) + //SRS - Changed UINT64_MAX to UINT32_MAX for type consistency, otherwise test is always false + if( memoryTypeIndex == UINT32_MAX ) { return false; } @@ -495,8 +496,9 @@ void idVulkanBlock::Print() idLib::Printf( "Type Index: %u\n", memoryTypeIndex ); idLib::Printf( "Usage: %s\n", memoryUsageStrings[ usage ] ); idLib::Printf( "Count: %d\n", count ); - idLib::Printf( "Size: %lu\n", size ); - idLib::Printf( "Allocated: %lu\n", allocated ); + //SRS - Changed %lu to %llu + idLib::Printf( "Size: %llu\n", size ); + idLib::Printf( "Allocated: %llu\n", allocated ); idLib::Printf( "Next Block: %u\n", nextBlockId ); idLib::Printf( "------------------------\n" ); @@ -505,8 +507,9 @@ void idVulkanBlock::Print() idLib::Printf( "{\n" ); idLib::Printf( "\tId: %u\n", current->id ); - idLib::Printf( "\tSize: %lu\n", current->size ); - idLib::Printf( "\tOffset: %lu\n", current->offset ); + //SRS - Changed %lu to %llu + idLib::Printf( "\tSize: %llu\n", current->size ); + idLib::Printf( "\tOffset: %llu\n", current->offset ); idLib::Printf( "\tType: %s\n", allocationTypeStrings[ current->type ] ); idLib::Printf( "}\n" ); @@ -679,7 +682,8 @@ void idVulkanAllocator::Print() { idLib::Printf( "Device Local MB: %d\n", int( deviceLocalMemoryBytes / 1024 * 1024 ) ); idLib::Printf( "Host Visible MB: %d\n", int( hostVisibleMemoryBytes / 1024 * 1024 ) ); - idLib::Printf( "Buffer Granularity: %lu\n", bufferImageGranularity ); + //SRS - Changed %lu to %llu + idLib::Printf( "Buffer Granularity: %llu\n", bufferImageGranularity ); idLib::Printf( "\n" ); for( int i = 0; i < VK_MAX_MEMORY_TYPES; ++i ) @@ -702,7 +706,8 @@ CONSOLE_COMMAND( Vulkan_PrintHeapInfo, "Print out the heap information for this for( uint32 i = 0; i < props.memoryHeapCount; ++i ) { VkMemoryHeap heap = props.memoryHeaps[ i ]; - idLib::Printf( "id=%d, size=%lu, flags=", i, heap.size ); + //SRS - Changed %lu to %llu + idLib::Printf( "id=%d, size=%llu, flags=", i, heap.size ); if( heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT ) { idLib::Printf( "DEVICE_LOCAL" ); diff --git a/neo/renderer/Vulkan/BufferObject_VK.cpp b/neo/renderer/Vulkan/BufferObject_VK.cpp index 3b6eff8c..25733662 100644 --- a/neo/renderer/Vulkan/BufferObject_VK.cpp +++ b/neo/renderer/Vulkan/BufferObject_VK.cpp @@ -105,8 +105,14 @@ bool idVertexBuffer::AllocBufferObject( const void* data, int allocSize, bufferU } else if( usage == BU_DYNAMIC ) { + // SRS - needed to ensure host coherency for MoltenVK on OSX < 10.15.6, otherwise black screen +#if defined(__APPLE__) + vmaReq.usage = VMA_MEMORY_USAGE_UNKNOWN; + vmaReq.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; +#else vmaReq.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; - vmaReq.flags = VMA_MEMORY_REQUIREMENT_PERSISTENT_MAP_BIT; +#endif + vmaReq.flags = VMA_MEMORY_REQUIREMENT_PERSISTENT_MAP_BIT; } ID_VK_CHECK( vmaCreateBuffer( vmaAllocator, &bufferCreateInfo, &vmaReq, &apiObject, &vmaAllocation, &allocation ) ); @@ -357,7 +363,13 @@ bool idIndexBuffer::AllocBufferObject( const void* data, int allocSize, bufferUs } else if( usage == BU_DYNAMIC ) { - vmaReq.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; + // SRS - needed to ensure host coherency for MoltenVK on OSX < 10.15.6, otherwise black screen +#if defined(__APPLE__) + vmaReq.usage = VMA_MEMORY_USAGE_UNKNOWN; + vmaReq.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; +#else + vmaReq.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; +#endif vmaReq.flags = VMA_MEMORY_REQUIREMENT_PERSISTENT_MAP_BIT; } @@ -610,8 +622,14 @@ bool idUniformBuffer::AllocBufferObject( const void* data, int allocSize, buffer } else if( usage == BU_DYNAMIC ) { - vmaReq.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; - vmaReq.flags = VMA_MEMORY_REQUIREMENT_PERSISTENT_MAP_BIT; + // SRS - needed to ensure host coherency for MoltenVK on OSX < 10.15.6, otherwise black screen +#if defined(__APPLE__) + vmaReq.usage = VMA_MEMORY_USAGE_UNKNOWN; + vmaReq.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; +#else + vmaReq.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; +#endif + vmaReq.flags = VMA_MEMORY_REQUIREMENT_PERSISTENT_MAP_BIT; } ID_VK_CHECK( vmaCreateBuffer( vmaAllocator, &bufferCreateInfo, &vmaReq, &apiObject, &vmaAllocation, &allocation ) ); @@ -803,4 +821,4 @@ void idUniformBuffer::ClearWithoutFreeing() #else allocation.deviceMemory = VK_NULL_HANDLE; #endif -} \ No newline at end of file +} diff --git a/neo/renderer/Vulkan/Image_VK.cpp b/neo/renderer/Vulkan/Image_VK.cpp index 2ec73d1f..8fff25f7 100644 --- a/neo/renderer/Vulkan/Image_VK.cpp +++ b/neo/renderer/Vulkan/Image_VK.cpp @@ -657,13 +657,18 @@ void idImage::SubImageUpload( int mipLevel, int x, int y, int z, int width, int { assert( x >= 0 && y >= 0 && mipLevel >= 0 && width >= 0 && height >= 0 && mipLevel < opts.numLevels ); + // SRS - Calculate buffer size without changing original width and height dimensions for compressed images + int bufferW = width; + int bufferH = height; + if( IsCompressed() ) { - width = ( width + 3 ) & ~3; - height = ( height + 3 ) & ~3; + bufferW = ( width + 3 ) & ~3; + bufferH = ( height + 3 ) & ~3; } - int size = width * height * BitsForFormat( opts.format ) / 8; + int size = bufferW * bufferH * BitsForFormat( opts.format ) / 8; + // SRS end VkBuffer buffer; VkCommandBuffer commandBuffer; @@ -722,7 +727,7 @@ void idImage::SubImageUpload( int mipLevel, int x, int y, int z, int width, int VkBufferImageCopy imgCopy = {}; imgCopy.bufferOffset = offset; imgCopy.bufferRowLength = pixelPitch; - imgCopy.bufferImageHeight = height; + imgCopy.bufferImageHeight = bufferH; // SRS - Use buffer height vs. image height to avoid vulkan errors for compressed images imgCopy.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; imgCopy.imageSubresource.layerCount = 1; imgCopy.imageSubresource.mipLevel = mipLevel; @@ -730,7 +735,7 @@ void idImage::SubImageUpload( int mipLevel, int x, int y, int z, int width, int imgCopy.imageOffset.x = x; imgCopy.imageOffset.y = y; imgCopy.imageOffset.z = 0; - imgCopy.imageExtent.width = width; + imgCopy.imageExtent.width = width; // SRS - Always use original width and height dimensions, even when image is compressed imgCopy.imageExtent.height = height; imgCopy.imageExtent.depth = 1; @@ -760,4 +765,128 @@ void idImage::SubImageUpload( int mipLevel, int x, int y, int z, int width, int vkCmdPipelineBarrier( commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, 0, NULL, 0, NULL, 1, &barrier ); layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; -} \ No newline at end of file +} + +// SRS - added method to set image layout +/* +==================== +idImage::SetImageLayout +==================== +*/ +void idImage::SetImageLayout( VkImage image, VkImageSubresourceRange subresourceRange, VkImageLayout oldImageLayout, VkImageLayout newImageLayout ) +{ + + VkBuffer buffer; + VkCommandBuffer commandBuffer; + int size = 0; + int offset = 0; + byte* data = stagingManager.Stage( size, 16, commandBuffer, buffer, offset ); + + VkImageMemoryBarrier barrier = {}; + barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; + barrier.image = image; + barrier.subresourceRange = subresourceRange; + barrier.oldLayout = oldImageLayout; + barrier.newLayout = newImageLayout; + + // Source layouts (old) + // Source access mask controls actions that have to be finished on the old layout before it will be transitioned to the new layout + switch ( oldImageLayout ) + { + case VK_IMAGE_LAYOUT_UNDEFINED: + // Image layout is undefined (or does not matter) + // Only valid as initial layout + // No flags required, listed only for completeness + barrier.srcAccessMask = 0; + break; + + case VK_IMAGE_LAYOUT_PREINITIALIZED: + // Image is preinitialized + // Only valid as initial layout for linear images, preserves memory contents + // Make sure host writes have been finished + barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; + break; + + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + // Image is a color attachment + // Make sure any writes to the color buffer have been finished + barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + break; + + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + // Image is a depth/stencil attachment + // Make sure any writes to the depth/stencil buffer have been finished + barrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + break; + + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + // Image is a transfer source + // Make sure any reads from the image have been finished + barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + break; + + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + // Image is a transfer destination + // Make sure any writes to the image have been finished + barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + break; + + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + // Image is read by a shader + // Make sure any shader reads from the image have been finished + barrier.srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + break; + + default: + // Other source layouts aren't handled (yet) + break; + } + + // Target layouts (new) + // Destination access mask controls the dependency for the new image layout + switch ( newImageLayout ) + { + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + // Image will be used as a transfer destination + // Make sure any writes to the image have been finished + barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + break; + + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + // Image will be used as a transfer source + // Make sure any reads from the image have been finished + barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + break; + + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + // Image will be used as a color attachment + // Make sure any writes to the color buffer have been finished + barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + break; + + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + // Image layout will be used as a depth/stencil attachment + // Make sure any writes to depth/stencil buffer have been finished + barrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + break; + + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + // Image will be read in a shader (sampler, input attachment) + // Make sure any writes to the image have been finished + if ( barrier.srcAccessMask == 0 ) + { + barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; + } + barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + break; + + default: + // Other destination layouts aren't handled (yet) + break; + } + + vkCmdPipelineBarrier( commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, 0, 0, NULL, 0, NULL, 1, &barrier ); +} +// SRS End diff --git a/neo/renderer/Vulkan/RenderBackend_VK.cpp b/neo/renderer/Vulkan/RenderBackend_VK.cpp index 9833cab8..f9f39ccf 100644 --- a/neo/renderer/Vulkan/RenderBackend_VK.cpp +++ b/neo/renderer/Vulkan/RenderBackend_VK.cpp @@ -74,6 +74,16 @@ static const char* g_instanceExtensions[ g_numInstanceExtensions ] = }; #endif +// SRS - needed for MoltenVK portability implementation on OSX +#if defined(__APPLE__) +// required for VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME visibility (as of SDK 1.2.170.0) +#include +#if defined(USE_MoltenVK) +// optionally needed for runtime access to fullImageViewSwizzle (instead of env var MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE = 1) +#include +#endif +#endif + static const int g_numDebugInstanceExtensions = 1; static const char* g_debugInstanceExtensions[ g_numDebugInstanceExtensions ] = { @@ -83,7 +93,12 @@ static const char* g_debugInstanceExtensions[ g_numDebugInstanceExtensions ] = static const int g_numValidationLayers = 1; static const char* g_validationLayers[ g_numValidationLayers ] = { +// SRS - use MoltenVK validation layer on macOS when using libMoltenVK in place of libvulkan +#if defined(__APPLE__) && defined(USE_MoltenVK) + "MoltenVK" +#else "VK_LAYER_KHRONOS_validation" +#endif }; #define ID_VK_ERROR_STRING( x ) case static_cast< int >( x ): return #x @@ -288,7 +303,8 @@ static void CreateVulkanInstance() ValidateValidationLayers(); } -#if defined(__linux__) + // SRS - Add OSX case +#if defined(__linux__) || defined(__APPLE__) auto extensions = get_required_extensions( sdlInstanceExtensions, enableLayers ); createInfo.enabledExtensionCount = static_cast( extensions.size() ); createInfo.ppEnabledExtensionNames = extensions.data(); @@ -442,7 +458,8 @@ static void CreateSurface() ID_VK_CHECK( vkCreateWaylandSurfaceKHR( info.inst, &createInfo, NULL, &info.surface ) ); #else -#if defined(__linux__) + // SRS - Add OSX case +#if defined(__linux__) || defined(__APPLE__) if( !SDL_Vulkan_CreateSurface( vkcontext.sdlWindow, vkcontext.instance, &vkcontext.surface ) ) { idLib::FatalError( "Error while creating Vulkan surface: %s", SDL_GetError() ); @@ -506,6 +523,15 @@ static void PopulateDeviceExtensions( const idList< VkExtensionProperties >& ext { //idLib::Printf( "Checking Vulkan device extension [%s]\n", extensionProps[ i ].extensionName ); + // SRS - needed for MoltenVK portability implementation on OSX +#if defined(__APPLE__) + if( idStr::Icmp( extensionProps[ i ].extensionName, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME ) == 0 ) + { + extensions.AddUnique( VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME ); + continue; + } +#endif + if( idStr::Icmp( extensionProps[ i ].extensionName, VK_EXT_DEBUG_MARKER_EXTENSION_NAME ) == 0 && enableLayers ) { extensions.AddUnique( VK_EXT_DEBUG_MARKER_EXTENSION_NAME ); @@ -711,6 +737,17 @@ static void CreateLogicalDeviceAndQueues() devqInfo.Append( qinfo ); } + // SRS - needed for MoltenVK portability implementation on OSX +#if defined(__APPLE__) + VkPhysicalDeviceFeatures2 deviceFeatures2 = {}; + VkPhysicalDevicePortabilitySubsetFeaturesKHR portabilityFeatures = {}; + + deviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; + deviceFeatures2.pNext = &portabilityFeatures; + portabilityFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR; + + vkGetPhysicalDeviceFeatures2( vkcontext.physicalDevice, &deviceFeatures2 ); +#else VkPhysicalDeviceFeatures deviceFeatures = {}; deviceFeatures.textureCompressionBC = VK_TRUE; deviceFeatures.imageCubeArray = VK_TRUE; @@ -719,12 +756,18 @@ static void CreateLogicalDeviceAndQueues() deviceFeatures.depthBounds = vkcontext.physicalDeviceFeatures.depthBounds; deviceFeatures.fillModeNonSolid = VK_TRUE; deviceFeatures.samplerAnisotropy = vkcontext.physicalDeviceFeatures.samplerAnisotropy; // RB +#endif VkDeviceCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + // SRS - needed for MoltenVK portability implementation on OSX +#if defined(__APPLE__) + info.pNext = &deviceFeatures2; +#else + info.pEnabledFeatures = &deviceFeatures; +#endif info.queueCreateInfoCount = devqInfo.Num(); info.pQueueCreateInfos = devqInfo.Ptr(); - info.pEnabledFeatures = &deviceFeatures; info.enabledExtensionCount = vkcontext.deviceExtensions.Num(); info.ppEnabledExtensionNames = vkcontext.deviceExtensions.Ptr(); @@ -843,7 +886,8 @@ static VkExtent2D ChooseSurfaceExtent( VkSurfaceCapabilitiesKHR& caps ) int width = glConfig.nativeScreenWidth; int height = glConfig.nativeScreenHeight; -#if defined(__linux__) + // SRS - Add OSX case +#if defined(__linux__) || defined(__APPLE__) SDL_Vulkan_GetDrawableSize( vkcontext.sdlWindow, &width, &height ); width = idMath::ClampInt( caps.minImageExtent.width, caps.maxImageExtent.width, width ); @@ -1110,6 +1154,14 @@ static void CreateRenderTargets() { vkcontext.sampleCount = VK_SAMPLE_COUNT_2_BIT; } + +#if defined(__APPLE__) + // SRS - Disable MSAA for OSX since shaderStorageImageMultisample is disabled on MoltenVK for now + if( samples >= 2 ) + { + vkcontext.sampleCount = VK_SAMPLE_COUNT_1_BIT; + } +#endif // Select Depth Format { @@ -1127,7 +1179,8 @@ static void CreateRenderTargets() depthOptions.format = FMT_DEPTH; // Eric: See if this fixes resizing -#if defined(__linux__) + // SRS - Add OSX case +#if defined(__linux__) || defined(__APPLE__) gpuInfo_t& gpu = *vkcontext.gpu; VkExtent2D extent = ChooseSurfaceExtent( gpu.surfaceCaps ); @@ -1247,7 +1300,8 @@ static void CreateRenderPass() depthAttachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; // RB - //depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + // SRS - reenable, otherwise get Vulkan validation layer warnings + depthAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; depthAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; depthAttachment.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; @@ -1453,7 +1507,8 @@ void idRenderBackend::Init() // DG: make sure SDL has setup video so getting supported modes in R_SetNewMode() works -#if defined(__linux__) && defined(USE_VULKAN) + // SRS - Add OSX case +#if ( defined(__linux__) || defined(__APPLE__) ) && defined(USE_VULKAN) VKimp_PreInit(); #else GLimp_PreInit(); @@ -1474,6 +1529,16 @@ void idRenderBackend::Init() idLib::Printf( "Creating Vulkan Instance...\n" ); CreateVulkanInstance(); + // SRS - On macOS optionally set fullImageViewSwizzle to TRUE (instead of env var MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE = 1) +#if defined(__APPLE__) && defined(USE_MoltenVK) + MVKConfiguration pConfig; + size_t pConfigSize = sizeof( pConfig ); + + vkGetMoltenVKConfigurationMVK( vkcontext.instance, &pConfig, &pConfigSize ); + pConfig.fullImageViewSwizzle = VK_TRUE; + vkSetMoltenVKConfigurationMVK( vkcontext.instance, &pConfig, &pConfigSize ); +#endif + // create the windowing interface //#ifdef _WIN32 CreateSurface(); @@ -1638,7 +1703,8 @@ void idRenderBackend::Shutdown() ClearContext(); // destroy main window -#if defined(__linux__) && defined(USE_VULKAN) + // SRS - Add OSX case +#if ( defined(__linux__) || defined(__APPLE__) ) && defined(USE_VULKAN) VKimp_Shutdown(); #else GLimp_Shutdown(); diff --git a/neo/renderer/Vulkan/Staging_VK.cpp b/neo/renderer/Vulkan/Staging_VK.cpp index 1ac81b95..6be64681 100644 --- a/neo/renderer/Vulkan/Staging_VK.cpp +++ b/neo/renderer/Vulkan/Staging_VK.cpp @@ -146,7 +146,9 @@ idVulkanStagingManager::Shutdown */ void idVulkanStagingManager::Shutdown() { - vkUnmapMemory( vkcontext.device, memory ); + // SRS - use vkFreeMemory (with implicit unmap) vs. vkUnmapMemory to avoid validation layer errors on shutdown + //vkUnmapMemory( vkcontext.device, memory ); + vkFreeMemory( vkcontext.device, memory, NULL ); memory = VK_NULL_HANDLE; mappedData = NULL; @@ -160,6 +162,10 @@ void idVulkanStagingManager::Shutdown() maxBufferSize = 0; currentBuffer = 0; + + // SRS - destroy command pool to avoid validation layer errors on shutdown + vkDestroyCommandPool( vkcontext.device, commandPool, NULL ); + commandPool = VK_NULL_HANDLE; } /* diff --git a/neo/renderer/Vulkan/vma.h b/neo/renderer/Vulkan/vma.h index 53adffba..506b78e3 100644 --- a/neo/renderer/Vulkan/vma.h +++ b/neo/renderer/Vulkan/vma.h @@ -768,7 +768,27 @@ remove them if not needed. #include // for std::mutex #include -#if !defined(_WIN32) +//SRS - Modified from vkQuake2, to compile with C++11 on OSX versions with no aligned_alloc +#if defined(__APPLE__) +#if !defined(MAC_OS_X_VERSION_10_16) && defined(__cplusplus) && __cplusplus < 201703L +// For C++14, usr/include/malloc/_malloc.h declares aligned_alloc() only with +// the MacOSX11.0 SDK in Xcode 12 (which is what adds MAC_OS_X_VERSION_10_16). +// For C++17 aligned_alloc is available with the 10.15 SDK already. +void* aligned_alloc( size_t alignment, size_t size ) +{ + // alignment must be >= sizeof(void*) + if(alignment < sizeof(void*)) + { + alignment = sizeof(void*); + } + + void *pointer; + if(posix_memalign(&pointer, alignment, size) == 0) + return pointer; + return NULL; +} +#endif +#elif !defined(_WIN32) #include // for aligned_alloc() #endif @@ -3468,7 +3488,8 @@ void VmaBlock::PrintDetailedMap( class VmaStringBuilder& sb ) const sb.Add( ",\n\t\t\t\"FreeBytes\": " ); sb.AddNumber( m_SumFreeSize ); sb.Add( ",\n\t\t\t\"Suballocations\": " ); - sb.AddNumber( m_Suballocations.size() ); + //SRS - cast to uint32_t to avoid type ambiguity + sb.AddNumber( ( uint32_t )m_Suballocations.size() ); sb.Add( ",\n\t\t\t\"FreeSuballocations\": " ); sb.AddNumber( m_FreeCount ); sb.Add( ",\n\t\t\t\"SuballocationList\": [" ); @@ -4933,7 +4954,8 @@ void VmaAllocator_T::PrintDetailedMap( VmaStringBuilder& sb ) sb.Add( ",\n\"OwnAllocations\": {\n\t\"Type " ); ownAllocationsStarted = true; } - sb.AddNumber( memTypeIndex ); + //SRS - cast to uint32_t to avoid type ambiguity, memTypeIndex is an unsigned int + sb.AddNumber( ( uint32_t )memTypeIndex ); if( blockVectorType == VMA_BLOCK_VECTOR_TYPE_MAPPED ) { sb.Add( " Mapped" ); @@ -4984,7 +5006,8 @@ void VmaAllocator_T::PrintDetailedMap( VmaStringBuilder& sb ) sb.Add( ",\n\"Allocations\": {\n\t\"Type " ); allocationsStarted = true; } - sb.AddNumber( memTypeIndex ); + //SRS - cast to uint32_t to avoid type ambiguity, memTypeIndex is an unsigned int + sb.AddNumber( ( uint32_t )memTypeIndex ); if( blockVectorType == VMA_BLOCK_VECTOR_TYPE_MAPPED ) { sb.Add( " Mapped" ); diff --git a/neo/swf/SWF_Bitstream.cpp b/neo/swf/SWF_Bitstream.cpp index f8b5cbe7..56459c32 100644 --- a/neo/swf/SWF_Bitstream.cpp +++ b/neo/swf/SWF_Bitstream.cpp @@ -39,7 +39,7 @@ int maskForNumBits[33] = { NBM( 0x00 ), NBM( 0x01 ), NBM( 0x02 ), NBM( 0x03 ), NBM( 0x1C ), NBM( 0x1D ), NBM( 0x1E ), NBM( 0x1F ), -1 }; -#define NBS( x ) (int32)( (-1) << ( x - 1 ) ) +#define NBS( x ) (int32)( (unsigned long)(-1L) << ( x - 1 ) ) // SRS - Cast to unsigned long int signForNumBits[33] = { NBS( 0x01 ), NBS( 0x01 ), NBS( 0x02 ), NBS( 0x03 ), NBS( 0x04 ), NBS( 0x05 ), NBS( 0x06 ), NBS( 0x07 ), NBS( 0x08 ), NBS( 0x09 ), NBS( 0x0A ), NBS( 0x0B ), diff --git a/neo/sys/posix/platform_osx.cpp b/neo/sys/posix/platform_osx.cpp index 726a46d7..00c49ebd 100644 --- a/neo/sys/posix/platform_osx.cpp +++ b/neo/sys/posix/platform_osx.cpp @@ -396,8 +396,8 @@ void Sys_ReLaunch() // DG end } -// OS X doesn't have clock_gettime() -int clock_gettime( clk_id_t clock, struct timespec* tp ) +// OS X 10.11 or earlier doesn't have native clock_gettime() +int clock_gettime( /*clk_id_t*/ clockid_t clock, struct timespec* tp ) // SRS - use APPLE clockid_t { switch( clock ) { diff --git a/neo/sys/posix/posix_main.cpp b/neo/sys/posix/posix_main.cpp index 81c5c528..4d55bdbe 100644 --- a/neo/sys/posix/posix_main.cpp +++ b/neo/sys/posix/posix_main.cpp @@ -410,6 +410,7 @@ Sys_DefaultBasePath Get the default base path - binary image path +- MacOS app bundle resources directory path // SRS - Added MacOS app bundle resources path - current directory - hardcoded Try to be intelligent: if there is no BASE_GAMEDIR, try the next path @@ -434,6 +435,20 @@ const char* Sys_DefaultBasePath() { common->Printf( "no '%s' directory in exe path %s, skipping\n", BASE_GAMEDIR, basepath.c_str() ); } + #if defined(__APPLE__) // SRS - - Added check for MacOS app bundle resources path + basepath += "/../Resources"; + testbase = basepath; + testbase += "/"; + testbase += BASE_GAMEDIR; + if( stat( testbase.c_str(), &st ) != -1 && S_ISDIR( st.st_mode ) ) + { + return basepath.c_str(); + } + else + { + common->Printf( "no '%s' directory in MacOS app bundle resources path %s, skipping\n", BASE_GAMEDIR, basepath.c_str() ); + } + #endif } if( basepath != Posix_Cwd() ) { diff --git a/neo/sys/posix/posix_public.h b/neo/sys/posix/posix_public.h index 772bf011..7c7ba169 100644 --- a/neo/sys/posix/posix_public.h +++ b/neo/sys/posix/posix_public.h @@ -68,8 +68,10 @@ char* Posix_ConsoleInput(); double MeasureClockTicks(); #ifdef __APPLE__ -enum clk_id_t { CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_MONOTONIC_RAW }; -int clock_gettime( clk_id_t clock, struct timespec* tp ); +#if !defined(CLOCK_REALTIME) // SRS - define clockid_t enum for OSX 10.11 and earlier +enum /*clk_id_t*/ clockid_t { CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_MONOTONIC_RAW }; +#endif +int clock_gettime( /*clk_id_t*/ clockid_t clock, struct timespec* tp ); // SRS - use APPLE clockid_t #endif // Eric: Not used on Linux since using SDL2 diff --git a/neo/sys/sdl/sdl_events.cpp b/neo/sys/sdl/sdl_events.cpp index 9225a76d..c5f4e25b 100644 --- a/neo/sys/sdl/sdl_events.cpp +++ b/neo/sys/sdl/sdl_events.cpp @@ -852,7 +852,8 @@ void Sys_GrabMouseCursor( bool grabIt ) { flags = GRAB_SETSTATE; } -#if defined(__linux__) && defined(USE_VULKAN) +// SRS - Add OSX case +#if ( defined(__linux__) || defined(__APPLE__) ) && defined(USE_VULKAN) VKimp_GrabInput( flags ); #else GLimp_GrabInput( flags ); diff --git a/neo/sys/sdl/sdl_local.h b/neo/sys/sdl/sdl_local.h index ae937526..594f8157 100644 --- a/neo/sys/sdl/sdl_local.h +++ b/neo/sys/sdl/sdl_local.h @@ -35,7 +35,8 @@ const int GRAB_REENABLE = ( 1 << 1 ); const int GRAB_HIDECURSOR = ( 1 << 2 ); const int GRAB_SETSTATE = ( 1 << 3 ); -#if defined(__linux__) && defined(USE_VULKAN) +// SRS - Add OSX case +#if ( defined(__linux__) || defined(__APPLE__) ) && defined(USE_VULKAN) void VKimp_GrabInput( int flags ); #else void GLimp_GrabInput( int flags ); diff --git a/neo/sys/sdl/sdl_vkimp.cpp b/neo/sys/sdl/sdl_vkimp.cpp index 11802f50..1d235b5a 100644 --- a/neo/sys/sdl/sdl_vkimp.cpp +++ b/neo/sys/sdl/sdl_vkimp.cpp @@ -41,6 +41,10 @@ If you have questions concerning this license or the applicable additional terms #include #include #include +// SRS - optinally needed for VK_MVK_MOLTENVK_EXTENSION_NAME visibility +#if defined(__APPLE__) && defined(USE_MoltenVK) +#include +#endif #include #include "renderer/RenderCommon.h" @@ -90,6 +94,14 @@ std::vector get_required_extensions( const std::vector } } + // SRS - needed for MoltenVK portability implementation and optionally for MoltenVK configuration on OSX +#if defined(__APPLE__) + sdlInstanceExtensions.push_back( VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME ); +#if defined(USE_MoltenVK) + sdlInstanceExtensions.push_back( VK_MVK_MOLTENVK_EXTENSION_NAME ); +#endif +#endif + if( enableValidationLayers ) { sdlInstanceExtensions.push_back( "VK_EXT_debug_report" ); @@ -305,11 +317,11 @@ bool VKimp_Init( glimpParms_t parms ) common->Printf( "No usable VK mode found: %s", SDL_GetError() ); return false; } - +/* SRS - This must be leftover code from OpenGL, disable it #ifdef __APPLE__ glewExperimental = GL_TRUE; #endif - +*/ // DG: disable cursor, we have two cursors in menu (because mouse isn't grabbed in menu) SDL_ShowCursor( SDL_DISABLE ); // DG end diff --git a/neo/sys/sys_lobby.h b/neo/sys/sys_lobby.h index 1dbde0ef..dedf7463 100644 --- a/neo/sys/sys_lobby.h +++ b/neo/sys/sys_lobby.h @@ -947,6 +947,8 @@ idSessionCallbacks class idSessionCallbacks { public: + virtual ~idSessionCallbacks() {} // SRS - Added virtual destructor + virtual idLobby& GetPartyLobby() = 0; virtual idLobby& GetGameLobby() = 0; virtual idLobby& GetActingGameStateLobby() = 0; diff --git a/neo/sys/sys_lobby_backend.h b/neo/sys/sys_lobby_backend.h index 2cfb77ff..b7b29f49 100644 --- a/neo/sys/sys_lobby_backend.h +++ b/neo/sys/sys_lobby_backend.h @@ -236,6 +236,8 @@ public: idLobbyBackend() : type( TYPE_INVALID ), isLocal( false ), isHost( false ) {} idLobbyBackend( lobbyBackendType_t lobbyType ) : type( lobbyType ), isLocal( false ), isHost( false ) {} + virtual ~idLobbyBackend() {} // SRS - Added virtual destructor + virtual void StartHosting( const idMatchParameters& p, float skillLevel, lobbyBackendType_t type ) = 0; virtual void StartFinding( const idMatchParameters& p, int numPartyUsers, float skillLevel ) = 0; virtual void JoinFromConnectInfo( const lobbyConnectInfo_t& connectInfo ) = 0; diff --git a/neo/sys/sys_savegame.cpp b/neo/sys/sys_savegame.cpp index a7f8bc15..6812ed61 100644 --- a/neo/sys/sys_savegame.cpp +++ b/neo/sys/sys_savegame.cpp @@ -272,6 +272,7 @@ idSaveLoadParms::~idSaveLoadParms */ idSaveLoadParms::~idSaveLoadParms() { + /* SRS - Don't need to repeat this code here, since auto-deletes are already handled by idSaveGameManager::FinishProcessor for( int i = 0; i < files.Num(); ++i ) { if( files[i]->type & SAVEGAMEFILE_AUTO_DELETE ) @@ -279,6 +280,7 @@ idSaveLoadParms::~idSaveLoadParms() delete files[i]; } } + */ } /* diff --git a/neo/sys/sys_voicechat.h b/neo/sys/sys_voicechat.h index e9e894a9..06f4263c 100644 --- a/neo/sys/sys_voicechat.h +++ b/neo/sys/sys_voicechat.h @@ -39,7 +39,9 @@ class idVoiceChatMgr { public: idVoiceChatMgr() : activeLobbyType( -1 ), activeGroupIndex( 0 ), sendFrame( 0 ), disableVoiceReasons( 0 ), sendGlobal( false ) {} - + + virtual ~idVoiceChatMgr() {} // SRS - Added virtual destructor + virtual void Init( void* pXAudio2 ); virtual void Shutdown();