diff --git a/neo/renderer/ImageManager.cpp b/neo/renderer/ImageManager.cpp index f7a4cdc9..482bc595 100644 --- a/neo/renderer/ImageManager.cpp +++ b/neo/renderer/ImageManager.cpp @@ -784,6 +784,9 @@ void idImageManager::Shutdown() imageHash.Clear(); deferredImages.DeleteContents( true ); deferredImageHash.Clear(); +#if defined( USE_NVRHI ) + commandList.Reset(); +#endif } /* diff --git a/neo/renderer/ImmediateMode.cpp b/neo/renderer/ImmediateMode.cpp index a44d22ac..651ca155 100644 --- a/neo/renderer/ImmediateMode.cpp +++ b/neo/renderer/ImmediateMode.cpp @@ -67,6 +67,12 @@ void fhImmediateMode::Init( nvrhi::ICommandList* commandList ) InitBuffers( commandList ); } +void fhImmediateMode::Shutdown() +{ + vertexBuffer.FreeBufferObject(); + indexBuffer.FreeBufferObject(); +} + void fhImmediateMode::ResetStats() { drawCallCount = 0; diff --git a/neo/renderer/ImmediateMode.h b/neo/renderer/ImmediateMode.h index 9a743ba9..c2d6078c 100644 --- a/neo/renderer/ImmediateMode.h +++ b/neo/renderer/ImmediateMode.h @@ -73,6 +73,7 @@ public: static void AddTrianglesFromPolygon( fhImmediateMode& im, const idVec3* xyz, int num ); static void Init( nvrhi::ICommandList* commandList ); + static void Shutdown(); static void ResetStats(); static int DrawCallCount(); static int DrawCallVertexSize(); diff --git a/neo/renderer/ModelManager.cpp b/neo/renderer/ModelManager.cpp index 86246a56..d136fe40 100644 --- a/neo/renderer/ModelManager.cpp +++ b/neo/renderer/ModelManager.cpp @@ -286,6 +286,9 @@ void idRenderModelManagerLocal::Shutdown() { models.DeleteContents( true ); hash.Free(); +#if defined( USE_NVRHI ) + commandList.Reset(); +#endif } /* diff --git a/neo/renderer/NVRHI/RenderBackend_NVRHI.cpp b/neo/renderer/NVRHI/RenderBackend_NVRHI.cpp index 7ce69f62..24d5d122 100644 --- a/neo/renderer/NVRHI/RenderBackend_NVRHI.cpp +++ b/neo/renderer/NVRHI/RenderBackend_NVRHI.cpp @@ -199,7 +199,32 @@ void idRenderBackend::Init() void idRenderBackend::Shutdown() { - delete ssaoPass; + // SRS - Clean up NVRHI resources before Sys_Quit(), otherwise non-zero exit code (destructors too late) + + // Clear all cached pipeline data + tr.backend.ClearCaches(); + pipelineCache.Shutdown(); + + // Delete all renderpass resources + commonPasses.Shutdown(); + + // Delete current binding sets + for( int i = 0; i < currentBindingSets.Num(); i++ ) + { + currentBindingSets[i].Reset(); + } + + // Unload shaders, delete binding layouts, and unmap memory + renderProgManager.Shutdown(); + + // Delete renderlog command buffer and timer query resources + renderLog.Shutdown(); + + // Delete command list + commandList.Reset(); + + // Delete immediate mode buffer objects + fhImmediateMode::Shutdown(); #if defined( VULKAN_USE_PLATFORM_SDL ) VKimp_Shutdown(); diff --git a/neo/renderer/Passes/CommonPasses.cpp b/neo/renderer/Passes/CommonPasses.cpp index a11893ae..01eb5dbb 100644 --- a/neo/renderer/Passes/CommonPasses.cpp +++ b/neo/renderer/Passes/CommonPasses.cpp @@ -177,6 +177,43 @@ void CommonRenderPasses::Init( nvrhi::IDevice* device ) } } +void CommonRenderPasses::Shutdown() +{ + // SRS - Delete the pipelines referenced by the blit cache + for( auto& [key, pipeline] : m_BlitPsoCache ) + { + pipeline.Reset(); + } + + // SRS - These assets have automatic resource management with overloaded = operator + m_RectVS = nullptr; + m_BlitPS = nullptr; + m_BlitArrayPS = nullptr; + m_SharpenPS = nullptr; + m_SharpenArrayPS = nullptr; + + m_BlackTexture = nullptr; + m_GrayTexture = nullptr; + m_WhiteTexture = nullptr; + m_BlackTexture2DArray = nullptr; + m_WhiteTexture2DArray = nullptr; + m_BlackCubeMapArray = nullptr; + + m_PointClampSampler = nullptr; + m_PointWrapSampler = nullptr; + m_LinearClampSampler = nullptr; + m_LinearBorderSampler = nullptr; + m_LinearClampCompareSampler = nullptr; + m_LinearWrapSampler = nullptr; + m_AnisotropicWrapSampler = nullptr; + m_AnisotropicClampEdgeSampler = nullptr; + + m_BlitBindingLayout = nullptr; + + // SRS - Remove reference to nvrhi::IDevice, otherwise won't clean up properly on shutdown + m_Device = nullptr; +} + void CommonRenderPasses::BlitTexture( nvrhi::ICommandList* commandList, const BlitParameters& params, BindingCache* bindingCache ) { assert( commandList ); diff --git a/neo/renderer/Passes/CommonPasses.h b/neo/renderer/Passes/CommonPasses.h index a0b32c70..ed7d8877 100644 --- a/neo/renderer/Passes/CommonPasses.h +++ b/neo/renderer/Passes/CommonPasses.h @@ -134,6 +134,7 @@ public: CommonRenderPasses(); void Init( nvrhi::IDevice* device ); + void Shutdown(); void BlitTexture( nvrhi::ICommandList* commandList, const BlitParameters& params, BindingCache* bindingCache = nullptr ); @@ -141,4 +142,4 @@ public: void BlitTexture( nvrhi::ICommandList* commandList, nvrhi::IFramebuffer* targetFramebuffer, nvrhi::ITexture* sourceTexture, BindingCache* bindingCache = nullptr ); }; -#endif \ No newline at end of file +#endif diff --git a/neo/renderer/PipelineCache.cpp b/neo/renderer/PipelineCache.cpp index 150c7148..62369b93 100644 --- a/neo/renderer/PipelineCache.cpp +++ b/neo/renderer/PipelineCache.cpp @@ -43,6 +43,12 @@ void PipelineCache::Init( nvrhi::DeviceHandle deviceHandle ) device = deviceHandle; } +void PipelineCache::Shutdown() +{ + // SRS - Remove reference to nvrhi::IDevice, otherwise won't clean up properly on shutdown + device = nullptr; +} + void PipelineCache::Clear() { pipelines.Clear(); @@ -515,4 +521,4 @@ nvrhi::DepthStencilState::StencilOpDesc PipelineCache::GetStencilOpState( uint64 } return stencilOp; -} \ No newline at end of file +} diff --git a/neo/renderer/PipelineCache.h b/neo/renderer/PipelineCache.h index 33f20580..80a491dd 100644 --- a/neo/renderer/PipelineCache.h +++ b/neo/renderer/PipelineCache.h @@ -69,6 +69,7 @@ public: PipelineCache(); void Init( nvrhi::DeviceHandle deviceHandle ); + void Shutdown(); void Clear(); @@ -85,4 +86,4 @@ private: }; -#endif \ No newline at end of file +#endif diff --git a/neo/renderer/RenderLog.cpp b/neo/renderer/RenderLog.cpp index 214b3f8d..daf4be0c 100644 --- a/neo/renderer/RenderLog.cpp +++ b/neo/renderer/RenderLog.cpp @@ -332,6 +332,21 @@ void idRenderLog::Init() #endif } +void idRenderLog::Shutdown() +{ +#if defined( USE_NVRHI ) + if( commandList ) + { + commandList.Reset(); + } + + for( int i = 0; i < MRB_TOTAL_QUERIES; i++ ) + { + timerQueries[i].Reset(); + } +#endif +} + void idRenderLog::StartFrame( nvrhi::ICommandList* _commandList ) { #if defined( USE_NVRHI ) @@ -537,4 +552,4 @@ void idRenderLog::CloseBlock() { PC_EndNamedEvent( commandList ); } -// RB end \ No newline at end of file +// RB end diff --git a/neo/renderer/RenderLog.h b/neo/renderer/RenderLog.h index 87c4f185..5d6b81da 100644 --- a/neo/renderer/RenderLog.h +++ b/neo/renderer/RenderLog.h @@ -90,6 +90,7 @@ public: idRenderLog(); void Init(); + void Shutdown(); void StartFrame( nvrhi::ICommandList* _commandList ); void EndFrame(); diff --git a/neo/renderer/RenderProgs.cpp b/neo/renderer/RenderProgs.cpp index cee76ad3..2f8cedde 100644 --- a/neo/renderer/RenderProgs.cpp +++ b/neo/renderer/RenderProgs.cpp @@ -769,6 +769,29 @@ idRenderProgManager::Shutdown() void idRenderProgManager::Shutdown() { KillAllShaders(); + +#if defined( USE_NVRHI ) + // SRS - Delete renderprogs builtin binding layouts + for( int i = 0; i < renderProgs.Num(); i++ ) + { + for( int j = 0; j < renderProgs[i].bindingLayouts.Num(); j++ ) + { + renderProgs[i].bindingLayouts[j].Reset(); + } + } + + // SRS - Delete binding layouts + for( int i = 0; i < bindingLayouts.Num(); i++ ) + { + for( int j = 0; j < bindingLayouts[i].Num(); j++ ) + { + bindingLayouts[i][j].Reset(); + } + } + + // SRS - Unmap buffer memory using overloaded = operator + constantBuffer = nullptr; +#endif } /* @@ -1228,4 +1251,4 @@ void RpPrintState( uint64 stateBits ) { printStencil( STENCIL_FACE_NUM, stateBits, mask, ref ); } -} \ No newline at end of file +} diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index b7c5c231..7db1f552 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -2284,6 +2284,10 @@ void idRenderSystemLocal::Shutdown() Clear(); +#if defined( USE_NVRHI ) + commandList.Reset(); +#endif + ShutdownOpenGL(); bInitialized = false; diff --git a/neo/sys/sdl/DeviceManager_VK.cpp b/neo/sys/sdl/DeviceManager_VK.cpp index 31f6f2ad..f42d04e0 100644 --- a/neo/sys/sdl/DeviceManager_VK.cpp +++ b/neo/sys/sdl/DeviceManager_VK.cpp @@ -1083,6 +1083,20 @@ void DeviceManager_VK::DestroyDeviceAndSwapChain() 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(); diff --git a/neo/sys/sdl/sdl_vkimp.cpp b/neo/sys/sdl/sdl_vkimp.cpp index 7ee07135..9f295188 100644 --- a/neo/sys/sdl/sdl_vkimp.cpp +++ b/neo/sys/sdl/sdl_vkimp.cpp @@ -534,12 +534,6 @@ bool VKimp_SetScreenParms( glimpParms_t parms ) void DeviceManager::Shutdown() { DestroyDeviceAndSwapChain(); - - // destroy window - VKimp_Shutdown(); - - // restore gamma - //VKimp_RestoreGamma(); } #endif @@ -552,6 +546,13 @@ void VKimp_Shutdown() { common->Printf( "Shutting down Vulkan subsystem\n" ); +#if defined( USE_NVRHI ) + if( deviceManager ) + { + deviceManager->Shutdown(); + } +#endif + if( window ) { SDL_DestroyWindow( window );