summaryrefslogtreecommitdiff
path: root/materialsystem/occlusionquerymgr.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /materialsystem/occlusionquerymgr.cpp
downloadarchived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz
archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip
Diffstat (limited to 'materialsystem/occlusionquerymgr.cpp')
-rw-r--r--materialsystem/occlusionquerymgr.cpp258
1 files changed, 258 insertions, 0 deletions
diff --git a/materialsystem/occlusionquerymgr.cpp b/materialsystem/occlusionquerymgr.cpp
new file mode 100644
index 0000000..5ee497e
--- /dev/null
+++ b/materialsystem/occlusionquerymgr.cpp
@@ -0,0 +1,258 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================
+
+#include "pch_materialsystem.h"
+
+#define MATSYS_INTERNAL
+
+#include "occlusionquerymgr.h"
+#include "imaterialsysteminternal.h"
+#include "imatrendercontextinternal.h"
+
+// NOTE: This must be the last file included!!!
+#include "tier0/memdbgon.h"
+
+
+//-----------------------------------------------------------------------------
+// Singleton
+//-----------------------------------------------------------------------------
+static COcclusionQueryMgr s_OcclusionQueryMgr;
+COcclusionQueryMgr *g_pOcclusionQueryMgr = &s_OcclusionQueryMgr;
+
+
+//-----------------------------------------------------------------------------
+// Constructor
+//-----------------------------------------------------------------------------
+COcclusionQueryMgr::COcclusionQueryMgr()
+{
+ m_nFrameCount = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Allocate and delete query objects.
+//-----------------------------------------------------------------------------
+OcclusionQueryObjectHandle_t COcclusionQueryMgr::CreateOcclusionQueryObject( )
+{
+ m_Mutex.Lock();
+ int h = m_OcclusionQueryObjects.AddToTail();
+ m_Mutex.Unlock();
+ return (OcclusionQueryObjectHandle_t)h;
+}
+
+void COcclusionQueryMgr::OnCreateOcclusionQueryObject( OcclusionQueryObjectHandle_t h )
+{
+ for ( int i = 0; i < COUNT_OCCLUSION_QUERY_STACK; i++)
+ {
+ m_OcclusionQueryObjects[(int)h].m_QueryHandle[i] = g_pShaderAPI->CreateOcclusionQueryObject( );
+ }
+}
+
+// Flushes an outstanding query
+// HEY - Be very careful using this method - it causes a full pipeline flush/stall!
+void COcclusionQueryMgr::FlushQuery( OcclusionQueryObjectHandle_t hOcclusionQuery, int nIndex )
+{
+ // Flush out any previous queries
+ int h = (int)hOcclusionQuery;
+ if ( m_OcclusionQueryObjects[h].m_bHasBeenIssued[nIndex] )
+ {
+ ShaderAPIOcclusionQuery_t hQuery = m_OcclusionQueryObjects[h].m_QueryHandle[nIndex];
+
+ while ( OCCLUSION_QUERY_RESULT_PENDING == g_pShaderAPI->OcclusionQuery_GetNumPixelsRendered( hQuery, true ) )
+ continue;
+ }
+}
+
+void COcclusionQueryMgr::DestroyOcclusionQueryObject( OcclusionQueryObjectHandle_t hOcclusionQuery )
+{
+ int h = (int)hOcclusionQuery;
+ Assert( m_OcclusionQueryObjects.IsValidIndex( h ) );
+ if ( m_OcclusionQueryObjects.IsValidIndex( h ) )
+ {
+ for ( int i = 0; i < COUNT_OCCLUSION_QUERY_STACK; i++)
+ {
+ if ( m_OcclusionQueryObjects[h].m_QueryHandle[i] != INVALID_SHADERAPI_OCCLUSION_QUERY_HANDLE )
+ {
+ g_pShaderAPI->DestroyOcclusionQueryObject( m_OcclusionQueryObjects[h].m_QueryHandle[i] );
+ }
+ }
+ m_Mutex.Lock();
+ m_OcclusionQueryObjects.Remove( h );
+ m_Mutex.Unlock();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Advance frame
+//-----------------------------------------------------------------------------
+void COcclusionQueryMgr::AdvanceFrame()
+{
+ ++m_nFrameCount;
+}
+
+
+//-----------------------------------------------------------------------------
+// Alt-tab support
+// NOTE: This doesn't queue anything up
+//-----------------------------------------------------------------------------
+void COcclusionQueryMgr::AllocOcclusionQueryObjects( void )
+{
+ FOR_EACH_LL( m_OcclusionQueryObjects, iterator )
+ {
+ for ( int i = 0; i < COUNT_OCCLUSION_QUERY_STACK; i++)
+ {
+ m_OcclusionQueryObjects[iterator].m_QueryHandle[i] = g_pShaderAPI->CreateOcclusionQueryObject();
+ m_OcclusionQueryObjects[iterator].m_bHasBeenIssued[i] = false; // any in-flight queries are never returning
+ }
+ }
+}
+
+void COcclusionQueryMgr::FreeOcclusionQueryObjects( void )
+{
+ FOR_EACH_LL( m_OcclusionQueryObjects, iterator )
+ {
+ for ( int i = 0; i < COUNT_OCCLUSION_QUERY_STACK; i++)
+ {
+ if ( m_OcclusionQueryObjects[iterator].m_QueryHandle[i] != INVALID_SHADERAPI_OCCLUSION_QUERY_HANDLE )
+ {
+ g_pShaderAPI->DestroyOcclusionQueryObject( m_OcclusionQueryObjects[iterator].m_QueryHandle[i] );
+ m_OcclusionQueryObjects[iterator].m_QueryHandle[i] = INVALID_SHADERAPI_OCCLUSION_QUERY_HANDLE;
+ m_OcclusionQueryObjects[iterator].m_bHasBeenIssued[i] = false;
+ }
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Used to make the handle think it's never had a successful query before
+//-----------------------------------------------------------------------------
+void COcclusionQueryMgr::ResetOcclusionQueryObject( OcclusionQueryObjectHandle_t hOcclusionQuery )
+{
+ int h = (int)hOcclusionQuery;
+ Assert( m_OcclusionQueryObjects.IsValidIndex( h ) );
+ if ( m_OcclusionQueryObjects.IsValidIndex( h ) )
+ {
+ // Forget we've issued any previous queries - there's no need to flush them.
+ for ( int i = 0; i < COUNT_OCCLUSION_QUERY_STACK; i++)
+ {
+ m_OcclusionQueryObjects[h].m_bHasBeenIssued[i] = false;
+ }
+
+ m_OcclusionQueryObjects[h].m_LastResult = -1;
+ m_OcclusionQueryObjects[h].m_nFrameIssued = -1;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Bracket drawing with begin and end so that we can get counts next frame.
+//-----------------------------------------------------------------------------
+void COcclusionQueryMgr::BeginOcclusionQueryDrawing( OcclusionQueryObjectHandle_t hOcclusionQuery )
+{
+ int h = (int)hOcclusionQuery;
+ Assert( m_OcclusionQueryObjects.IsValidIndex( h ) );
+ if ( m_OcclusionQueryObjects.IsValidIndex( h ) )
+ {
+ int nCurrent = m_OcclusionQueryObjects[h].m_nCurrentIssue;
+ ShaderAPIOcclusionQuery_t hQuery = m_OcclusionQueryObjects[h].m_QueryHandle[nCurrent];
+ if ( hQuery != INVALID_SHADERAPI_OCCLUSION_QUERY_HANDLE )
+ {
+ // If it's been issued, but we haven't gotten a result when we polled last time,
+ // try polling one last time, since we can't poll again after we issue again.
+ if ( m_OcclusionQueryObjects[h].m_bHasBeenIssued[nCurrent] )
+ {
+ int nPixels = g_pShaderAPI->OcclusionQuery_GetNumPixelsRendered( hQuery, false );
+ if ( ( nPixels == OCCLUSION_QUERY_RESULT_PENDING ) && ( m_OcclusionQueryObjects[h].m_nFrameIssued == m_nFrameCount ) )
+ {
+ static int s_nWarnCount = 0;
+ if ( s_nWarnCount++ < 5 )
+ {
+ DevWarning( "blocking issue in occlusion queries! Grab brian!\n" );
+ }
+ }
+ while( !OCCLUSION_QUERY_FINISHED( nPixels ) )
+ {
+ // We're going to reuse this query, so issue a flush to force the query results to come back.
+ nPixels = g_pShaderAPI->OcclusionQuery_GetNumPixelsRendered( hQuery, true );
+ }
+ if ( nPixels >= 0 )
+ {
+ m_OcclusionQueryObjects[h].m_LastResult = nPixels;
+ }
+ m_OcclusionQueryObjects[h].m_bHasBeenIssued[nCurrent] = false;
+ }
+ g_pShaderAPI->BeginOcclusionQueryDrawing( hQuery );
+ }
+ }
+}
+
+
+void COcclusionQueryMgr::EndOcclusionQueryDrawing( OcclusionQueryObjectHandle_t hOcclusionQuery )
+{
+ int h = (int)hOcclusionQuery;
+ Assert( m_OcclusionQueryObjects.IsValidIndex( h ) );
+ if ( m_OcclusionQueryObjects.IsValidIndex( h ) )
+ {
+ int nCurrent = m_OcclusionQueryObjects[h].m_nCurrentIssue;
+ ShaderAPIOcclusionQuery_t hQuery = m_OcclusionQueryObjects[h].m_QueryHandle[nCurrent];
+ if ( hQuery != INVALID_SHADERAPI_OCCLUSION_QUERY_HANDLE )
+ {
+ g_pShaderAPI->EndOcclusionQueryDrawing( hQuery );
+
+ m_OcclusionQueryObjects[h].m_bHasBeenIssued[nCurrent] = true;
+ m_OcclusionQueryObjects[h].m_nFrameIssued = m_nFrameCount;
+
+ nCurrent = ( nCurrent + 1 ) % COUNT_OCCLUSION_QUERY_STACK;
+ m_OcclusionQueryObjects[h].m_nCurrentIssue = nCurrent;
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Get the number of pixels rendered between begin and end on an earlier frame.
+// Calling this in the same frame is a huge perf hit!
+//-----------------------------------------------------------------------------
+void COcclusionQueryMgr::OcclusionQuery_IssueNumPixelsRenderedQuery( OcclusionQueryObjectHandle_t hOcclusionQuery )
+{
+ int h = (int)hOcclusionQuery;
+ Assert( m_OcclusionQueryObjects.IsValidIndex( h ) );
+ if ( m_OcclusionQueryObjects.IsValidIndex( h ) )
+ {
+ for( int i = 0; i < COUNT_OCCLUSION_QUERY_STACK; i++ )
+ {
+ int nIndex = ( m_OcclusionQueryObjects[h].m_nCurrentIssue + i ) % COUNT_OCCLUSION_QUERY_STACK;
+ ShaderAPIOcclusionQuery_t hQuery = m_OcclusionQueryObjects[h].m_QueryHandle[nIndex];
+ if ( hQuery != INVALID_SHADERAPI_OCCLUSION_QUERY_HANDLE && m_OcclusionQueryObjects[h].m_bHasBeenIssued[nIndex] )
+ {
+ int nPixels = g_pShaderAPI->OcclusionQuery_GetNumPixelsRendered( hQuery );
+ if ( nPixels == OCCLUSION_QUERY_RESULT_ERROR )
+ {
+ // In GL mode, it's possible for queries to fail (say when mat_queue_mode is toggled). In this case, just clear m_bHasBeenIssued and forget we ever issued this query.
+ m_OcclusionQueryObjects[h].m_bHasBeenIssued[nIndex] = false;
+ }
+ else if ( nPixels >= 0 )
+ {
+ m_OcclusionQueryObjects[h].m_LastResult = nPixels;
+ m_OcclusionQueryObjects[h].m_bHasBeenIssued[nIndex] = false;
+ }
+ }
+ }
+ }
+}
+
+int COcclusionQueryMgr::OcclusionQuery_GetNumPixelsRendered( OcclusionQueryObjectHandle_t h, bool bDoQuery )
+{
+ if ( bDoQuery )
+ {
+ OcclusionQuery_IssueNumPixelsRenderedQuery( h );
+ }
+
+ int nPixels = m_OcclusionQueryObjects[(int)h].m_LastResult;
+ return nPixels;
+}