⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vertexshaderdx8.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
				{
					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 + -