From faefaa4669edfdbf829c65ec2cfa4d0b74b038a8 Mon Sep 17 00:00:00 2001 From: Robert Beckebans Date: Sun, 3 May 2020 13:39:38 +0200 Subject: [PATCH] Updated idRenderLog to support RenderDoc and Nvidia's Nsight --- RELEASE-NOTES.md | 2 + neo/renderer/OpenGL/RenderBackend_GL.cpp | 11 ++ neo/renderer/RenderBackend.cpp | 68 +++++----- neo/renderer/RenderBackend.h | 3 + neo/renderer/RenderLog.cpp | 150 +++++++++++++++++++--- neo/renderer/RenderLog.h | 12 +- neo/renderer/RenderSystem.h | 1 + neo/renderer/Vulkan/RenderBackend_VK.cpp | 151 ++++++++++++++++++++--- neo/renderer/Vulkan/qvk.h | 13 ++ 9 files changed, 341 insertions(+), 70 deletions(-) diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index b0251d18..a62e39f8 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -77,6 +77,8 @@ The main goal is that the new content looks the same in RBDOOM-3-BFG as in Blend * Improved Shadow Mapping performance by reducing the number of taps from 12 to 6 and keeping a good quality using dithering the result with Blue Noise magic by Alan Wolfe +* Updated idRenderLog to support RenderDoc and Nvidia's Nsight and only issue OpenGL or Vulkan debug commands if the debug extensions are detected. Reference: https://devblogs.nvidia.com/best-practices-gpu-performance-events/ + * Artistic Style C++ beautifier configuration has slightly changed to work closer to Clang Format's behaviour * Updated documentation regarding modding support in the README diff --git a/neo/renderer/OpenGL/RenderBackend_GL.cpp b/neo/renderer/OpenGL/RenderBackend_GL.cpp index 97a91d02..b7308a73 100644 --- a/neo/renderer/OpenGL/RenderBackend_GL.cpp +++ b/neo/renderer/OpenGL/RenderBackend_GL.cpp @@ -333,6 +333,17 @@ static void R_CheckPortableExtensions() common->Printf( "X..%s not found\n", "GL_GREMEDY_string_marker" ); } + // KHR_debug + glConfig.khronosDebugAvailable = GLEW_KHR_debug != 0; + if( glConfig.khronosDebugAvailable ) + { + common->Printf( "...using %s\n", "GLEW_KHR_debug" ); + } + else + { + common->Printf( "X..%s not found\n", "GLEW_KHR_debug" ); + } + // GL_ARB_framebuffer_object glConfig.framebufferObjectAvailable = GLEW_ARB_framebuffer_object != 0; if( glConfig.framebufferObjectAvailable ) diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 019933ff..de6961ec 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -930,7 +930,7 @@ void idRenderBackend::FillDepthBufferGeneric( const drawSurf_t* const* drawSurfs color[3] = 1.0f; } - renderLog.OpenBlock( shader->GetName() ); + renderLog.OpenBlock( shader->GetName(), colorMdGrey ); bool drawSolid = false; if( shader->Coverage() == MC_OPAQUE ) @@ -1095,7 +1095,7 @@ void idRenderBackend::FillDepthBufferFast( drawSurf_t** drawSurfs, int numDrawSu } renderLog.OpenMainBlock( MRB_FILL_DEPTH_BUFFER ); - renderLog.OpenBlock( "RB_FillDepthBufferFast" ); + renderLog.OpenBlock( "Render_FillDepthBufferFast", colorBlue ); // force MVP change on first surface currentSpace = NULL; @@ -1150,7 +1150,7 @@ void idRenderBackend::FillDepthBufferFast( drawSurf_t** drawSurfs, int numDrawSu currentSpace = surf->space; } - renderLog.OpenBlock( shader->GetName() ); + renderLog.OpenBlock( shader->GetName(), colorMdGrey ); if( surf->jointCache ) { @@ -1924,7 +1924,7 @@ void idRenderBackend::RenderInteractions( const drawSurf_t* surfList, const view // check for the fast path if( surfaceShader->GetFastPathBumpImage() && !r_skipInteractionFastPath.GetBool() ) { - renderLog.OpenBlock( surf->material->GetName() ); + renderLog.OpenBlock( surf->material->GetName(), colorMdGrey ); inter.bumpImage = surfaceShader->GetFastPathBumpImage(); inter.specularImage = surfaceShader->GetFastPathSpecularImage(); @@ -1936,7 +1936,7 @@ void idRenderBackend::RenderInteractions( const drawSurf_t* surfList, const view continue; } - renderLog.OpenBlock( surf->material->GetName() ); + renderLog.OpenBlock( surf->material->GetName(), colorMdGrey ); inter.bumpImage = NULL; inter.specularImage = NULL; @@ -2106,7 +2106,7 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr */ renderLog.OpenMainBlock( MRB_AMBIENT_PASS ); - renderLog.OpenBlock( "RB_AmbientPass" ); + renderLog.OpenBlock( "Render_AmbientPass", colorBlue ); // RB: not needed // GL_StartDepthPass( backEnd.viewDef->scissor ); @@ -2326,7 +2326,7 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr // check for the fast path if( surfaceMaterial->GetFastPathBumpImage() && !r_skipInteractionFastPath.GetBool() ) { - renderLog.OpenBlock( surfaceMaterial->GetName() ); + renderLog.OpenBlock( surfaceMaterial->GetName(), colorMdGrey ); inter.bumpImage = surfaceMaterial->GetFastPathBumpImage(); inter.specularImage = surfaceMaterial->GetFastPathSpecularImage(); @@ -2338,7 +2338,7 @@ void idRenderBackend::AmbientPass( const drawSurf_t* const* drawSurfs, int numDr continue; } - renderLog.OpenBlock( surfaceMaterial->GetName() ); + renderLog.OpenBlock( surfaceMaterial->GetName(), colorMdGrey ); //bool drawSolid = false; @@ -2677,7 +2677,7 @@ mask to be used by the following stencil shadow and draw interaction passes. */ void idRenderBackend::StencilSelectLight( const viewLight_t* vLight ) { - renderLog.OpenBlock( "Stencil Select" ); + renderLog.OpenBlock( "Stencil Select", colorPink ); // enable the light scissor if( !currentScissor.Equals( vLight->scissorRect ) && r_useScissor.GetBool() ) @@ -3420,7 +3420,7 @@ void idRenderBackend::DrawInteractions( const viewDef_t* _viewDef ) } renderLog.OpenMainBlock( MRB_DRAW_INTERACTIONS ); - renderLog.OpenBlock( "RB_DrawInteractions" ); + renderLog.OpenBlock( "Render_Interactions", colorYellow ); GL_SelectTexture( 0 ); @@ -3447,7 +3447,7 @@ void idRenderBackend::DrawInteractions( const viewDef_t* _viewDef ) } const idMaterial* lightShader = vLight->lightShader; - renderLog.OpenBlock( lightShader->GetName() ); + renderLog.OpenBlock( lightShader->GetName(), colorMdGrey ); // set the depth bounds for the whole light if( useLightDepthBounds ) @@ -3494,14 +3494,14 @@ void idRenderBackend::DrawInteractions( const viewDef_t* _viewDef ) if( vLight->localInteractions != NULL ) { - renderLog.OpenBlock( "Local Light Interactions" ); + renderLog.OpenBlock( "Local Light Interactions", colorPurple ); RenderInteractions( vLight->localInteractions, vLight, GLS_DEPTHFUNC_EQUAL, false, useLightDepthBounds ); renderLog.CloseBlock(); } if( vLight->globalInteractions != NULL ) { - renderLog.OpenBlock( "Global Light Interactions" ); + renderLog.OpenBlock( "Global Light Interactions", colorPurple ); RenderInteractions( vLight->globalInteractions, vLight, GLS_DEPTHFUNC_EQUAL, false, useLightDepthBounds ); renderLog.CloseBlock(); } @@ -3547,28 +3547,28 @@ void idRenderBackend::DrawInteractions( const viewDef_t* _viewDef ) if( vLight->globalShadows != NULL ) { - renderLog.OpenBlock( "Global Light Shadows" ); + renderLog.OpenBlock( "Global Light Shadows", colorBrown ); StencilShadowPass( vLight->globalShadows, vLight ); renderLog.CloseBlock(); } if( vLight->localInteractions != NULL ) { - renderLog.OpenBlock( "Local Light Interactions" ); + renderLog.OpenBlock( "Local Light Interactions", colorPurple ); RenderInteractions( vLight->localInteractions, vLight, GLS_DEPTHFUNC_EQUAL, performStencilTest, useLightDepthBounds ); renderLog.CloseBlock(); } if( vLight->localShadows != NULL ) { - renderLog.OpenBlock( "Local Light Shadows" ); + renderLog.OpenBlock( "Local Light Shadows", colorBrown ); StencilShadowPass( vLight->localShadows, vLight ); renderLog.CloseBlock(); } if( vLight->globalInteractions != NULL ) { - renderLog.OpenBlock( "Global Light Interactions" ); + renderLog.OpenBlock( "Global Light Interactions", colorPurple ); RenderInteractions( vLight->globalInteractions, vLight, GLS_DEPTHFUNC_EQUAL, performStencilTest, useLightDepthBounds ); renderLog.CloseBlock(); } @@ -3577,7 +3577,7 @@ void idRenderBackend::DrawInteractions( const viewDef_t* _viewDef ) if( vLight->translucentInteractions != NULL && !r_skipTranslucent.GetBool() ) { - renderLog.OpenBlock( "Translucent Interactions" ); + renderLog.OpenBlock( "Translucent Interactions", colorCyan ); // Disable the depth bounds test because translucent surfaces don't work with // the depth bounds tests since they did not write depth during the depth pass. @@ -3645,7 +3645,7 @@ int idRenderBackend::DrawShaderPasses( const drawSurf_t* const* const drawSurfs, return numDrawSurfs; } - renderLog.OpenBlock( "RB_DrawShaderPasses" ); + renderLog.OpenBlock( "Render_GenericShaderPasses", colorBlue ); GL_SelectTexture( 0 ); @@ -3703,7 +3703,7 @@ int idRenderBackend::DrawShaderPasses( const drawSurf_t* const* const drawSurfs, continue; } - renderLog.OpenBlock( shader->GetName() ); + renderLog.OpenBlock( shader->GetName(), colorMdGrey ); // determine the stereoDepth offset // guiStereoScreenOffset will always be zero for 3D views, so the != @@ -3833,7 +3833,7 @@ int idRenderBackend::DrawShaderPasses( const drawSurf_t* const* const drawSurfs, { continue; } - renderLog.OpenBlock( "New Shader Stage" ); + renderLog.OpenBlock( "Custom Renderproc Shader Stage", colorRed ); GL_State( stageGLState ); @@ -3913,7 +3913,7 @@ int idRenderBackend::DrawShaderPasses( const drawSurf_t* const* const drawSurfs, stageVertexColor_t svc = pStage->vertexColor; - renderLog.OpenBlock( "Old Shader Stage" ); + renderLog.OpenBlock( "Standard Shader Stage", colorGreen ); GL_Color( color ); if( surf->space->isGuiSurface ) @@ -4105,7 +4105,7 @@ void idRenderBackend::BlendLight( const drawSurf_t* drawSurfs, const drawSurf_t* { return; } - renderLog.OpenBlock( vLight->lightShader->GetName() ); + renderLog.OpenBlock( vLight->lightShader->GetName(), colorPink ); const idMaterial* lightShader = vLight->lightShader; const float* regs = vLight->shaderRegisters; @@ -4242,7 +4242,7 @@ idRenderBackend::FogPass */ void idRenderBackend::FogPass( const drawSurf_t* drawSurfs, const drawSurf_t* drawSurfs2, const viewLight_t* vLight ) { - renderLog.OpenBlock( vLight->lightShader->GetName() ); + renderLog.OpenBlock( vLight->lightShader->GetName(), colorCyan ); // find the current color and density of the fog const idMaterial* lightShader = vLight->lightShader; @@ -4346,7 +4346,7 @@ void idRenderBackend::FogAllLights() return; } renderLog.OpenMainBlock( MRB_FOG_ALL_LIGHTS ); - renderLog.OpenBlock( "RB_FogAllLights" ); + renderLog.OpenBlock( "Render_FogAllLights", colorBlue ); // force fog plane to recalculate currentSpace = NULL; @@ -4726,13 +4726,14 @@ void idRenderBackend::DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef return; } - // FIXME very expensive to enable this in subviews + // skip this in subviews because it is very expensive if( _viewDef->isSubview ) { return; } - RENDERLOG_PRINTF( "---------- RB_SSAO() ----------\n" ); + renderLog.OpenMainBlock( MRB_SSAO_PASS ); + renderLog.OpenBlock( "Render_SSAO", colorBlue ); #if 0 GL_CheckErrors(); @@ -4820,6 +4821,8 @@ void idRenderBackend::DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef // build hierarchical depth buffer if( r_useHierarchicalDepthBuffer.GetBool() ) { + renderLog.OpenBlock( "Render_HiZ", colorDkGrey ); + renderProgManager.BindShader_AmbientOcclusionMinify(); glClearColor( 0, 0, 0, 1 ); @@ -4859,17 +4862,18 @@ void idRenderBackend::DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef jitterTexScale[2] = 0; jitterTexScale[3] = 0; SetFragmentParm( RENDERPARM_JITTERTEXSCALE, jitterTexScale ); // rpJitterTexScale -#if 1 + float screenCorrectionParm[4]; screenCorrectionParm[0] = 1.0f / width; screenCorrectionParm[1] = 1.0f / height; screenCorrectionParm[2] = width; screenCorrectionParm[3] = height; SetFragmentParm( RENDERPARM_SCREENCORRECTIONFACTOR, screenCorrectionParm ); // rpScreenCorrectionFactor -#endif DrawElementsWithCounters( &unitSquareSurface ); } + + renderLog.CloseBlock(); } // set the window clipping @@ -4878,7 +4882,6 @@ void idRenderBackend::DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS | GLS_CULL_TWOSIDED ); - if( downModulateScreen ) { if( r_ssaoFiltering.GetBool() ) @@ -5056,6 +5059,9 @@ void idRenderBackend::DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef GL_State( GLS_DEFAULT ); + renderLog.CloseBlock(); + renderLog.CloseMainBlock(); + //GL_CheckErrors(); #endif } @@ -5444,7 +5450,7 @@ idRenderBackend::DrawViewInternal */ void idRenderBackend::DrawViewInternal( const viewDef_t* _viewDef, const int stereoEye ) { - renderLog.OpenBlock( "RB_DrawViewInternal" ); + renderLog.OpenBlock( "Render_DrawViewInternal", colorRed ); //------------------------------------------------- // guis can wind up referencing purged images that need to be loaded. diff --git a/neo/renderer/RenderBackend.h b/neo/renderer/RenderBackend.h index 80e1f23f..265bd525 100644 --- a/neo/renderer/RenderBackend.h +++ b/neo/renderer/RenderBackend.h @@ -160,6 +160,9 @@ struct vulkanContext_t idList< const char* > deviceExtensions; idList< const char* > validationLayers; + bool debugMarkerSupportAvailable; + bool debugUtilsSupportAvailable; + // selected GPU gpuInfo_t* gpu; diff --git a/neo/renderer/RenderLog.cpp b/neo/renderer/RenderLog.cpp index 9bd69b64..0d47b3c8 100644 --- a/neo/renderer/RenderLog.cpp +++ b/neo/renderer/RenderLog.cpp @@ -3,7 +3,7 @@ Doom 3 BFG Edition GPL Source Code Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. -Copyright (C) 2013 Robert Beckebans +Copyright (C) 2013-2020 Robert Beckebans This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). @@ -47,22 +47,28 @@ const char* renderLogMainBlockLabels[] = ASSERT_ENUM_STRING( MRB_NONE, 0 ), ASSERT_ENUM_STRING( MRB_BEGIN_DRAWING_VIEW, 1 ), ASSERT_ENUM_STRING( MRB_FILL_DEPTH_BUFFER, 2 ), - ASSERT_ENUM_STRING( MRB_AMBIENT_PASS, 3 ), // RB - ASSERT_ENUM_STRING( MRB_DRAW_INTERACTIONS, 4 ), - ASSERT_ENUM_STRING( MRB_DRAW_SHADER_PASSES, 5 ), - ASSERT_ENUM_STRING( MRB_FOG_ALL_LIGHTS, 6 ), - ASSERT_ENUM_STRING( MRB_DRAW_SHADER_PASSES_POST, 7 ), - ASSERT_ENUM_STRING( MRB_DRAW_DEBUG_TOOLS, 8 ), - ASSERT_ENUM_STRING( MRB_CAPTURE_COLORBUFFER, 9 ), - ASSERT_ENUM_STRING( MRB_POSTPROCESS, 10 ), - ASSERT_ENUM_STRING( MRB_GPU_SYNC, 11 ), - ASSERT_ENUM_STRING( MRB_END_FRAME, 12 ), - ASSERT_ENUM_STRING( MRB_BINK_FRAME, 13 ), - ASSERT_ENUM_STRING( MRB_BINK_NEXT_FRAME, 14 ), - ASSERT_ENUM_STRING( MRB_TOTAL, 15 ), - ASSERT_ENUM_STRING( MRB_MAX, 16 ) + ASSERT_ENUM_STRING( MRB_FILL_GEOMETRY_BUFFER, 3 ), // RB + ASSERT_ENUM_STRING( MRB_SSAO_PASS, 4 ), // RB + ASSERT_ENUM_STRING( MRB_AMBIENT_PASS, 5 ), // RB + ASSERT_ENUM_STRING( MRB_DRAW_INTERACTIONS, 6 ), + ASSERT_ENUM_STRING( MRB_DRAW_SHADER_PASSES, 7 ), + ASSERT_ENUM_STRING( MRB_FOG_ALL_LIGHTS, 8 ), + ASSERT_ENUM_STRING( MRB_DRAW_SHADER_PASSES_POST, 9 ), + ASSERT_ENUM_STRING( MRB_DRAW_DEBUG_TOOLS, 10 ), + ASSERT_ENUM_STRING( MRB_CAPTURE_COLORBUFFER, 11 ), + ASSERT_ENUM_STRING( MRB_POSTPROCESS, 12 ), + ASSERT_ENUM_STRING( MRB_GPU_SYNC, 13 ), + ASSERT_ENUM_STRING( MRB_END_FRAME, 14 ), + ASSERT_ENUM_STRING( MRB_BINK_FRAME, 15 ), + ASSERT_ENUM_STRING( MRB_BINK_NEXT_FRAME, 16 ), + ASSERT_ENUM_STRING( MRB_TOTAL, 17 ), + ASSERT_ENUM_STRING( MRB_MAX, 18 ) }; +#if !defined(USE_VULKAN) + static GLuint renderLogMainBlockTimeQueryIds[MRB_MAX]; +#endif + extern uint64 Sys_Microseconds(); /* ================================================================================================ @@ -103,8 +109,45 @@ PC_BeginNamedEvent FIXME: this is not thread safe on the PC ======================== */ -void PC_BeginNamedEvent( const char* szName, ... ) +void PC_BeginNamedEvent( const char* szName, const idVec4& color ) { +#if defined( USE_VULKAN ) + + // start an annotated group of calls under the this name + if( vkcontext.debugMarkerSupportAvailable ) + { + VkDebugMarkerMarkerInfoEXT label = {}; + label.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT; + label.pMarkerName = szName; + label.color[0] = color.x; + label.color[1] = color.y; + label.color[2] = color.z; + label.color[3] = color.w; + + qvkCmdDebugMarkerBeginEXT( vkcontext.commandBuffer[ vkcontext.frameParity ], &label ); + } + else if( vkcontext.debugUtilsSupportAvailable ) + { + VkDebugUtilsLabelEXT label = {}; + label.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT; + label.pLabelName = szName; + label.color[0] = color.x; + label.color[1] = color.y; + label.color[2] = color.z; + label.color[3] = color.w; + + qvkCmdBeginDebugUtilsLabelEXT( vkcontext.commandBuffer[ vkcontext.frameParity ], &label ); + } +#else + // RB: colors are not supported in OpenGL + + // only do this if RBDOOM-3-BFG was started by RenderDoc or some similar tool + if( glConfig.gremedyStringMarkerAvailable && glConfig.khronosDebugAvailable ) + { + glPushDebugGroup( GL_DEBUG_SOURCE_APPLICATION_ARB, 0, GLsizei( strlen( szName ) ), szName ); + } +#endif + #if 0 if( !r_pix.GetBool() ) { @@ -150,6 +193,23 @@ PC_EndNamedEvent */ void PC_EndNamedEvent() { +#if defined( USE_VULKAN ) + if( vkcontext.debugMarkerSupportAvailable ) + { + qvkCmdDebugMarkerEndEXT( vkcontext.commandBuffer[ vkcontext.frameParity ] ); + } + else if( vkcontext.debugUtilsSupportAvailable ) + { + qvkCmdEndDebugUtilsLabelEXT( vkcontext.commandBuffer[ vkcontext.frameParity ] ); + } +#else + // only do this if RBDOOM-3-BFG was started by RenderDoc or some similar tool + if( glConfig.gremedyStringMarkerAvailable && glConfig.khronosDebugAvailable ) + { + glPopDebugGroup(); + } +#endif + #if 0 if( !r_pix.GetBool() ) { @@ -529,14 +589,67 @@ void idRenderLog::LogCloseBlock( renderLogIndentLabel_t label ) #else // !STUB_RENDER_LOG +// RB begin +/* +======================== +idRenderLog::idRenderLog +======================== +*/ +idRenderLog::idRenderLog() +{ +#if !defined(USE_VULKAN) + memset( renderLogMainBlockTimeQueryIds, 0, sizeof( renderLogMainBlockTimeQueryIds ) ); +#endif +} + +#if 0 + +/* +======================== +idRenderLog::OpenMainBlock +======================== +*/ +void idRenderLog::OpenMainBlock( renderLogMainBlock_t block ) +{ +#if defined( USE_VULKAN ) + // TODO +#else + if( glConfig.timerQueryAvailable ) + { + if( renderLogMainBlockTimeQueryIds[block] == 0 ) + { + glGenQueries( 1, &renderLogMainBlockTimeQueryIds[block] ); + } + + glBeginQuery( GL_TIME_ELAPSED_EXT, renderLogMainBlockTimeQueryIds[block] ); + } +#endif +} + +/* +======================== +idRenderLog::CloseMainBlock +======================== +*/ +void idRenderLog::CloseMainBlock() +{ +#if defined( USE_VULKAN ) + // TODO +#else + glEndQuery( GL_TIME_ELAPSED_EXT ); +#endif +} + +#endif + /* ======================== idRenderLog::OpenBlock ======================== */ -void idRenderLog::OpenBlock( const char* label ) +void idRenderLog::OpenBlock( const char* label, const idVec4& color ) { - PC_BeginNamedEvent( label ); + PC_BeginNamedEvent( label, color ); } /* @@ -548,5 +661,6 @@ void idRenderLog::CloseBlock() { PC_EndNamedEvent(); } +// RB end #endif // !STUB_RENDER_LOG diff --git a/neo/renderer/RenderLog.h b/neo/renderer/RenderLog.h index 3bf1b774..b8c1bc32 100644 --- a/neo/renderer/RenderLog.h +++ b/neo/renderer/RenderLog.h @@ -3,6 +3,7 @@ Doom 3 BFG Edition GPL Source Code Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. +Copyright (C) 2013-2020 Robert Beckebans This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). @@ -34,7 +35,7 @@ Contains the RenderLog declaration. ================================================================================================ */ -#if defined(ID_RETAIL) && !defined(ID_RETAIL_INTERNAL) +#if 1 //defined(ID_RETAIL) && !defined(ID_RETAIL_INTERNAL) #define STUB_RENDER_LOG #endif @@ -43,6 +44,8 @@ enum renderLogMainBlock_t MRB_NONE, MRB_BEGIN_DRAWING_VIEW, MRB_FILL_DEPTH_BUFFER, + MRB_FILL_GEOMETRY_BUFFER, + MRB_SSAO_PASS, MRB_AMBIENT_PASS, MRB_DRAW_INTERACTIONS, MRB_DRAW_SHADER_PASSES, @@ -172,12 +175,15 @@ ID_INLINE void idRenderLog::Outdent( renderLogIndentLabel_t label ) ================================================ idRenderLog stubbed version for the SPUs and high performance rendering in retail builds. + +// Performance Events abstraction layer for OpenGL, Vulkan, DX12 +// see https://devblogs.nvidia.com/best-practices-gpu-performance-events/ ================================================ */ class idRenderLog { public: - idRenderLog() {} + idRenderLog(); void StartFrame() {} void EndFrame() {} @@ -187,7 +193,7 @@ public: return 0; } - void OpenBlock( const char* label ); + void OpenBlock( const char* label, const idVec4& color = colorBlack ); void CloseBlock(); void OpenMainBlock( renderLogMainBlock_t block ) {} void CloseMainBlock() {} diff --git a/neo/renderer/RenderSystem.h b/neo/renderer/RenderSystem.h index 257add68..8a89a324 100644 --- a/neo/renderer/RenderSystem.h +++ b/neo/renderer/RenderSystem.h @@ -209,6 +209,7 @@ struct glconfig_t // RB begin bool gremedyStringMarkerAvailable; + bool khronosDebugAvailable; bool vertexHalfFloatAvailable; bool framebufferObjectAvailable; diff --git a/neo/renderer/Vulkan/RenderBackend_VK.cpp b/neo/renderer/Vulkan/RenderBackend_VK.cpp index 43f5ff91..82429b03 100644 --- a/neo/renderer/Vulkan/RenderBackend_VK.cpp +++ b/neo/renderer/Vulkan/RenderBackend_VK.cpp @@ -3,8 +3,8 @@ Doom 3 BFG Edition GPL Source Code Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. -Copyright (C) 2013-2019 Robert Beckebans Copyright (C) 2016-2017 Dustin Land +Copyright (C) 2018-2020 Robert Beckebans This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). @@ -31,9 +31,21 @@ If you have questions concerning this license or the applicable additional terms #pragma hdrstop #include "precompiled.h" -#if 0 // defined(__linux__) - #include "../../sys/posix/posix_public.h" -#endif +// VK_EXT_debug_marker +PFN_vkDebugMarkerSetObjectTagEXT qvkDebugMarkerSetObjectTagEXT = VK_NULL_HANDLE; +PFN_vkDebugMarkerSetObjectNameEXT qvkDebugMarkerSetObjectNameEXT = VK_NULL_HANDLE; +PFN_vkCmdDebugMarkerBeginEXT qvkCmdDebugMarkerBeginEXT = VK_NULL_HANDLE; +PFN_vkCmdDebugMarkerEndEXT qvkCmdDebugMarkerEndEXT = VK_NULL_HANDLE; +PFN_vkCmdDebugMarkerInsertEXT qvkCmdDebugMarkerInsertEXT = VK_NULL_HANDLE; + +// VK_EXT_debug_utils +PFN_vkQueueBeginDebugUtilsLabelEXT qvkQueueBeginDebugUtilsLabelEXT = VK_NULL_HANDLE; +PFN_vkQueueEndDebugUtilsLabelEXT qvkQueueEndDebugUtilsLabelEXT = VK_NULL_HANDLE; +PFN_vkCmdBeginDebugUtilsLabelEXT qvkCmdBeginDebugUtilsLabelEXT = VK_NULL_HANDLE; +PFN_vkCmdEndDebugUtilsLabelEXT qvkCmdEndDebugUtilsLabelEXT = VK_NULL_HANDLE; +PFN_vkCmdInsertDebugUtilsLabelEXT qvkCmdInsertDebugUtilsLabelEXT = VK_NULL_HANDLE; + + #include "../RenderCommon.h" #include "../RenderBackend.h" @@ -68,12 +80,6 @@ static const char* g_debugInstanceExtensions[ g_numDebugInstanceExtensions ] = VK_EXT_DEBUG_REPORT_EXTENSION_NAME }; -static const int g_numDeviceExtensions = 1; -static const char* g_deviceExtensions[ g_numDeviceExtensions ] = -{ - VK_KHR_SWAPCHAIN_EXTENSION_NAME -}; - static const int g_numValidationLayers = 1; static const char* g_validationLayers[ g_numValidationLayers ] = { @@ -268,11 +274,6 @@ static void CreateVulkanInstance() } #endif - for( int i = 0; i < g_numDeviceExtensions; ++i ) - { - vkcontext.deviceExtensions.Append( g_deviceExtensions[ i ] ); - } - if( enableLayers ) { for( int i = 0; i < g_numDebugInstanceExtensions; ++i ) @@ -466,6 +467,7 @@ static void CreateSurface() CheckPhysicalDeviceExtensionSupport ============= */ +/* static bool CheckPhysicalDeviceExtensionSupport( gpuInfo_t& gpu, idList< const char* >& requiredExt ) { int required = requiredExt.Num(); @@ -485,6 +487,89 @@ static bool CheckPhysicalDeviceExtensionSupport( gpuInfo_t& gpu, idList< const c return available == required; } +*/ + +/* +============= +PopulateDeviceExtensions +============= +*/ +static void PopulateDeviceExtensions( const idList< VkExtensionProperties >& extensionProps, idList< const char* >& extensions ) +{ + extensions.Clear(); + extensions.Append( VK_KHR_SWAPCHAIN_EXTENSION_NAME ); + + const int numExtensions = extensionProps.Num(); + const bool enableLayers = r_vkEnableValidationLayers.GetBool(); + + for( int i = 0; i < numExtensions; ++i ) + { + //idLib::Printf( "Checking Vulkan device extension [%s]\n", extensionProps[ i ].extensionName ); + + if( idStr::Icmp( extensionProps[ i ].extensionName, VK_EXT_DEBUG_MARKER_EXTENSION_NAME ) == 0 && enableLayers ) + { + extensions.AddUnique( VK_EXT_DEBUG_MARKER_EXTENSION_NAME ); + continue; + } + + if( idStr::Icmp( extensionProps[ i ].extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME ) == 0 && enableLayers ) + { + extensions.AddUnique( VK_EXT_DEBUG_UTILS_EXTENSION_NAME ); + continue; + } + } +} + +/* +============= +CheckDeviceExtensionSupport +============= +*/ +static bool CheckDeviceExtensionSupport( const idList< VkExtensionProperties >& extensionProps, const idList< const char* >& requiredExt ) +{ + int required = requiredExt.Num(); + int available = 0; + + for( int i = 0; i < requiredExt.Num(); ++i ) + { + for( int j = 0; j < extensionProps.Num(); ++j ) + { + if( idStr::Icmp( requiredExt[ i ], extensionProps[ j ].extensionName ) == 0 ) + { + available++; + break; + } + } + } + + return available == required; +} + +/* +============= +EnableDeviceExtensionFeatures +============= +*/ +static void EnableDeviceExtensionFeatures( const idList< const char* >& extensions ) +{ + vkcontext.debugMarkerSupportAvailable = false; + vkcontext.debugUtilsSupportAvailable = false; + + for( int i = 0; i < extensions.Num(); ++i ) + { + if( idStr::Icmp( extensions[ i ], VK_EXT_DEBUG_MARKER_EXTENSION_NAME ) == 0 ) + { + idLib::Printf( "Using Vulkan device extension [%s]\n", VK_EXT_DEBUG_MARKER_EXTENSION_NAME ); + vkcontext.debugMarkerSupportAvailable = true; + } + + if( idStr::Icmp( extensions[ i ], VK_EXT_DEBUG_UTILS_EXTENSION_NAME ) == 0 ) + { + idLib::Printf( "Using Vulkan device extension [%s]\n", VK_EXT_DEBUG_UTILS_EXTENSION_NAME ); + vkcontext.debugUtilsSupportAvailable = true; + } + } +} /* ============= @@ -499,10 +584,10 @@ static void SelectPhysicalDevice() { gpuInfo_t& gpu = vkcontext.gpus[ i ]; - int graphicsIdx = -1; - int presentIdx = -1; + idList< const char* > extensions; + PopulateDeviceExtensions( gpu.extensionProps, extensions ); - if( !CheckPhysicalDeviceExtensionSupport( gpu, vkcontext.deviceExtensions ) ) + if( !CheckDeviceExtensionSupport( gpu.extensionProps, extensions ) ) { continue; } @@ -517,6 +602,9 @@ static void SelectPhysicalDevice() continue; } + int graphicsIdx = -1; + int presentIdx = -1; + // Find graphics queue family for( int j = 0; j < gpu.queueFamilyProps.Num(); ++j ) { @@ -560,6 +648,9 @@ static void SelectPhysicalDevice() vkcontext.presentFamilyIdx = presentIdx; vkcontext.physicalDevice = gpu.device; vkcontext.gpu = &gpu; + vkcontext.deviceExtensions = extensions; + + EnableDeviceExtensionFeatures( vkcontext.deviceExtensions ); vkGetPhysicalDeviceFeatures( vkcontext.physicalDevice, &vkcontext.physicalDeviceFeatures ); @@ -651,6 +742,30 @@ static void CreateLogicalDeviceAndQueues() vkGetDeviceQueue( vkcontext.device, vkcontext.graphicsFamilyIdx, 0, &vkcontext.graphicsQueue ); vkGetDeviceQueue( vkcontext.device, vkcontext.presentFamilyIdx, 0, &vkcontext.presentQueue ); + + if( vkcontext.debugMarkerSupportAvailable ) + { + qvkDebugMarkerSetObjectTagEXT = ( PFN_vkDebugMarkerSetObjectTagEXT ) vkGetDeviceProcAddr( vkcontext.device, "vkDebugMarkerSetObjectTagEXT" ); + qvkDebugMarkerSetObjectNameEXT = ( PFN_vkDebugMarkerSetObjectNameEXT ) vkGetDeviceProcAddr( vkcontext.device, "vkDebugMarkerSetObjectNameEXT" ); + + qvkCmdDebugMarkerBeginEXT = ( PFN_vkCmdDebugMarkerBeginEXT )vkGetDeviceProcAddr( vkcontext.device, "vkCmdDebugMarkerBeginEXT" ); + qvkCmdDebugMarkerEndEXT = ( PFN_vkCmdDebugMarkerEndEXT )vkGetDeviceProcAddr( vkcontext.device, "vkCmdDebugMarkerEndEXT" ); + qvkCmdDebugMarkerInsertEXT = ( PFN_vkCmdDebugMarkerInsertEXT ) vkGetDeviceProcAddr( vkcontext.device, "vkCmdDebugMarkerInsertEXT" ); + + // TODO + + //VK_RegisterObjectForDebug( reinterpret_cast< uint64 >( vkcontext.graphicsQueue ), "graphics_queue", VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT ); + //VK_RegisterObjectForDebug( reinterpret_cast< uint64 >( vkcontext.presentQueue ), "present_queue", VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT ); + } + + if( vkcontext.debugUtilsSupportAvailable ) + { + qvkQueueBeginDebugUtilsLabelEXT = ( PFN_vkQueueBeginDebugUtilsLabelEXT )vkGetDeviceProcAddr( vkcontext.device, "vkQueueBeginDebugUtilsLabelEXT" ); + qvkQueueEndDebugUtilsLabelEXT = ( PFN_vkQueueEndDebugUtilsLabelEXT )vkGetDeviceProcAddr( vkcontext.device, "vkQueueEndDebugUtilsLabelEXT" ); + qvkCmdBeginDebugUtilsLabelEXT = ( PFN_vkCmdBeginDebugUtilsLabelEXT )vkGetDeviceProcAddr( vkcontext.device, "vkCmdBeginDebugUtilsLabelEXT" ); + qvkCmdEndDebugUtilsLabelEXT = ( PFN_vkCmdEndDebugUtilsLabelEXT )vkGetDeviceProcAddr( vkcontext.device, "vkCmdEndDebugUtilsLabelEXT" ); + qvkCmdInsertDebugUtilsLabelEXT = ( PFN_vkCmdInsertDebugUtilsLabelEXT )vkGetDeviceProcAddr( vkcontext.device, "vkCmdInsertDebugUtilsLabelEXT" ); + } } /* diff --git a/neo/renderer/Vulkan/qvk.h b/neo/renderer/Vulkan/qvk.h index f14be97b..ced1d88e 100644 --- a/neo/renderer/Vulkan/qvk.h +++ b/neo/renderer/Vulkan/qvk.h @@ -79,6 +79,19 @@ static const int MAX_DESC_SET_UNIFORMS = 48; static const int MAX_IMAGE_PARMS = 16; static const int MAX_UBO_PARMS = 2; +// VK_EXT_debug_marker +extern PFN_vkDebugMarkerSetObjectTagEXT qvkDebugMarkerSetObjectTagEXT; +extern PFN_vkDebugMarkerSetObjectNameEXT qvkDebugMarkerSetObjectNameEXT; +extern PFN_vkCmdDebugMarkerBeginEXT qvkCmdDebugMarkerBeginEXT; +extern PFN_vkCmdDebugMarkerEndEXT qvkCmdDebugMarkerEndEXT; +extern PFN_vkCmdDebugMarkerInsertEXT qvkCmdDebugMarkerInsertEXT; + +// VK_EXT_debug_utils +extern PFN_vkQueueBeginDebugUtilsLabelEXT qvkQueueBeginDebugUtilsLabelEXT; +extern PFN_vkQueueEndDebugUtilsLabelEXT qvkQueueEndDebugUtilsLabelEXT; +extern PFN_vkCmdBeginDebugUtilsLabelEXT qvkCmdBeginDebugUtilsLabelEXT; +extern PFN_vkCmdEndDebugUtilsLabelEXT qvkCmdEndDebugUtilsLabelEXT; +extern PFN_vkCmdInsertDebugUtilsLabelEXT qvkCmdInsertDebugUtilsLabelEXT; #endif