Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

272 lines
7.6 KiB

//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//
//=============================================================================//
#ifndef IMATERIALSYSTEMINTERNAL_H
#define IMATERIALSYSTEMINTERNAL_H
#ifdef _WIN32
#pragma once
#endif
#include "materialsystem/imaterialsystem.h"
#include "tier1/callqueue.h"
#include "tier1/memstack.h"
#include "tier1/fmtstr.h"
#include "tier0/vprof_telemetry.h"
#include "tier0/perfstats.h"
class IMaterialInternal;
//-----------------------------------------------------------------------------
// Special call queue that knows (a) single threaded access, and (b) all
// functions called after last function added
//-----------------------------------------------------------------------------
class CMatCallQueue
{
public:
CMatCallQueue()
{
static int nStackCount = 0;
CFmtStr stackName( "CMatCallQueue.m_Allocator[%d]", nStackCount++ );
#ifdef DEDICATED
m_Allocator.Init( (const char *)stackName, 2*1024, 0, 0, 4 );
#else
m_Allocator.Init( (const char *)stackName, ( IsGameConsole() || IsPlatformPosix() ) ? 2*1024*1024 : 8*1024*1024, 64*1024, 256*1024, 4 );
#endif
m_FunctorFactory.SetAllocator( &m_Allocator );
m_pHead = m_pTail = NULL;
}
size_t GetMemoryUsed()
{
return m_Allocator.GetUsed();
}
int Count()
{
int i = 0;
Elem_t *pCurrent = m_pHead;
while ( pCurrent )
{
i++;
pCurrent = pCurrent->pNext;
}
return i;
}
template <typename T>
T &Copy( T &item )
{
T *pCopy = (T *)m_Allocator.Alloc( sizeof(T) );
memcpy( pCopy, &item, sizeof(T) );
return *pCopy;
}
template <typename T>
T *CopyArray( T *p, int n )
{
T *pCopy = (T *)m_Allocator.Alloc( sizeof(T) * n );
memcpy( (void *)pCopy, p, sizeof(T) * n );
return pCopy;
}
template <const char *>
const char *Copy( const char *psz )
{
int len = V_strlen( psz );
char *pCopy = (char *)m_Allocator.Alloc( len + 1 );
memcpy( pCopy, psz, len + 1 );
return pCopy;
}
void CallQueued()
{
TM_ZONE_PLOT( TELEMETRY_LEVEL1, "RenderThread", TELEMETRY_ZONE_PLOT_SLOT_2 );
PERF_STATS_BLOCK( "RenderThread", PERF_STATS_SLOT_RENDERTHREAD );
if ( !m_pHead )
{
return;
}
CFunctor *pFunctor;
Elem_t *pCurrent = m_pHead;
while ( pCurrent )
{
pFunctor = pCurrent->GetFunctor();
#ifdef _DEBUG
if ( pFunctor->m_nUserID == m_nBreakSerialNumber)
{
m_nBreakSerialNumber = (unsigned)-1;
}
#endif
if ( pCurrent->pNext )
{
PREFETCH360( pCurrent->pNext, 0 );
PREFETCH360( pCurrent->pNext, 128 );
}
(*pFunctor)();
pFunctor->~CFunctor(); // no need to ref count, we're alone here...
pCurrent = pCurrent->pNext;
}
#ifdef DEBUG_MATCALLQUEUE
static int prevHigh = 0;
if ( m_Allocator.GetUsed() > prevHigh )
{
Msg( "***%d\n", m_Allocator.GetUsed() );
prevHigh = m_Allocator.GetUsed();
}
#endif
m_Allocator.FreeAll( false );
m_pHead = m_pTail = NULL;
}
void QueueFunctor( CFunctor *pFunctor )
{
Assert( pFunctor );
m_Allocator.Alloc( sizeof(Elem_t) );
QueueFunctorInternal( m_FunctorFactory.CreateRefCountingFunctor( pFunctor, &CFunctor::operator() ) );
}
void Flush()
{
if ( !m_pHead )
{
return;
}
CFunctor *pFunctor;
Elem_t *pCurrent = m_pHead;
while ( pCurrent )
{
pFunctor = pCurrent->GetFunctor();
pFunctor->Release();
pCurrent = pCurrent->pNext;
}
m_Allocator.FreeAll( false );
m_pHead = m_pTail = NULL;
}
#define DEFINE_MATCALLQUEUE_NONMEMBER_QUEUE_CALL(N) \
template <typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
void QueueCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
{ \
m_Allocator.Alloc( sizeof(Elem_t) ); \
QueueFunctorInternal( m_FunctorFactory.CreateFunctor( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \
}
//-------------------------------------
#define DEFINE_MATCALLQUEUE_MEMBER_QUEUE_CALL(N) \
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
void QueueCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \
{ \
m_Allocator.Alloc( sizeof(Elem_t) ); \
QueueFunctorInternal( m_FunctorFactory.CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \
}
//-------------------------------------
#define DEFINE_MATCALLQUEUE_CONST_MEMBER_QUEUE_CALL(N) \
template <typename OBJECT_TYPE_PTR, typename FUNCTION_CLASS, typename FUNCTION_RETTYPE FUNC_TEMPLATE_FUNC_PARAMS_##N FUNC_TEMPLATE_ARG_PARAMS_##N> \
void QueueCall(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \
{ \
m_Allocator.Alloc( sizeof(Elem_t) ); \
QueueFunctorInternal( m_FunctorFactory.CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ) ); \
}
//-------------------------------------
FUNC_GENERATE_ALL( DEFINE_MATCALLQUEUE_NONMEMBER_QUEUE_CALL );
FUNC_GENERATE_ALL( DEFINE_MATCALLQUEUE_MEMBER_QUEUE_CALL );
FUNC_GENERATE_ALL( DEFINE_MATCALLQUEUE_CONST_MEMBER_QUEUE_CALL );
private:
void QueueFunctorInternal( CFunctor *pFunctor )
{
#ifdef _DEBUG
pFunctor->m_nUserID = m_nCurSerialNumber++;
#endif
MEM_ALLOC_CREDIT_( "CMatCallQueue.m_Allocator" );
// Caller is expected to have preallocated Elem_t entry immediately prior to functor
Elem_t *pNew = ((Elem_t *)pFunctor) - 1;
if ( m_pTail )
{
m_pTail->pNext = pNew;
m_pTail = pNew;
}
else
{
m_pHead = m_pTail = pNew;
}
pNew->pNext = NULL;
}
struct Elem_t
{
Elem_t *pNext;
CFunctor *GetFunctor() { return (CFunctor *)(this + 1 ); }
};
Elem_t *m_pHead;
Elem_t *m_pTail;
CMemoryStack m_Allocator;
CCustomizedFunctorFactory<CMemoryStack, CRefCounted1<CFunctor, CRefCountServiceDestruct< CRefST > > > m_FunctorFactory;
unsigned m_nCurSerialNumber;
unsigned m_nBreakSerialNumber;
};
#define MATCONFIG_FLAGS_SUPPORT_EDITOR ( 1 << 0 )
#define MATCONFIG_FLAGS_SUPPORT_GBUFFER ( 1 << 1 )
//-----------------------------------------------------------------------------
// Additional interfaces used internally to the library
//-----------------------------------------------------------------------------
abstract_class IMaterialSystemInternal : public IMaterialSystem
{
public:
// Returns the current material
virtual IMaterial* GetCurrentMaterial() = 0;
virtual int GetLightmapPage( void ) = 0;
// Gets the maximum lightmap page size...
virtual int GetLightmapWidth( int lightmap ) const = 0;
virtual int GetLightmapHeight( int lightmap ) const = 0;
virtual ITexture *GetLocalCubemap( void ) = 0;
// virtual bool RenderZOnlyWithHeightClipEnabled( void ) = 0;
virtual void ForceDepthFuncEquals( bool bEnable ) = 0;
virtual enum MaterialHeightClipMode_t GetHeightClipMode( void ) = 0;
// FIXME: Remove? Here for debugging shaders in CShaderSystem
virtual void AddMaterialToMaterialList( IMaterialInternal *pMaterial ) = 0;
virtual void RemoveMaterial( IMaterialInternal *pMaterial ) = 0;
virtual void RemoveMaterialSubRect( IMaterialInternal *pMaterial ) = 0;
virtual bool InFlashlightMode() const = 0;
virtual bool IsCascadedShadowMapping() const = 0;
// Can we use editor materials?
virtual bool CanUseEditorMaterials() const = 0;
virtual int GetConfigurationFlags( void ) const = 0;
virtual const char *GetForcedTextureLoadPathID() = 0;
virtual CMatCallQueue *GetRenderCallQueue() = 0;
virtual void UnbindMaterial( IMaterial *pMaterial ) = 0;
virtual uint GetRenderThreadId() const = 0 ;
};
#endif // IMATERIALSYSTEMINTERNAL_H