📄 vertexshaderdx8.cpp
字号:
{
CreatePixelShader( pDict->GetShader(i)->m_pName );
}
}
break;
}
}
}
//-----------------------------------------------------------------------------
//
// Methods related to vertex shaders
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// The lovely low-level dx call to create a vertex shader
//-----------------------------------------------------------------------------
static HardwareVertexShader_t CreateVertexShader( const PrecompiledShaderByteCode_t& byteCode )
{
MaterialSystemStats()->IncrementCountedStat( MATERIAL_SYSTEM_STATS_NUM_VERTEX_SHADER_CREATES, 1 );
MEASURE_TIMED_STAT( MATERIAL_SYSTEM_STATS_CREATE_VERTEX_SHADER_TIME );
// Compute the vertex specification
HardwareVertexShader_t shader;
HRESULT hr = D3DDevice()->CreateVertexShader( (DWORD*)byteCode.m_pRawData, &shader );
// NOTE: This isn't recorded before the CreateVertexShader because
// we don't know the value of shader until after the CreateVertexShader.
RECORD_COMMAND( DX8_CREATE_VERTEX_SHADER, 3 );
RECORD_INT( ( int )shader ); // hack hack hack
RECORD_INT( byteCode.m_nSizeInBytes );
RECORD_STRUCT( byteCode.m_pRawData, byteCode.m_nSizeInBytes );
if ( FAILED( hr ) )
{
Assert(0);
shader = INVALID_HARDWARE_VERTEX_SHADER;
}
return shader;
}
//-----------------------------------------------------------------------------
// Finds a precompiled shader
//-----------------------------------------------------------------------------
const PrecompiledShader_t *CShaderDictionary::LookupPrecompiledShader( PrecompiledShaderType_t type, const char *pShaderName )
{
unsigned short i = m_PrecompiledShaders[type].Find( pShaderName );
if ( i != m_PrecompiledShaders[type].InvalidIndex() )
{
return m_PrecompiledShaders[type][i];
}
Warning( "shader \"%s\" not found!\n", pShaderName );
// Whoops! Using a bogus shader
// FIXME: Should we return an error shader here?
Assert( 0 );
return NULL;
}
//-----------------------------------------------------------------------------
// Find duplicate vertex shaders...
//-----------------------------------------------------------------------------
int CShaderDictionary::FindVertexShader( char const* pFileName ) const
{
return m_VertexShaders.Find( pFileName );
}
//-----------------------------------------------------------------------------
// Initializes vertex shaders
//-----------------------------------------------------------------------------
bool CShaderDictionary::InitializeVertexShaders( const char *pFileName, VertexShaderInfo_t &info )
{
// Increase the reference count by one so we don't deallocate
// until the end of the level
info.m_nRefCount = 1;
info.m_nShaderCount = 0;
info.m_HardwareShaders = NULL;
const PrecompiledShader_t *pShader = LookupPrecompiledShader( PRECOMPILED_VERTEX_SHADER, pFileName );
if ( !pShader )
return false;
info.m_HardwareShaders = new HardwareVertexShader_t[pShader->m_nShaderCount];
info.m_nShaderCount = pShader->m_nShaderCount;
info.m_Flags = pShader->m_nFlags;
for( int j = 0; j < pShader->m_nShaderCount; j++ )
{
info.m_HardwareShaders[j] = ::CreateVertexShader( pShader->m_pByteCode[j] );
if ( info.m_HardwareShaders[j] == INVALID_HARDWARE_VERTEX_SHADER )
{
Assert( 0 );
delete[] info.m_HardwareShaders;
return false;
}
}
return true;
}
//-----------------------------------------------------------------------------
// Creates and destroys vertex shaders
//-----------------------------------------------------------------------------
VertexShader_t CShaderDictionary::CreateVertexShader( char const* pFileName, int nStaticVshIndex )
{
if ( !pFileName )
return INVALID_VERTEX_SHADER;
// Find duplicate vertex shaders...
int i = FindVertexShader( pFileName );
if (i == m_VertexShaders.InvalidIndex())
{
i = m_VertexShaders.Insert( pFileName );
if ( !InitializeVertexShaders( pFileName, m_VertexShaders[i] ))
{
m_VertexShaders.RemoveAt( i );
return INVALID_VERTEX_SHADER;
}
}
++m_VertexShaders[i].m_nRefCount;
return (VertexShader_t)i;
}
//-----------------------------------------------------------------------------
// Destroys a vertex shader.
//-----------------------------------------------------------------------------
void CShaderDictionary::DestroyVertexShader( VertexShader_t shader )
{
// Can't delete this one...
if ( (shader == INVALID_VERTEX_SHADER) || ((int)shader >= m_VertexShaders.Count()))
return;
if (--m_VertexShaders[shader].m_nRefCount <= 0)
{
for (int i = m_VertexShaders[shader].m_nShaderCount; --i >= 0; )
{
HardwareVertexShader_t vertexShader = m_VertexShaders[shader].m_HardwareShaders[i];
if (vertexShader == INVALID_HARDWARE_VERTEX_SHADER)
continue;
RECORD_COMMAND( DX8_DESTROY_VERTEX_SHADER, 1 );
RECORD_INT( ( int )vertexShader );
vertexShader->Release();
}
if ( m_VertexShaders[shader].m_HardwareShaders )
{
delete[] m_VertexShaders[shader].m_HardwareShaders;
}
m_VertexShaders.RemoveAt( shader );
}
}
//-----------------------------------------------------------------------------
// Destroys all vertex shaders.
//-----------------------------------------------------------------------------
void CShaderDictionary::DestroyAllVertexShaders( )
{
for (int i = m_VertexShaders.First(); i != m_VertexShaders.InvalidIndex(); i = m_VertexShaders.Next(i) )
{
for (int j = m_VertexShaders[i].m_nShaderCount; --j >= 0; )
{
HardwareVertexShader_t vertexShader = m_VertexShaders[i].m_HardwareShaders[j];
if (vertexShader != INVALID_HARDWARE_VERTEX_SHADER)
{
RECORD_COMMAND( DX8_DESTROY_VERTEX_SHADER, 1 );
RECORD_INT( ( int )vertexShader );
vertexShader->Release();
}
}
if ( m_VertexShaders[i].m_HardwareShaders )
{
delete[] m_VertexShaders[i].m_HardwareShaders;
}
}
m_VertexShaders.RemoveAll();
}
//-----------------------------------------------------------------------------
// Gets the hardware vertex shader
//-----------------------------------------------------------------------------
HardwareVertexShader_t CShaderDictionary::GetHardwareVertexShader( VertexShader_t shader, int vshIndex )
{
if ( vshIndex == -1 )
{
int nLightCombo = ShaderAPI()->GetCurrentLightCombo();
int nBoneCount = ShaderAPI()->GetCurrentNumBones();
int nFogType = ShaderAPI()->GetCurrentFogType();
// use the old method of figuring out the vertex shader index using
// numbones, light combo, and fog mode.
vshIndex = ComputeVertexShader( nBoneCount, nLightCombo, nFogType, m_VertexShaders[shader].m_Flags );
}
Assert( vshIndex >= 0 && vshIndex < m_VertexShaders[shader].m_nShaderCount );
return m_VertexShaders[shader].m_HardwareShaders[vshIndex];
}
//-----------------------------------------------------------------------------
//
// Methods related to pixel shaders
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Find duplicate pixel shaders...
//-----------------------------------------------------------------------------
int CShaderDictionary::FindPixelShader( char const* pFileName ) const
{
// Find the shader...
return m_PixelShaders.Find( pFileName );
}
static void PatchPixelShaderForAtiMsaaHack(DWORD *pShader, DWORD dwTexCoordMask)
{
bool bIsSampler, bIsTexCoord;
// Should be able to patch only ps2.0
if (*pShader != 0xFFFF0200)
return;
pShader++;
while (pShader)
{
switch (*pShader & D3DSI_OPCODE_MASK)
{
case D3DSIO_COMMENT:
// Process comment
pShader = pShader + (*pShader >> 16) + 1;
break;
case D3DSIO_END:
// End of shader
return;
case D3DSIO_DCL:
bIsSampler = (*(pShader + 1) & D3DSP_TEXTURETYPE_MASK) != D3DSTT_UNKNOWN;
bIsTexCoord = (((*(pShader + 2) & D3DSP_REGTYPE_MASK) >> D3DSP_REGTYPE_SHIFT) +
((*(pShader + 2) & D3DSP_REGTYPE_MASK2) >> D3DSP_REGTYPE_SHIFT2)) == D3DSPR_TEXTURE;
if (!bIsSampler && bIsTexCoord)
{
DWORD dwTexCoord = *(pShader + 2) & D3DSP_REGNUM_MASK;
DWORD mask = 0x01;
for (DWORD i = 0; i < 16; i++)
{
if (((dwTexCoordMask & mask) == mask) && (dwTexCoord == i))
{
// If found -- patch and get out
*(pShader + 2) |= D3DSPDM_PARTIALPRECISION;
break;
}
mask <<= 1;
}
}
// Intentionally fall through...
default:
// Skip instruction
pShader = pShader + ((*pShader & D3DSI_INSTLENGTH_MASK) >> D3DSI_INSTLENGTH_SHIFT) + 1;
}
}
}
//-----------------------------------------------------------------------------
// The lovely low-level dx call to create a pixel shader
//-----------------------------------------------------------------------------
static HardwarePixelShader_t CreatePixelShader( PrecompiledShaderByteCode_t& byteCode,
unsigned int nCentroidMask )
{
MEASURE_TIMED_STAT( MATERIAL_SYSTEM_STATS_CREATE_PIXEL_SHADER_TIME );
if( nCentroidMask && HardwareConfig()->NeedsATICentroidHack() )
{
PatchPixelShaderForAtiMsaaHack( ( DWORD * )byteCode.m_pRawData, nCentroidMask );
}
HardwarePixelShader_t shader;
HRESULT hr = D3DDevice()->CreatePixelShader( (DWORD*)byteCode.m_pRawData, &shader );
// NOTE: We have to do this after creating the pixel shader since we don't know
// lookup.m_PixelShader yet!!!!!!!
RECORD_COMMAND( DX8_CREATE_PIXEL_SHADER, 3 );
RECORD_INT( ( int )shader ); // hack hack hack
RECORD_INT( byteCode.m_nSizeInBytes );
RECORD_STRUCT( byteCode.m_pRawData, byteCode.m_nSizeInBytes );
if ( FAILED( hr ) )
{
Assert(0);
shader = INVALID_HARDWARE_PIXEL_SHADER;
}
return shader;
}
//-----------------------------------------------------------------------------
// Initializes pixel shaders
//-----------------------------------------------------------------------------
bool CShaderDictionary::InitializePixelShader( const char *pFileName, PixelShaderInfo_t &info )
{
// FIXME: do we need to do this for pixel shaders? We do this for vertex shaders.
// Increase the reference count by one so we don't deallocate
// until the end of the level
info.m_nRefCount = 1;
info.m_nShaderCount = 0;
info.m_HardwareShaders = NULL;
info.m_pPrecompiledDXShader = NULL;
const PrecompiledShader_t *pShader = LookupPrecompiledShader( PRECOMPILED_PIXEL_SHADER, pFileName );
if ( !pShader )
return false;
// Cache off the precompiled shaders + create them on-demand
info.m_pPrecompiledDXShader = pShader;
info.m_nShaderCount = pShader->m_nShaderCount;
info.m_HardwareShaders = new HardwarePixelShader_t[ pShader->m_nShaderCount ];
// Initialize these to 0 to force them to be cached later
for( int j = 0; j < pShader->m_nShaderCount; j++ )
{
info.m_HardwareShaders[j] = INVALID_HARDWARE_PIXEL_SHADER;
}
return true;
}
//-----------------------------------------------------------------------------
// Creates and destroys pixel shaders
//-----------------------------------------------------------------------------
PixelShader_t CShaderDictionary::CreatePixelShader( char const* pFileName, int nStaticPshIndex )
{
// FIXME: NOTE: We could also implement this by returning a unique PixelShader_t
// for each pFileName/nStaticPshIndex combination. I didn't do this because
// even though it's cleaner from the API standpoint because it would mean a
// much larger m_PixelShader dictionary + resulting slower search times.
if ( !pFileName )
return INVALID_PIXEL_SHADER;
// Find duplicate pixel shaders...
int i = FindPixelShader( pFileName );
if (i == m_PixelShaders.InvalidIndex())
{
i = m_PixelShaders.Insert( pFileName );
if ( !InitializePixelShader( pFileName, m_PixelShaders[i] ) )
{
m_PixelShaders.RemoveAt( i );
return INVALID_PIXEL_SHADER;
}
}
PixelShaderInfo_t &info = m_PixelShaders[i];
// FIXME: At the moment, pixel shaders don't know about dynamic psh indices
// which means they only need to precache one thing here. When we introduce
// dynamic pixel shader indices, we'll need to precache *all* dynamic pshs
// associated with the static psh here.
// Make sure the psh index is valid.
if ( nStaticPshIndex >= info.m_pPrecompiledDXShader->m_nShaderCount )
return INVALID_PIXEL_SHADER;
++info.m_nRefCount;
int nDynamicPshIndex;
for( nDynamicPshIndex = 0; nDynamicPshIndex < info.m_pPrecompiledDXShader->m_nDynamicCombos; nDynamicPshIndex++ )
{
HardwarePixelShader_t &shader = info.m_HardwareShaders[nStaticPshIndex+nDynamicPshIndex];
if ( shader == INVALID_HARDWARE_PIXEL_SHADER )
{
// Precache the pixel shader
PrecompiledShaderByteCode_t &byteCode = info.m_pPrecompiledDXShader->m_pByteCode[nStaticPshIndex+nDynamicPshIndex];
// Make sure the data is valid
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -