From f0c61a3f552fd4655aff8202bd92b0ab80396101 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Tue, 28 Feb 2023 18:02:45 -0500 Subject: [PATCH 1/9] Use command queue sync method vs. device sync for higher performance / frame rate --- neo/cmake-xcode-debug.sh | 7 +-- neo/idlib/precompiled.h | 3 +- neo/renderer/NVRHI/RenderBackend_NVRHI.cpp | 10 ++-- neo/sys/DeviceManager.h | 1 - neo/sys/DeviceManager_DX12.cpp | 11 +++++ neo/sys/DeviceManager_VK.cpp | 54 ++++++---------------- 6 files changed, 37 insertions(+), 49 deletions(-) diff --git a/neo/cmake-xcode-debug.sh b/neo/cmake-xcode-debug.sh index 66d77134..a2ee3f06 100755 --- a/neo/cmake-xcode-debug.sh +++ b/neo/cmake-xcode-debug.sh @@ -5,6 +5,7 @@ cd xcode-debug # note 1: remove or set -DCMAKE_SUPPRESS_REGENERATION=OFF to reenable ZERO_CHECK target which checks for CMakeLists.txt changes and re-runs CMake before builds # however, if ZERO_CHECK is reenabled **must** add VULKAN_SDK location to Xcode Custom Paths (under Prefs/Locations) otherwise build failures may occur # note 2: policy CMAKE_POLICY_DEFAULT_CMP0142=NEW suppresses non-existant per-config suffixes on Xcode library search paths, works for cmake version 3.25 and later -#note 3: env variable MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE=1 enables MoltenVK's image view swizzle which may be required on older macOS versions or hardware (see vulkaninfo) -# note 4: env variable MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=2 enables MoltenVK's use of Metal argument buffers only if VK_EXT_descriptor_indexing is enabled -cmake -G Xcode -DCMAKE_BUILD_TYPE=Debug -DCMAKE_XCODE_GENERATE_SCHEME=ON -DCMAKE_XCODE_SCHEME_ENVIRONMENT="MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE=1;MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=2" -DCMAKE_SUPPRESS_REGENERATION=ON -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include ../neo -DCMAKE_POLICY_DEFAULT_CMP0142=NEW -Wno-dev +# note 3: env variable MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE=1 enables MoltenVK's image view swizzle which may be required on older macOS versions or hardware (see vulkaninfo) +# note 4: env variable MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS=1 enforces synchronous queue submits which is required for the synchronization method used by the game +# note 5: env variable MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=2 enables MoltenVK's use of Metal argument buffers only if VK_EXT_descriptor_indexing is enabled +cmake -G Xcode -DCMAKE_BUILD_TYPE=Debug -DCMAKE_XCODE_GENERATE_SCHEME=ON -DCMAKE_XCODE_SCHEME_ENVIRONMENT="MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE=1;MVK_CONFIG_SYNCHRONOUS_QUEUE_SUBMITS=1;MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=2" -DCMAKE_SUPPRESS_REGENERATION=ON -DOPENAL_LIBRARY=/usr/local/opt/openal-soft/lib/libopenal.dylib -DOPENAL_INCLUDE_DIR=/usr/local/opt/openal-soft/include ../neo -DCMAKE_POLICY_DEFAULT_CMP0142=NEW -Wno-dev diff --git a/neo/idlib/precompiled.h b/neo/idlib/precompiled.h index 90dfe8d3..3ac48bd2 100644 --- a/neo/idlib/precompiled.h +++ b/neo/idlib/precompiled.h @@ -90,8 +90,9 @@ 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 -#if defined(__APPLE__) && ( defined( USE_VULKAN ) || defined( USE_NVRHI ) ) +#if ( defined(__APPLE__) && defined( USE_VULKAN ) ) || defined( USE_NVRHI ) // SRS - macOS MoltenVK/Metal needs triple buffering for full screen to work properly + // SRS - use triple buffering for NVRHI with command queue event query sync method const uint32 NUM_FRAME_DATA = 3; #else const uint32 NUM_FRAME_DATA = 2; diff --git a/neo/renderer/NVRHI/RenderBackend_NVRHI.cpp b/neo/renderer/NVRHI/RenderBackend_NVRHI.cpp index f985b942..b1acac89 100644 --- a/neo/renderer/NVRHI/RenderBackend_NVRHI.cpp +++ b/neo/renderer/NVRHI/RenderBackend_NVRHI.cpp @@ -1597,14 +1597,16 @@ We want to exit this with the GPU idle, right at vsync void idRenderBackend::GL_BlockingSwapBuffers() { // Make sure that all frames have finished rendering - deviceManager->GetDevice()->waitForIdle(); - - // Release all in-flight references to the render targets - deviceManager->GetDevice()->runGarbageCollection(); + // SRS - device-level sync kills perf by serializing command queue processing (CPU) and rendering (GPU) + // - instead, use alternative sync method (based on command queue event queries) inside Present() + //deviceManager->GetDevice()->waitForIdle(); // Present to the swap chain. deviceManager->Present(); + // Release all in-flight references to the render targets + deviceManager->GetDevice()->runGarbageCollection(); + renderLog.EndFrame(); if( deviceManager->GetGraphicsAPI() == nvrhi::GraphicsAPI::VULKAN ) diff --git a/neo/sys/DeviceManager.h b/neo/sys/DeviceManager.h index 60e1e90b..02d5e6a0 100644 --- a/neo/sys/DeviceManager.h +++ b/neo/sys/DeviceManager.h @@ -61,7 +61,6 @@ struct DeviceCreationParameters nvrhi::Format swapChainFormat = nvrhi::Format::RGBA8_UNORM; // RB: don't do the sRGB gamma ramp with the swapchain uint32_t swapChainSampleCount = 1; uint32_t swapChainSampleQuality = 0; - uint32_t maxFramesInFlight = 2; bool enableDebugRuntime = false; bool enableNvrhiValidationLayer = false; bool vsyncEnabled = false; diff --git a/neo/sys/DeviceManager_DX12.cpp b/neo/sys/DeviceManager_DX12.cpp index 0be4f182..e357fed3 100644 --- a/neo/sys/DeviceManager_DX12.cpp +++ b/neo/sys/DeviceManager_DX12.cpp @@ -61,6 +61,7 @@ class DeviceManager_DX12 : public DeviceManager std::vector m_RhiSwapChainBuffers; RefCountPtr m_FrameFence; std::vector m_FrameFenceEvents; + nvrhi::EventQueryHandle m_FrameWaitQuery; UINT64 m_FrameCount = 1; @@ -447,6 +448,9 @@ bool DeviceManager_DX12::CreateDeviceAndSwapChain() m_FrameFenceEvents.push_back( CreateEvent( nullptr, false, true, NULL ) ); } + m_FrameWaitQuery = nvrhiDevice->createEventQuery(); + nvrhiDevice->setEventQuery( m_FrameWaitQuery, nvrhi::CommandQueue::Graphics ); + return true; } @@ -459,6 +463,8 @@ void DeviceManager_DX12::DestroyDeviceAndSwapChain() nvrhiDevice = nullptr; + m_FrameWaitQuery = nullptr; + for( auto fenceEvent : m_FrameFenceEvents ) { WaitForSingleObject( fenceEvent, INFINITE ); @@ -648,6 +654,11 @@ void DeviceManager_DX12::Present() // SRS - Don't change deviceParms.vsyncEnabled here, simply test for vsync mode 2 to set DXGI SyncInterval m_SwapChain->Present( deviceParms.vsyncEnabled && r_swapInterval.GetInteger() == 2 ? 1 : 0, presentFlags ); + // SRS - Sync on previous frame's command queue completion vs. waitForIdle() on whole device + nvrhiDevice->waitEventQuery( m_FrameWaitQuery ); + nvrhiDevice->resetEventQuery( m_FrameWaitQuery ); + nvrhiDevice->setEventQuery( m_FrameWaitQuery, nvrhi::CommandQueue::Graphics ); + m_FrameFence->SetEventOnCompletion( m_FrameCount, m_FrameFenceEvents[bufferIndex] ); m_GraphicsQueue->Signal( m_FrameFence, m_FrameCount ); m_FrameCount++; diff --git a/neo/sys/DeviceManager_VK.cpp b/neo/sys/DeviceManager_VK.cpp index 9b760356..d2314abd 100644 --- a/neo/sys/DeviceManager_VK.cpp +++ b/neo/sys/DeviceManager_VK.cpp @@ -272,8 +272,7 @@ private: nvrhi::CommandListHandle m_BarrierCommandList; vk::Semaphore m_PresentSemaphore; - std::queue m_FramesInFlight; - std::vector m_QueryPool; + nvrhi::EventQueryHandle m_FrameWaitQuery; // SRS - flag indicating support for eFifoRelaxed surface presentation (r_swapInterval = 1) mode bool enablePModeFifoRelaxed = false; @@ -1124,6 +1123,10 @@ bool DeviceManager_VK::CreateDeviceAndSwapChain() vkGetMoltenVKConfigurationMVK( m_VulkanInstance, &pConfig, &pConfigSize ); + // SRS - Enforce synchronous queue submission for vkQueueSubmit() & vkQueuePresentKHR() + pConfig.synchronousQueueSubmits = VK_TRUE; + vkSetMoltenVKConfigurationMVK( m_VulkanInstance, &pConfig, &pConfigSize ); + // SRS - If we don't have native image view swizzle, enable MoltenVK's image view swizzle feature if( portabilityFeatures.imageViewFormatSwizzle == VK_FALSE ) { @@ -1182,6 +1185,9 @@ bool DeviceManager_VK::CreateDeviceAndSwapChain() m_PresentSemaphore = m_VulkanDevice.createSemaphore( vk::SemaphoreCreateInfo() ); + m_FrameWaitQuery = m_NvrhiDevice->createEventQuery(); + m_NvrhiDevice->setEventQuery( m_FrameWaitQuery, nvrhi::CommandQueue::Graphics ); + #undef CHECK return true; @@ -1191,25 +1197,13 @@ void DeviceManager_VK::DestroyDeviceAndSwapChain() { destroySwapChain(); + m_FrameWaitQuery = nullptr; + m_VulkanDevice.destroySemaphore( m_PresentSemaphore ); m_PresentSemaphore = vk::Semaphore(); m_BarrierCommandList = nullptr; - while( m_FramesInFlight.size() > 0 ) - { - auto query = m_FramesInFlight.front(); - m_FramesInFlight.pop(); - query = nullptr; - } - - if( !m_QueryPool.empty() ) - { - auto query = m_QueryPool.back(); - m_QueryPool.pop_back(); - query = nullptr; - } - m_NvrhiDevice = nullptr; m_ValidationLayer = nullptr; m_RendererString.clear(); @@ -1294,37 +1288,17 @@ void DeviceManager_VK::Present() } else { -#ifndef _WIN32 if( deviceParms.vsyncEnabled ) { m_PresentQueue.waitIdle(); } -#endif - - while( m_FramesInFlight.size() > deviceParms.maxFramesInFlight ) - { - auto query = m_FramesInFlight.front(); - m_FramesInFlight.pop(); - - m_NvrhiDevice->waitEventQuery( query ); - - m_QueryPool.push_back( query ); - } - - nvrhi::EventQueryHandle query; - if( !m_QueryPool.empty() ) - { - query = m_QueryPool.back(); - m_QueryPool.pop_back(); - } + // SRS - Sync on previous frame's command queue completion vs. waitForIdle() on whole device else { - query = m_NvrhiDevice->createEventQuery(); + m_NvrhiDevice->waitEventQuery( m_FrameWaitQuery ); + m_NvrhiDevice->resetEventQuery( m_FrameWaitQuery ); + m_NvrhiDevice->setEventQuery( m_FrameWaitQuery, nvrhi::CommandQueue::Graphics ); } - - m_NvrhiDevice->resetEventQuery( query ); - m_NvrhiDevice->setEventQuery( query, nvrhi::CommandQueue::Graphics ); - m_FramesInFlight.push( query ); } } From 967f38d64b2d78b77bf73a4afd492f9a729ba654 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Tue, 28 Feb 2023 18:05:09 -0500 Subject: [PATCH 2/9] Save screen shots to fs_savepath versus fs_basepath --- neo/renderer/RenderSystem_init.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index 01a5d7e7..d1183236 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -890,7 +890,8 @@ bool R_ReadPixelsRGB8( nvrhi::IDevice* device, CommonRenderPasses* pPasses, nvrh data[ i * 4 + 3 ] = 0xff; } - R_WritePNG( fullname, static_cast( pData ), 4, desc.width, desc.height, true, "fs_basepath" ); + // SRS - Save screen shots to fs_savepath, not fs_basepath + R_WritePNG( fullname, static_cast( pData ), 4, desc.width, desc.height, true, "fs_savepath" ); if( newData ) { From c5aa8afe8a32f60defbdf9e78346ea1ff58e5526 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Sat, 4 Mar 2023 16:37:02 -0500 Subject: [PATCH 3/9] Fix SDL display size / refresh rate changes when already in fullscreen mode --- neo/sys/sdl/sdl_vkimp.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/neo/sys/sdl/sdl_vkimp.cpp b/neo/sys/sdl/sdl_vkimp.cpp index 35bc8856..03030f69 100644 --- a/neo/sys/sdl/sdl_vkimp.cpp +++ b/neo/sys/sdl/sdl_vkimp.cpp @@ -470,15 +470,24 @@ static bool SetScreenParmsFullscreen( glimpParms_t parms ) // change settings in that display mode according to parms // FIXME: check if refreshrate, width and height are supported? - m.refresh_rate = parms.displayHz; - m.w = parms.width; - m.h = parms.height; - - // set that displaymode - if( SDL_SetWindowDisplayMode( window, &m ) < 0 ) + if( m.w != parms.width || m.h != parms.height || m.refresh_rate != parms.displayHz ) { - common->Warning( "Couldn't set window mode for fullscreen, reason: %s", SDL_GetError() ); - return false; + m.w = parms.width; + m.h = parms.height; + m.refresh_rate = parms.displayHz; + + // if we're already in fullscreen mode, disable it first so resizing works properly + if( glConfig.isFullscreen ) + { + SDL_SetWindowFullscreen( window, SDL_FALSE ); + } + + // set the new displaymode + if( SDL_SetWindowDisplayMode( window, &m ) < 0 ) + { + common->Warning( "Couldn't set window mode for fullscreen, reason: %s", SDL_GetError() ); + return false; + } } // if we're currently not in fullscreen mode, we need to switch to fullscreen From 76da1beefd9d5c09a25b0c3a134d91bfe8bc29cd Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Sat, 4 Mar 2023 16:39:43 -0500 Subject: [PATCH 4/9] Fix compilation errors when Optick profiling is off --- neo/framework/File_SaveGame.cpp | 8 ++++++++ neo/framework/common_frame.cpp | 2 ++ neo/idlib/ParallelJobList.cpp | 2 ++ neo/idlib/precompiled.h | 2 +- neo/sys/common/savegame.cpp | 2 ++ 5 files changed, 15 insertions(+), 1 deletion(-) diff --git a/neo/framework/File_SaveGame.cpp b/neo/framework/File_SaveGame.cpp index 65e2e94b..b6ff7288 100644 --- a/neo/framework/File_SaveGame.cpp +++ b/neo/framework/File_SaveGame.cpp @@ -71,7 +71,9 @@ class idSGFcompressThread : public idSysThread public: virtual int Run() { +#if USE_OPTICK OPTICK_THREAD( "idSGFcompressThread" ); +#endif sgf->CompressBlock(); return 0; @@ -83,7 +85,9 @@ class idSGFdecompressThread : public idSysThread public: virtual int Run() { +#if USE_OPTICK OPTICK_THREAD( "idSGFdecompressThread" ); +#endif sgf->DecompressBlock(); return 0; @@ -95,7 +99,9 @@ class idSGFwriteThread : public idSysThread public: virtual int Run() { +#if USE_OPTICK OPTICK_THREAD( "idSGFwriteThread" ); +#endif sgf->WriteBlock(); return 0; @@ -107,7 +113,9 @@ class idSGFreadThread : public idSysThread public: virtual int Run() { +#if USE_OPTICK OPTICK_THREAD( "idSGFreadThread" ); +#endif sgf->ReadBlock(); return 0; diff --git a/neo/framework/common_frame.cpp b/neo/framework/common_frame.cpp index 36a3a5ec..da8dc167 100644 --- a/neo/framework/common_frame.cpp +++ b/neo/framework/common_frame.cpp @@ -90,7 +90,9 @@ be called directly in the foreground thread for comparison. */ int idGameThread::Run() { +#if USE_OPTICK OPTICK_THREAD( "idGameThread" ); +#endif commonLocal.frameTiming.startGameTime = Sys_Microseconds(); diff --git a/neo/idlib/ParallelJobList.cpp b/neo/idlib/ParallelJobList.cpp index 54b14c5d..16c31ec6 100644 --- a/neo/idlib/ParallelJobList.cpp +++ b/neo/idlib/ParallelJobList.cpp @@ -1145,7 +1145,9 @@ idJobThread::Run */ int idJobThread::Run() { +#if USE_OPTICK OPTICK_THREAD( GetName() ); +#endif threadJobListState_t threadJobListState[MAX_JOBLISTS]; int numJobLists = 0; diff --git a/neo/idlib/precompiled.h b/neo/idlib/precompiled.h index 3ac48bd2..012c878c 100644 --- a/neo/idlib/precompiled.h +++ b/neo/idlib/precompiled.h @@ -107,7 +107,7 @@ const int MAX_EXPRESSION_REGISTERS = 4096; #endif // RB: make Optick profiling available everywhere -#if defined( USE_OPTICK ) +#if USE_OPTICK #include "../libs/optick/optick.h" #endif diff --git a/neo/sys/common/savegame.cpp b/neo/sys/common/savegame.cpp index 65de9bb8..de47bef8 100644 --- a/neo/sys/common/savegame.cpp +++ b/neo/sys/common/savegame.cpp @@ -746,7 +746,9 @@ idSaveGameThread::Run */ int idSaveGameThread::Run() { +#if USE_OPTICK OPTICK_THREAD( "idSaveGameThread" ); +#endif int ret = ERROR_SUCCESS; From 0c217ebbe96d534ca75e3752cda37646d63589a8 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Sat, 4 Mar 2023 21:06:08 -0500 Subject: [PATCH 5/9] Fix win32 compilation errors when Optick profiling is off --- neo/sys/win32/win_main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/neo/sys/win32/win_main.cpp b/neo/sys/win32/win_main.cpp index 427b447e..877b35d0 100644 --- a/neo/sys/win32/win_main.cpp +++ b/neo/sys/win32/win_main.cpp @@ -1949,6 +1949,7 @@ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin Sys_SetDPIAwareness(); // Setting memory allocators +#if USE_OPTICK OPTICK_SET_MEMORY_ALLOCATOR( []( size_t size ) -> void* { return operator new( size ); }, []( void* p ) @@ -1960,6 +1961,7 @@ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin /* Do some TLS initialization here if needed */ } ); +#endif #if 0 DWORD handler = ( DWORD )_except_handler; @@ -2034,7 +2036,9 @@ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin // main game loop while( 1 ) { +#if USE_OPTICK OPTICK_FRAME( "MainThread" ); +#endif Win_Frame(); @@ -2049,7 +2053,9 @@ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin common->Frame(); } +#if USE_OPTICK OPTICK_SHUTDOWN(); +#endif // never gets here return 0; From b1c2cdbec8dd978a9e2bb0e41461eaab63d4a33d Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Sat, 4 Mar 2023 21:15:32 -0500 Subject: [PATCH 6/9] More conservative frame sync: wait before vs after DX12 / Vulkan present operations --- neo/sys/DeviceManager_DX12.cpp | 10 +++++----- neo/sys/DeviceManager_VK.cpp | 21 ++++++--------------- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/neo/sys/DeviceManager_DX12.cpp b/neo/sys/DeviceManager_DX12.cpp index e357fed3..a13de424 100644 --- a/neo/sys/DeviceManager_DX12.cpp +++ b/neo/sys/DeviceManager_DX12.cpp @@ -636,6 +636,11 @@ void DeviceManager_DX12::EndFrame() void DeviceManager_DX12::Present() { + // SRS - Sync on previous frame's command queue completion vs. waitForIdle() on whole device + nvrhiDevice->waitEventQuery( m_FrameWaitQuery ); + nvrhiDevice->resetEventQuery( m_FrameWaitQuery ); + nvrhiDevice->setEventQuery( m_FrameWaitQuery, nvrhi::CommandQueue::Graphics ); + if( !windowVisible ) { return; @@ -654,11 +659,6 @@ void DeviceManager_DX12::Present() // SRS - Don't change deviceParms.vsyncEnabled here, simply test for vsync mode 2 to set DXGI SyncInterval m_SwapChain->Present( deviceParms.vsyncEnabled && r_swapInterval.GetInteger() == 2 ? 1 : 0, presentFlags ); - // SRS - Sync on previous frame's command queue completion vs. waitForIdle() on whole device - nvrhiDevice->waitEventQuery( m_FrameWaitQuery ); - nvrhiDevice->resetEventQuery( m_FrameWaitQuery ); - nvrhiDevice->setEventQuery( m_FrameWaitQuery, nvrhi::CommandQueue::Graphics ); - m_FrameFence->SetEventOnCompletion( m_FrameCount, m_FrameFenceEvents[bufferIndex] ); m_GraphicsQueue->Signal( m_FrameFence, m_FrameCount ); m_FrameCount++; diff --git a/neo/sys/DeviceManager_VK.cpp b/neo/sys/DeviceManager_VK.cpp index d2314abd..c5a7ab1c 100644 --- a/neo/sys/DeviceManager_VK.cpp +++ b/neo/sys/DeviceManager_VK.cpp @@ -1270,6 +1270,11 @@ void DeviceManager_VK::EndFrame() void DeviceManager_VK::Present() { + // SRS - Sync on previous frame's command queue completion vs. waitForIdle() on whole device + m_NvrhiDevice->waitEventQuery( m_FrameWaitQuery ); + m_NvrhiDevice->resetEventQuery( m_FrameWaitQuery ); + m_NvrhiDevice->setEventQuery( m_FrameWaitQuery, nvrhi::CommandQueue::Graphics ); + vk::PresentInfoKHR info = vk::PresentInfoKHR() .setWaitSemaphoreCount( 1 ) .setPWaitSemaphores( &m_PresentSemaphore ) @@ -1280,26 +1285,12 @@ void DeviceManager_VK::Present() const vk::Result res = m_PresentQueue.presentKHR( &info ); assert( res == vk::Result::eSuccess || res == vk::Result::eErrorOutOfDateKHR || res == vk::Result::eSuboptimalKHR ); - if( deviceParms.enableDebugRuntime ) + if( deviceParms.enableDebugRuntime || deviceParms.vsyncEnabled ) { // according to vulkan-tutorial.com, "the validation layer implementation expects // the application to explicitly synchronize with the GPU" m_PresentQueue.waitIdle(); } - else - { - if( deviceParms.vsyncEnabled ) - { - m_PresentQueue.waitIdle(); - } - // SRS - Sync on previous frame's command queue completion vs. waitForIdle() on whole device - else - { - m_NvrhiDevice->waitEventQuery( m_FrameWaitQuery ); - m_NvrhiDevice->resetEventQuery( m_FrameWaitQuery ); - m_NvrhiDevice->setEventQuery( m_FrameWaitQuery, nvrhi::CommandQueue::Graphics ); - } - } } DeviceManager* DeviceManager::CreateVK() From 7b9d36c1d13eaf7694dac808144ab3206eda6721 Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Sun, 5 Mar 2023 08:31:25 -0500 Subject: [PATCH 7/9] Revert compileshaders.cmake to use SPIRV target = vulkan1.2 for macOS / MoltenVK --- README.md | 2 +- neo/compileshaders.cmake | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 5b7bc821..539ef005 100644 --- a/README.md +++ b/README.md @@ -494,7 +494,7 @@ Recommended in this case is `cmake-vs2019-64bit.bat` or `cmake-vs2019-64bit-no-f You don't need FFmpeg to be installed. You can turn it off by adding -DFFMPEG=OFF and -DBINKDEC=ON to the CMake options. For debug builds FFmpeg is enabled by default because the bundled libbinkdec is slow during development if compiled for Debug mode. For release, retail and universal builds FFmpeg is disabled and libbinkdec is enabled by default. - The Vulkan SDK must be installed and can be obtained from https://vulkan.lunarg.com/sdk/home#mac + The Vulkan SDK 1.3.231.1 or later must be installed and can be obtained from https://vulkan.lunarg.com/sdk/home#mac 3. Generate the Makefiles using CMake: diff --git a/neo/compileshaders.cmake b/neo/compileshaders.cmake index 69f405f1..87f8ee74 100644 --- a/neo/compileshaders.cmake +++ b/neo/compileshaders.cmake @@ -106,12 +106,7 @@ function(compile_shaders) endif() if (NOT params_CFLAGS) - if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - # SRS - MoltenVK currently supports vulkan 1.1 (1.2 coming in next SDK release) - set(CFLAGS "$,-Zi,> -fspv-target-env=vulkan1.1 -O3 -WX -Zpr") - else() - set(CFLAGS "$,-Zi,> -fspv-target-env=vulkan1.2 -O3 -WX -Zpr") - endif() + set(CFLAGS "$,-Zi,> -fspv-target-env=vulkan1.2 -O3 -WX -Zpr") else() set(CFLAGS ${params_CFLAGS}) endif() From 378b66075c3661b3141b53f9a981e6ac64aee30a Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Sun, 5 Mar 2023 08:51:34 -0500 Subject: [PATCH 8/9] Revert screen shot fs_savepath change for Windows and linux --- neo/renderer/RenderSystem_init.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index d1183236..b730dfc0 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -890,8 +890,12 @@ bool R_ReadPixelsRGB8( nvrhi::IDevice* device, CommonRenderPasses* pPasses, nvrh data[ i * 4 + 3 ] = 0xff; } - // SRS - Save screen shots to fs_savepath, not fs_basepath + // SRS - Save screen shots to fs_savepath on macOS (i.e. don't save into an app bundle's basepath) +#if defined(__APPLE__) R_WritePNG( fullname, static_cast( pData ), 4, desc.width, desc.height, true, "fs_savepath" ); +#else + R_WritePNG( fullname, static_cast( pData ), 4, desc.width, desc.height, true, "fs_basepath" ); +#endif if( newData ) { From 764469ab310ecf6b0445451db6cb7a08a095775b Mon Sep 17 00:00:00 2001 From: Stephen Saunders Date: Sun, 5 Mar 2023 09:36:44 -0500 Subject: [PATCH 9/9] Revert #if USE_OPTICK wrappers --- neo/framework/File_SaveGame.cpp | 8 -------- neo/framework/common_frame.cpp | 2 -- neo/idlib/ParallelJobList.cpp | 2 -- neo/sys/common/savegame.cpp | 2 -- neo/sys/win32/win_main.cpp | 6 ------ 5 files changed, 20 deletions(-) diff --git a/neo/framework/File_SaveGame.cpp b/neo/framework/File_SaveGame.cpp index b6ff7288..65e2e94b 100644 --- a/neo/framework/File_SaveGame.cpp +++ b/neo/framework/File_SaveGame.cpp @@ -71,9 +71,7 @@ class idSGFcompressThread : public idSysThread public: virtual int Run() { -#if USE_OPTICK OPTICK_THREAD( "idSGFcompressThread" ); -#endif sgf->CompressBlock(); return 0; @@ -85,9 +83,7 @@ class idSGFdecompressThread : public idSysThread public: virtual int Run() { -#if USE_OPTICK OPTICK_THREAD( "idSGFdecompressThread" ); -#endif sgf->DecompressBlock(); return 0; @@ -99,9 +95,7 @@ class idSGFwriteThread : public idSysThread public: virtual int Run() { -#if USE_OPTICK OPTICK_THREAD( "idSGFwriteThread" ); -#endif sgf->WriteBlock(); return 0; @@ -113,9 +107,7 @@ class idSGFreadThread : public idSysThread public: virtual int Run() { -#if USE_OPTICK OPTICK_THREAD( "idSGFreadThread" ); -#endif sgf->ReadBlock(); return 0; diff --git a/neo/framework/common_frame.cpp b/neo/framework/common_frame.cpp index da8dc167..36a3a5ec 100644 --- a/neo/framework/common_frame.cpp +++ b/neo/framework/common_frame.cpp @@ -90,9 +90,7 @@ be called directly in the foreground thread for comparison. */ int idGameThread::Run() { -#if USE_OPTICK OPTICK_THREAD( "idGameThread" ); -#endif commonLocal.frameTiming.startGameTime = Sys_Microseconds(); diff --git a/neo/idlib/ParallelJobList.cpp b/neo/idlib/ParallelJobList.cpp index 16c31ec6..54b14c5d 100644 --- a/neo/idlib/ParallelJobList.cpp +++ b/neo/idlib/ParallelJobList.cpp @@ -1145,9 +1145,7 @@ idJobThread::Run */ int idJobThread::Run() { -#if USE_OPTICK OPTICK_THREAD( GetName() ); -#endif threadJobListState_t threadJobListState[MAX_JOBLISTS]; int numJobLists = 0; diff --git a/neo/sys/common/savegame.cpp b/neo/sys/common/savegame.cpp index de47bef8..65de9bb8 100644 --- a/neo/sys/common/savegame.cpp +++ b/neo/sys/common/savegame.cpp @@ -746,9 +746,7 @@ idSaveGameThread::Run */ int idSaveGameThread::Run() { -#if USE_OPTICK OPTICK_THREAD( "idSaveGameThread" ); -#endif int ret = ERROR_SUCCESS; diff --git a/neo/sys/win32/win_main.cpp b/neo/sys/win32/win_main.cpp index 877b35d0..427b447e 100644 --- a/neo/sys/win32/win_main.cpp +++ b/neo/sys/win32/win_main.cpp @@ -1949,7 +1949,6 @@ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin Sys_SetDPIAwareness(); // Setting memory allocators -#if USE_OPTICK OPTICK_SET_MEMORY_ALLOCATOR( []( size_t size ) -> void* { return operator new( size ); }, []( void* p ) @@ -1961,7 +1960,6 @@ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin /* Do some TLS initialization here if needed */ } ); -#endif #if 0 DWORD handler = ( DWORD )_except_handler; @@ -2036,9 +2034,7 @@ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin // main game loop while( 1 ) { -#if USE_OPTICK OPTICK_FRAME( "MainThread" ); -#endif Win_Frame(); @@ -2053,9 +2049,7 @@ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLin common->Frame(); } -#if USE_OPTICK OPTICK_SHUTDOWN(); -#endif // never gets here return 0;