|
|
//===== Copyright © 1996-2008, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//
//===========================================================================//
#include "shaderapidx10.h"
#include "shaderapibase.h"
#include "shaderapi/ishaderutil.h"
#include "materialsystem/idebugtextureinfo.h"
#include "materialsystem/materialsystem_config.h"
#include "materialsystem/ITexture.h"
#include "meshdx10.h"
#include "shadershadowdx10.h"
#include "shaderdevicedx10.h"
#include "shaderapidx10_global.h"
#include "imaterialinternal.h"
#include "shaderapi/gpumemorystats.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Methods related to queuing functions to be called prior to rendering
//-----------------------------------------------------------------------------
CFunctionCommit::CFunctionCommit() { m_pCommitFlags = NULL; m_nCommitBufferSize = 0; }
CFunctionCommit::~CFunctionCommit() { if ( m_pCommitFlags ) { delete[] m_pCommitFlags; m_pCommitFlags = NULL; } }
void CFunctionCommit::Init( int nFunctionCount ) { m_nCommitBufferSize = ( nFunctionCount + 7 ) >> 3; Assert( !m_pCommitFlags ); m_pCommitFlags = new unsigned char[ m_nCommitBufferSize ]; memset( m_pCommitFlags, 0, m_nCommitBufferSize ); }
//-----------------------------------------------------------------------------
// Methods related to queuing functions to be called per-(pMesh->Draw call) or per-pass
//-----------------------------------------------------------------------------
inline bool CFunctionCommit::IsCommitFuncInUse( int nFunc ) const { Assert( nFunc >> 3 < m_nCommitBufferSize ); return ( m_pCommitFlags[ nFunc >> 3 ] & ( 1 << ( nFunc & 0x7 ) ) ) != 0; }
inline void CFunctionCommit::MarkCommitFuncInUse( int nFunc ) { Assert( nFunc >> 3 < m_nCommitBufferSize ); m_pCommitFlags[ nFunc >> 3 ] |= 1 << ( nFunc & 0x7 ); }
inline void CFunctionCommit::AddCommitFunc( StateCommitFunc_t f ) { m_CommitFuncs.AddToTail( f ); }
//-----------------------------------------------------------------------------
// Clears all commit functions
//-----------------------------------------------------------------------------
inline void CFunctionCommit::ClearAllCommitFuncs( ) { memset( m_pCommitFlags, 0, m_nCommitBufferSize ); m_CommitFuncs.RemoveAll(); }
//-----------------------------------------------------------------------------
// Calls all commit functions in a particular list
//-----------------------------------------------------------------------------
void CFunctionCommit::CallCommitFuncs( ID3D10Device *pDevice, const ShaderStateDx10_t &desiredState, ShaderStateDx10_t ¤tState, bool bForce ) { int nCount = m_CommitFuncs.Count(); for ( int i = 0; i < nCount; ++i ) { m_CommitFuncs[i]( pDevice, desiredState, currentState, bForce ); }
ClearAllCommitFuncs( ); }
//-----------------------------------------------------------------------------
// Helpers for commit functions
//-----------------------------------------------------------------------------
#define ADD_COMMIT_FUNC( _func_name ) \
if ( !m_Commit.IsCommitFuncInUse( COMMIT_FUNC_ ## _func_name ) ) \ { \ m_Commit.AddCommitFunc( _func_name ); \ m_Commit.MarkCommitFuncInUse( COMMIT_FUNC_ ## _func_name ); \ }
#define ADD_RENDERSTATE_FUNC( _func_name, _state, _val ) \
if ( m_bResettingRenderState || ( m_DesiredState. ## _state != _val ) ) \ { \ m_DesiredState. ## _state = _val; \ ADD_COMMIT_FUNC( _func_name ) \ }
#define IMPLEMENT_RENDERSTATE_FUNC( _func_name, _state, _d3dFunc ) \
static void _func_name( ID3D10Device *pDevice, const ShaderStateDx10_t &desiredState, ShaderStateDx10_t ¤tState, bool bForce ) \ { \ if ( bForce || ( desiredState. ## _state != currentState. ## _state ) ) \ { \ pDevice->_d3dFunc( desiredState. ## _state ); \ currentState. ## _state = desiredState. ## _state; \ } \ }
//-----------------------------------------------------------------------------
// D3D state setting methods
//-----------------------------------------------------------------------------
// NOTE: For each commit func you create, add to this enumeration.
enum CommitFunc_t { COMMIT_FUNC_CommitSetViewports = 0, COMMIT_FUNC_CommitSetVertexShader, COMMIT_FUNC_CommitSetGeometryShader, COMMIT_FUNC_CommitSetPixelShader, COMMIT_FUNC_CommitSetVertexBuffer, COMMIT_FUNC_CommitSetIndexBuffer, COMMIT_FUNC_CommitSetInputLayout, COMMIT_FUNC_CommitSetTopology, COMMIT_FUNC_CommitSetRasterState,
COMMIT_FUNC_COUNT, };
IMPLEMENT_RENDERSTATE_FUNC( CommitSetTopology, m_Topology, IASetPrimitiveTopology ) IMPLEMENT_RENDERSTATE_FUNC( CommitSetVertexShader, m_pVertexShader, VSSetShader ) IMPLEMENT_RENDERSTATE_FUNC( CommitSetGeometryShader, m_pGeometryShader, GSSetShader ) IMPLEMENT_RENDERSTATE_FUNC( CommitSetPixelShader, m_pPixelShader, PSSetShader )
static void CommitSetInputLayout( ID3D10Device *pDevice, const ShaderStateDx10_t &desiredState, ShaderStateDx10_t ¤tState, bool bForce ) { const ShaderInputLayoutStateDx10_t& newState = desiredState.m_InputLayout; if ( bForce || memcmp( &newState, ¤tState.m_InputLayout, sizeof(ShaderInputLayoutStateDx10_t) ) ) { // FIXME: Deal with multiple streams
ID3D10InputLayout *pInputLayout = g_pShaderDeviceDx10->GetInputLayout( newState.m_hVertexShader, newState.m_pVertexDecl[0] ); pDevice->IASetInputLayout( pInputLayout );
currentState.m_InputLayout = newState; } }
static void CommitSetViewports( ID3D10Device *pDevice, const ShaderStateDx10_t &desiredState, ShaderStateDx10_t ¤tState, bool bForce ) { bool bChanged = bForce || ( desiredState.m_nViewportCount != currentState.m_nViewportCount ); if ( !bChanged && desiredState.m_nViewportCount > 0 ) { bChanged = memcmp( desiredState.m_pViewports, currentState.m_pViewports, desiredState.m_nViewportCount * sizeof( D3D10_VIEWPORT ) ) != 0; }
if ( !bChanged ) return;
pDevice->RSSetViewports( desiredState.m_nViewportCount, desiredState.m_pViewports ); currentState.m_nViewportCount = desiredState.m_nViewportCount;
#ifdef _DEBUG
memset( currentState.m_pViewports, 0xDD, sizeof( currentState.m_pViewports ) ); #endif
memcpy( currentState.m_pViewports, desiredState.m_pViewports, desiredState.m_nViewportCount * sizeof( D3D10_VIEWPORT ) ); }
static void CommitSetIndexBuffer( ID3D10Device *pDevice, const ShaderStateDx10_t &desiredState, ShaderStateDx10_t ¤tState, bool bForce ) { const ShaderIndexBufferStateDx10_t &newState = desiredState.m_IndexBuffer; bool bChanged = bForce || memcmp( &newState, ¤tState.m_IndexBuffer, sizeof(ShaderIndexBufferStateDx10_t) ); if ( !bChanged ) return;
pDevice->IASetIndexBuffer( newState.m_pBuffer, newState.m_Format, newState.m_nOffset ); memcpy( ¤tState.m_IndexBuffer, &newState, sizeof( ShaderIndexBufferStateDx10_t ) ); }
static void CommitSetVertexBuffer( ID3D10Device *pDevice, const ShaderStateDx10_t &desiredState, ShaderStateDx10_t ¤tState, bool bForce ) { ID3D10Buffer *ppVertexBuffers[ MAX_DX10_STREAMS ]; UINT pStrides[ MAX_DX10_STREAMS ]; UINT pOffsets[ MAX_DX10_STREAMS ];
UINT nFirstBuffer = 0; UINT nBufferCount = 0; bool bInMatch = true; for ( int i = 0; i < MAX_DX10_STREAMS; ++i ) { const ShaderVertexBufferStateDx10_t &newState = desiredState.m_pVertexBuffer[i]; bool bMatch = !bForce && !memcmp( &newState, ¤tState.m_pVertexBuffer[i], sizeof(ShaderVertexBufferStateDx10_t) ); if ( !bMatch ) { ppVertexBuffers[i] = newState.m_pBuffer; pStrides[i] = newState.m_nStride; pOffsets[i] = newState.m_nOffset; ++nBufferCount; memcpy( ¤tState.m_pVertexBuffer[i], &newState, sizeof( ShaderVertexBufferStateDx10_t ) ); }
if ( bInMatch ) { if ( !bMatch ) { bInMatch = false; nFirstBuffer = i; } continue; }
if ( bMatch ) { bInMatch = true; pDevice->IASetVertexBuffers( nFirstBuffer, nBufferCount, &ppVertexBuffers[nFirstBuffer], &pStrides[nFirstBuffer], &pOffsets[nFirstBuffer] ); nBufferCount = 0; } }
if ( !bInMatch ) { pDevice->IASetVertexBuffers( nFirstBuffer, nBufferCount, &ppVertexBuffers[nFirstBuffer], &pStrides[nFirstBuffer], &pOffsets[nFirstBuffer] ); } }
static void GenerateRasterizerDesc( D3D10_RASTERIZER_DESC* pDesc, const ShaderRasterState_t& state ) { pDesc->FillMode = ( state.m_FillMode == SHADER_FILL_WIREFRAME ) ? D3D10_FILL_WIREFRAME : D3D10_FILL_SOLID; // Cull state
if ( state.m_bCullEnable ) { pDesc->CullMode = D3D10_CULL_NONE; } else { pDesc->CullMode = ( state.m_CullMode == MATERIAL_CULLMODE_CW ) ? D3D10_CULL_BACK : D3D10_CULL_FRONT; } pDesc->FrontCounterClockwise = TRUE;
// Depth bias state
if ( !state.m_bDepthBias ) { pDesc->DepthBias = 0; pDesc->DepthBiasClamp = 0.0f; pDesc->SlopeScaledDepthBias = 0.0f; pDesc->DepthClipEnable = FALSE; } else { // FIXME: Implement! Read ConVars
}
pDesc->ScissorEnable = state.m_bScissorEnable ? TRUE : FALSE; pDesc->MultisampleEnable = state.m_bMultisampleEnable ? TRUE : FALSE; pDesc->AntialiasedLineEnable = FALSE; }
static void CommitSetRasterState( ID3D10Device *pDevice, const ShaderStateDx10_t &desiredState, ShaderStateDx10_t ¤tState, bool bForce ) { const ShaderRasterState_t& newState = desiredState.m_RasterState; if ( bForce || memcmp( &newState, ¤tState.m_RasterState, sizeof(ShaderRasterState_t) ) ) { // Clear out the existing state
if ( currentState.m_pRasterState ) { currentState.m_pRasterState->Release(); }
D3D10_RASTERIZER_DESC desc; GenerateRasterizerDesc( &desc, newState );
// NOTE: This does a search for existing matching state objects
ID3D10RasterizerState *pState = NULL; HRESULT hr = pDevice->CreateRasterizerState( &desc, &pState ); if ( !FAILED(hr) ) { Warning( "Unable to create rasterizer state object!\n" ); }
pDevice->RSSetState( pState );
currentState.m_pRasterState = pState; memcpy( ¤tState.m_RasterState, &newState, sizeof( ShaderRasterState_t ) ); } }
//-----------------------------------------------------------------------------
//
// Shader API Dx10
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Class Factory
//-----------------------------------------------------------------------------
static CShaderAPIDx10 s_ShaderAPIDx10; CShaderAPIDx10* g_pShaderAPIDx10 = &s_ShaderAPIDx10;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CShaderAPIDx10, IShaderAPI, SHADERAPI_INTERFACE_VERSION, s_ShaderAPIDx10 )
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CShaderAPIDx10, IDebugTextureInfo, DEBUG_TEXTURE_INFO_VERSION, s_ShaderAPIDx10 )
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
CShaderAPIDx10::CShaderAPIDx10() { m_bResettingRenderState = false; m_Commit.Init( COMMIT_FUNC_COUNT ); ClearShaderState( &m_DesiredState ); ClearShaderState( &m_CurrentState ); }
CShaderAPIDx10::~CShaderAPIDx10() { }
//-----------------------------------------------------------------------------
// Clears the shader state to a well-defined value
//-----------------------------------------------------------------------------
void CShaderAPIDx10::ClearShaderState( ShaderStateDx10_t* pState ) { memset( pState, 0, sizeof( ShaderStateDx10_t ) ); }
//-----------------------------------------------------------------------------
// Resets the render state
//-----------------------------------------------------------------------------
void CShaderAPIDx10::ResetRenderState( bool bFullReset ) { D3D10_RASTERIZER_DESC rDesc; memset( &rDesc, 0, sizeof(rDesc) ); rDesc.FillMode = D3D10_FILL_SOLID; rDesc.CullMode = D3D10_CULL_NONE; rDesc.FrontCounterClockwise = TRUE; // right-hand rule
ID3D10RasterizerState *pRasterizerState; HRESULT hr = D3D10Device()->CreateRasterizerState( &rDesc, &pRasterizerState ); Assert( !FAILED(hr) ); D3D10Device()->RSSetState( pRasterizerState );
D3D10_DEPTH_STENCIL_DESC dsDesc; memset( &dsDesc, 0, sizeof(dsDesc) );
ID3D10DepthStencilState *pDepthStencilState; hr = D3D10Device()->CreateDepthStencilState( &dsDesc, &pDepthStencilState ); Assert( !FAILED(hr) ); D3D10Device()->OMSetDepthStencilState( pDepthStencilState, 0 );
D3D10_BLEND_DESC bDesc; memset( &bDesc, 0, sizeof(bDesc) ); bDesc.SrcBlend = D3D10_BLEND_ONE; bDesc.DestBlend = D3D10_BLEND_ZERO; bDesc.BlendOp = D3D10_BLEND_OP_ADD; bDesc.SrcBlendAlpha = D3D10_BLEND_ONE; bDesc.DestBlendAlpha = D3D10_BLEND_ZERO; bDesc.BlendOpAlpha = D3D10_BLEND_OP_ADD; bDesc.RenderTargetWriteMask[0] = D3D10_COLOR_WRITE_ENABLE_ALL;
FLOAT pBlendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; ID3D10BlendState *pBlendState; hr = D3D10Device()->CreateBlendState( &bDesc, &pBlendState ); Assert( !FAILED(hr) ); D3D10Device()->OMSetBlendState( pBlendState, pBlendFactor, 0xFFFFFFFF ); }
//-----------------------------------------------------------------------------
// Commits queued-up state change requests
//-----------------------------------------------------------------------------
void CShaderAPIDx10::CommitStateChanges( bool bForce ) { // Don't bother committing anything if we're deactivated
if ( g_pShaderDevice->IsDeactivated() ) return;
m_Commit.CallCommitFuncs( D3D10Device(), m_DesiredState, m_CurrentState, bForce ); }
//-----------------------------------------------------------------------------
// Methods of IShaderDynamicAPI
//-----------------------------------------------------------------------------
void CShaderAPIDx10::GetBackBufferDimensions( int& nWidth, int& nHeight ) const { g_pShaderDeviceDx10->GetBackBufferDimensions( nWidth, nHeight ); }
// Get the dimensions of the current render target
void CShaderAPIDx10::GetCurrentRenderTargetDimensions( int& nWidth, int& nHeight ) const { ITexture *pTexture = GetRenderTargetEx( 0 ); if ( pTexture == NULL ) { GetBackBufferDimensions( nWidth, nHeight ); } else { nWidth = pTexture->GetActualWidth(); nHeight = pTexture->GetActualHeight(); } }
// Get the current viewport
void CShaderAPIDx10::GetCurrentViewport( int& nX, int& nY, int& nWidth, int& nHeight ) const { ShaderViewport_t viewport; GetViewports( &viewport, 1 ); nX = viewport.m_nTopLeftX; nY = viewport.m_nTopLeftY; nWidth = viewport.m_nWidth; nHeight = viewport.m_nHeight; }
inline void CShaderAPIDx10::SetScreenSizeForVPOS( int pshReg /* = 32 */) { }
inline void CShaderAPIDx10::SetVSNearAndFarZ( int vshReg ) { }
inline float CShaderAPIDx10::GetFarZ( void ) { return 1000.0f; // dummy default value
}
//-----------------------------------------------------------------------------
// Viewport-related methods
//-----------------------------------------------------------------------------
void CShaderAPIDx10::SetViewports( int nCount, const ShaderViewport_t* pViewports ) { nCount = min( nCount, MAX_DX10_VIEWPORTS ); m_DesiredState.m_nViewportCount = nCount;
for ( int i = 0; i < nCount; ++i ) { Assert( pViewports[i].m_nVersion == SHADER_VIEWPORT_VERSION );
D3D10_VIEWPORT& viewport = m_DesiredState.m_pViewports[i]; viewport.TopLeftX = pViewports[i].m_nTopLeftX; viewport.TopLeftY = pViewports[i].m_nTopLeftY; viewport.Width = pViewports[i].m_nWidth; viewport.Height = pViewports[i].m_nHeight; viewport.MinDepth = pViewports[i].m_flMinZ; viewport.MaxDepth = pViewports[i].m_flMaxZ; }
ADD_COMMIT_FUNC( CommitSetViewports ); }
int CShaderAPIDx10::GetViewports( ShaderViewport_t* pViewports, int nMax ) const { int nCount = m_DesiredState.m_nViewportCount; if ( pViewports && nMax ) { nCount = min( nCount, nMax ); memcpy( pViewports, m_DesiredState.m_pViewports, nCount * sizeof( ShaderViewport_t ) ); } return nCount; }
//-----------------------------------------------------------------------------
// Methods related to state objects
//-----------------------------------------------------------------------------
void CShaderAPIDx10::SetRasterState( const ShaderRasterState_t& state ) { if ( memcmp( &state, &m_DesiredState.m_RasterState, sizeof(ShaderRasterState_t) ) ) { memcpy( &m_DesiredState.m_RasterState, &state, sizeof(ShaderRasterState_t) ); ADD_COMMIT_FUNC( CommitSetRasterState ); } }
//-----------------------------------------------------------------------------
// Methods related to clearing buffers
//-----------------------------------------------------------------------------
void CShaderAPIDx10::ClearColor3ub( unsigned char r, unsigned char g, unsigned char b ) { m_DesiredState.m_ClearColor[0] = r / 255.0f; m_DesiredState.m_ClearColor[1] = g / 255.0f; m_DesiredState.m_ClearColor[2] = b / 255.0f; m_DesiredState.m_ClearColor[3] = 1.0f; }
void CShaderAPIDx10::ClearColor4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a ) { m_DesiredState.m_ClearColor[0] = r / 255.0f; m_DesiredState.m_ClearColor[1] = g / 255.0f; m_DesiredState.m_ClearColor[2] = b / 255.0f; m_DesiredState.m_ClearColor[3] = a / 255.0f; }
void CShaderAPIDx10::ClearBuffers( bool bClearColor, bool bClearDepth, bool bClearStencil, int renderTargetWidth, int renderTargetHeight ) { // NOTE: State change commit isn't necessary since clearing doesn't use state
// CommitStateChanges();
// FIXME: This implementation is totally bust0red [doesn't guarantee exact color specified]
if ( bClearColor ) { D3D10Device()->ClearRenderTargetView( D3D10RenderTargetView(), m_DesiredState.m_ClearColor ); } }
//-----------------------------------------------------------------------------
// Methods related to binding shaders
//-----------------------------------------------------------------------------
void CShaderAPIDx10::BindVertexShader( VertexShaderHandle_t hVertexShader ) { ID3D10VertexShader *pVertexShader = g_pShaderDeviceDx10->GetVertexShader( hVertexShader ); ADD_RENDERSTATE_FUNC( CommitSetVertexShader, m_pVertexShader, pVertexShader );
if ( m_bResettingRenderState || ( m_DesiredState.m_InputLayout.m_hVertexShader != hVertexShader ) ) { m_DesiredState.m_InputLayout.m_hVertexShader = hVertexShader; ADD_COMMIT_FUNC( CommitSetInputLayout ); } }
void CShaderAPIDx10::BindGeometryShader( GeometryShaderHandle_t hGeometryShader ) { ID3D10GeometryShader *pGeometryShader = g_pShaderDeviceDx10->GetGeometryShader( hGeometryShader ); ADD_RENDERSTATE_FUNC( CommitSetGeometryShader, m_pGeometryShader, pGeometryShader ); }
void CShaderAPIDx10::BindPixelShader( PixelShaderHandle_t hPixelShader ) { ID3D10PixelShader *pPixelShader = g_pShaderDeviceDx10->GetPixelShader( hPixelShader ); ADD_RENDERSTATE_FUNC( CommitSetPixelShader, m_pPixelShader, pPixelShader ); }
void CShaderAPIDx10::BindVertexBuffer( int nStreamID, IVertexBuffer *pVertexBuffer, int nOffsetInBytes, int nFirstVertex, int nVertexCount, VertexFormat_t fmt, int nRepetitions ) { // FIXME: What to do about repetitions?
CVertexBufferDx10 *pVertexBufferDx10 = static_cast<CVertexBufferDx10 *>( pVertexBuffer );
ShaderVertexBufferStateDx10_t state; if ( pVertexBufferDx10 ) { state.m_pBuffer = pVertexBufferDx10->GetDx10Buffer(); state.m_nStride = pVertexBufferDx10->VertexSize(); } else { state.m_pBuffer = NULL; state.m_nStride = 0; } state.m_nOffset = nOffsetInBytes;
if ( m_bResettingRenderState || memcmp( &m_DesiredState.m_pVertexBuffer[ nStreamID ], &state, sizeof( ShaderVertexBufferStateDx10_t ) ) ) { m_DesiredState.m_pVertexBuffer[ nStreamID ] = state; ADD_COMMIT_FUNC( CommitSetVertexBuffer ); }
if ( m_bResettingRenderState || ( m_DesiredState.m_InputLayout.m_pVertexDecl[ nStreamID ] != fmt ) ) { m_DesiredState.m_InputLayout.m_pVertexDecl[ nStreamID ] = fmt; ADD_COMMIT_FUNC( CommitSetInputLayout ); } }
void CShaderAPIDx10::BindIndexBuffer( IIndexBuffer *pIndexBuffer, int nOffsetInBytes ) { CIndexBufferDx10 *pIndexBufferDx10 = static_cast<CIndexBufferDx10 *>( pIndexBuffer );
ShaderIndexBufferStateDx10_t state; if ( pIndexBufferDx10 ) { state.m_pBuffer = pIndexBufferDx10->GetDx10Buffer(); state.m_Format = ( pIndexBufferDx10->GetIndexFormat() == MATERIAL_INDEX_FORMAT_16BIT ) ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; } else { state.m_pBuffer = NULL; state.m_Format = DXGI_FORMAT_R16_UINT; } state.m_nOffset = nOffsetInBytes;
ADD_RENDERSTATE_FUNC( CommitSetIndexBuffer, m_IndexBuffer, state ); }
//-----------------------------------------------------------------------------
// Unbinds resources because they are about to be deleted
//-----------------------------------------------------------------------------
void CShaderAPIDx10::Unbind( VertexShaderHandle_t hShader ) { ID3D10VertexShader* pShader = g_pShaderDeviceDx10->GetVertexShader( hShader ); Assert ( pShader ); if ( m_DesiredState.m_pVertexShader == pShader ) { BindVertexShader( VERTEX_SHADER_HANDLE_INVALID ); } if ( m_CurrentState.m_pVertexShader == pShader ) { CommitStateChanges(); } }
void CShaderAPIDx10::Unbind( GeometryShaderHandle_t hShader ) { ID3D10GeometryShader* pShader = g_pShaderDeviceDx10->GetGeometryShader( hShader ); Assert ( pShader ); if ( m_DesiredState.m_pGeometryShader == pShader ) { BindGeometryShader( GEOMETRY_SHADER_HANDLE_INVALID ); } if ( m_CurrentState.m_pGeometryShader == pShader ) { CommitStateChanges(); } }
void CShaderAPIDx10::Unbind( PixelShaderHandle_t hShader ) { ID3D10PixelShader* pShader = g_pShaderDeviceDx10->GetPixelShader( hShader ); Assert ( pShader ); if ( m_DesiredState.m_pPixelShader == pShader ) { BindPixelShader( PIXEL_SHADER_HANDLE_INVALID ); } if ( m_CurrentState.m_pPixelShader == pShader ) { CommitStateChanges(); } }
void CShaderAPIDx10::UnbindVertexBuffer( ID3D10Buffer *pBuffer ) { Assert ( pBuffer );
for ( int i = 0; i < MAX_DX10_STREAMS; ++i ) { if ( m_DesiredState.m_pVertexBuffer[i].m_pBuffer == pBuffer ) { BindVertexBuffer( i, NULL, 0, 0, 0, VERTEX_POSITION, 0 ); } } for ( int i = 0; i < MAX_DX10_STREAMS; ++i ) { if ( m_CurrentState.m_pVertexBuffer[i].m_pBuffer == pBuffer ) { CommitStateChanges(); break; } } }
void CShaderAPIDx10::UnbindIndexBuffer( ID3D10Buffer *pBuffer ) { Assert ( pBuffer );
if ( m_DesiredState.m_IndexBuffer.m_pBuffer == pBuffer ) { BindIndexBuffer( NULL, 0 ); } if ( m_CurrentState.m_IndexBuffer.m_pBuffer == pBuffer ) { CommitStateChanges(); } }
//-----------------------------------------------------------------------------
// Sets the topology state
//-----------------------------------------------------------------------------
void CShaderAPIDx10::SetTopology( MaterialPrimitiveType_t topology ) { D3D10_PRIMITIVE_TOPOLOGY d3dTopology; switch( topology ) { case MATERIAL_POINTS: d3dTopology = D3D10_PRIMITIVE_TOPOLOGY_POINTLIST; break;
case MATERIAL_LINES: d3dTopology = D3D10_PRIMITIVE_TOPOLOGY_LINELIST; break;
case MATERIAL_TRIANGLES: d3dTopology = D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST; break;
case MATERIAL_TRIANGLE_STRIP: d3dTopology = D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; break;
case MATERIAL_LINE_STRIP: d3dTopology = D3D10_PRIMITIVE_TOPOLOGY_LINESTRIP; break;
default: case MATERIAL_LINE_LOOP: case MATERIAL_POLYGON: case MATERIAL_QUADS: Assert( 0 ); d3dTopology = D3D10_PRIMITIVE_TOPOLOGY_UNDEFINED; break; }
ADD_RENDERSTATE_FUNC( CommitSetTopology, m_Topology, d3dTopology ); }
//-----------------------------------------------------------------------------
// Main entry point for rendering
//-----------------------------------------------------------------------------
void CShaderAPIDx10::Draw( MaterialPrimitiveType_t primitiveType, int nFirstIndex, int nIndexCount ) { SetTopology( primitiveType );
CommitStateChanges();
// FIXME: How do I set the base vertex location!?
D3D10Device()->DrawIndexed( (UINT)nIndexCount, (UINT)nFirstIndex, 0 ); }
//-----------------------------------------------------------------------------
//
// Abandon all hope below this point
//
//-----------------------------------------------------------------------------
bool CShaderAPIDx10::DoRenderTargetsNeedSeparateDepthBuffer() const { return false; }
// Can we download textures?
bool CShaderAPIDx10::CanDownloadTextures() const { return false; }
// Used to clear the transition table when we know it's become invalid.
void CShaderAPIDx10::ClearSnapshots() { }
// Sets the default *dynamic* state
void CShaderAPIDx10::SetDefaultState() { }
// Returns the snapshot id for the shader state
StateSnapshot_t CShaderAPIDx10::TakeSnapshot( ) { StateSnapshot_t id = 0; if (g_pShaderShadowDx10->m_IsTranslucent) id |= TRANSLUCENT; if (g_pShaderShadowDx10->m_IsAlphaTested) id |= ALPHATESTED; if (g_pShaderShadowDx10->m_bUsesVertexAndPixelShaders) id |= VERTEX_AND_PIXEL_SHADERS; if (g_pShaderShadowDx10->m_bIsDepthWriteEnabled) id |= DEPTHWRITE; return id; }
// Returns true if the state snapshot is transparent
bool CShaderAPIDx10::IsTranslucent( StateSnapshot_t id ) const { return (id & TRANSLUCENT) != 0; }
bool CShaderAPIDx10::IsAlphaTested( StateSnapshot_t id ) const { return (id & ALPHATESTED) != 0; }
bool CShaderAPIDx10::IsDepthWriteEnabled( StateSnapshot_t id ) const { return (id & DEPTHWRITE) != 0; }
bool CShaderAPIDx10::UsesVertexAndPixelShaders( StateSnapshot_t id ) const { return (id & VERTEX_AND_PIXEL_SHADERS) != 0; }
// Gets the vertex format for a set of snapshot ids
VertexFormat_t CShaderAPIDx10::ComputeVertexFormat( int numSnapshots, StateSnapshot_t* pIds ) const { return 0; }
// Gets the vertex format for a set of snapshot ids
VertexFormat_t CShaderAPIDx10::ComputeVertexUsage( int numSnapshots, StateSnapshot_t* pIds ) const { return 0; }
// Uses a state snapshot
void CShaderAPIDx10::UseSnapshot( StateSnapshot_t snapshot ) { }
void CShaderAPIDx10::GetStandardTextureDimensions( int *pWidth, int *pHeight, StandardTextureId_t id ) { ShaderUtil()->GetStandardTextureDimensions( pWidth, pHeight, id ); }
float CShaderAPIDx10::GetSubDHeight() { return ShaderUtil()->GetSubDHeight(); }
// The shade mode
void CShaderAPIDx10::ShadeMode( ShaderShadeMode_t mode ) { }
// Binds a particular material to render with
void CShaderAPIDx10::Bind( IMaterial* pMaterial ) { }
// Cull mode
void CShaderAPIDx10::CullMode( MaterialCullMode_t cullMode ) { }
void CShaderAPIDx10::FlipCullMode( void ) { }
void CShaderAPIDx10::ForceDepthFuncEquals( bool bEnable ) { }
// Forces Z buffering on or off
void CShaderAPIDx10::OverrideDepthEnable( bool bEnable, bool bDepthEnable ) { }
void CShaderAPIDx10::OverrideAlphaWriteEnable( bool bOverrideEnable, bool bAlphaWriteEnable ) { }
void CShaderAPIDx10::OverrideColorWriteEnable( bool bOverrideEnable, bool bColorWriteEnable ) { }
//legacy fast clipping linkage
void CShaderAPIDx10::SetHeightClipZ( float z ) { }
void CShaderAPIDx10::SetHeightClipMode( enum MaterialHeightClipMode_t heightClipMode ) { }
// Sets the lights
void CShaderAPIDx10::SetLights( int lightNum, const LightDesc_t* pDesc ) { }
void CShaderAPIDx10::SetLightingState( const MaterialLightingState_t &state ) { }
void CShaderAPIDx10::SetAmbientLightCube( Vector4D cube[6] ) { }
// Gets the lightmap dimensions
void CShaderAPIDx10::GetLightmapDimensions( int *w, int *h ) { g_pShaderUtil->GetLightmapDimensions( w, h ); }
// Flushes any primitives that are buffered
void CShaderAPIDx10::FlushBufferedPrimitives() { }
// Creates/destroys Mesh
IMesh* CShaderAPIDx10::CreateStaticMesh( VertexFormat_t fmt, const char *pTextureBudgetGroup, IMaterial * pMaterial, VertexStreamSpec_t *pStreamSpec ) { return &m_Mesh; }
void CShaderAPIDx10::DestroyStaticMesh( IMesh* mesh ) { }
// Gets the dynamic mesh; note that you've got to render the mesh
// before calling this function a second time. Clients should *not*
// call DestroyStaticMesh on the mesh returned by this call.
IMesh* CShaderAPIDx10::GetDynamicMesh( IMaterial* pMaterial, int nHWSkinBoneCount, bool buffered, IMesh* pVertexOverride, IMesh* pIndexOverride ) { Assert( (pMaterial == NULL) || ((IMaterialInternal *)pMaterial)->IsRealTimeVersion() ); return &m_Mesh; }
IMesh* CShaderAPIDx10::GetDynamicMeshEx( IMaterial* pMaterial, VertexFormat_t fmt, int nHWSkinBoneCount, bool buffered, IMesh* pVertexOverride, IMesh* pIndexOverride ) { // UNDONE: support compressed dynamic meshes if needed (pro: less VB memory, con: time spent compressing)
Assert( CompressionType( pVertexOverride->GetVertexFormat() ) != VERTEX_COMPRESSION_NONE ); Assert( (pMaterial == NULL) || ((IMaterialInternal *)pMaterial)->IsRealTimeVersion() ); return &m_Mesh; }
IMesh* CShaderAPIDx10::GetFlexMesh() { return &m_Mesh; }
// Begins a rendering pass that uses a state snapshot
void CShaderAPIDx10::BeginPass( StateSnapshot_t snapshot ) { }
// Renders a single pass of a material
void CShaderAPIDx10::RenderPass( const unsigned char *pInstanceCommandBuffer, int nPass, int nPassCount ) { }
// stuff related to matrix stacks
void CShaderAPIDx10::MatrixMode( MaterialMatrixMode_t matrixMode ) { }
void CShaderAPIDx10::PushMatrix() { }
void CShaderAPIDx10::PopMatrix() { }
void CShaderAPIDx10::LoadMatrix( float *m ) { }
void CShaderAPIDx10::MultMatrix( float *m ) { }
void CShaderAPIDx10::MultMatrixLocal( float *m ) { }
void CShaderAPIDx10::GetMatrix( MaterialMatrixMode_t matrixMode, float *dst ) { }
void CShaderAPIDx10::LoadIdentity( void ) { }
void CShaderAPIDx10::LoadCameraToWorld( void ) { }
void CShaderAPIDx10::Ortho( double left, double top, double right, double bottom, double zNear, double zFar ) { }
void CShaderAPIDx10::PerspectiveX( double fovx, double aspect, double zNear, double zFar ) { }
void CShaderAPIDx10::PerspectiveOffCenterX( double fovx, double aspect, double zNear, double zFar, double bottom, double top, double left, double right ) { }
void CShaderAPIDx10::PickMatrix( int x, int y, int width, int height ) { }
void CShaderAPIDx10::Rotate( float angle, float x, float y, float z ) { }
void CShaderAPIDx10::Translate( float x, float y, float z ) { }
void CShaderAPIDx10::Scale( float x, float y, float z ) { }
void CShaderAPIDx10::ScaleXY( float x, float y ) { }
// Fog methods...
void CShaderAPIDx10::FogMode( MaterialFogMode_t fogMode ) { }
void CShaderAPIDx10::FogStart( float fStart ) { }
void CShaderAPIDx10::FogEnd( float fEnd ) { }
void CShaderAPIDx10::SetFogZ( float fogZ ) { }
void CShaderAPIDx10::FogMaxDensity( float flMaxDensity ) { }
void CShaderAPIDx10::GetFogDistances( float *fStart, float *fEnd, float *fFogZ ) { }
void CShaderAPIDx10::SceneFogColor3ub( unsigned char r, unsigned char g, unsigned char b ) { }
void CShaderAPIDx10::SceneFogMode( MaterialFogMode_t fogMode ) { }
void CShaderAPIDx10::GetSceneFogColor( unsigned char *rgb ) { }
MaterialFogMode_t CShaderAPIDx10::GetSceneFogMode( ) { return MATERIAL_FOG_NONE; }
int CShaderAPIDx10::GetPixelFogCombo( ) { Assert( 0 ); // deprecated
return 0; //FIXME
}
void CShaderAPIDx10::FogColor3f( float r, float g, float b ) { }
void CShaderAPIDx10::FogColor3fv( float const* rgb ) { }
void CShaderAPIDx10::FogColor3ub( unsigned char r, unsigned char g, unsigned char b ) { }
void CShaderAPIDx10::FogColor3ubv( unsigned char const* rgb ) { }
void CShaderAPIDx10::Viewport( int x, int y, int width, int height ) { }
void CShaderAPIDx10::GetViewport( int& x, int& y, int& width, int& height ) const { }
// Sets the vertex and pixel shaders
void CShaderAPIDx10::SetVertexShaderIndex( int vshIndex ) { }
void CShaderAPIDx10::SetPixelShaderIndex( int pshIndex ) { }
// Sets the constant register for vertex and pixel shaders
void CShaderAPIDx10::SetVertexShaderConstant( int var, float const* pVec, int numConst, bool bForce ) { }
void CShaderAPIDx10::SetPixelShaderConstant( int var, float const* pVec, int numConst, bool bForce ) { }
void CShaderAPIDx10::InvalidateDelayedShaderConstants( void ) { }
//Set's the linear->gamma conversion textures to use for this hardware for both srgb writes enabled and disabled(identity)
void CShaderAPIDx10::SetLinearToGammaConversionTextures( ShaderAPITextureHandle_t hSRGBWriteEnabledTexture, ShaderAPITextureHandle_t hIdentityTexture ) { }
// Returns the nearest supported format
ImageFormat CShaderAPIDx10::GetNearestSupportedFormat( ImageFormat fmt, bool bFilteringRequired /* = true */ ) const { return fmt; }
ImageFormat CShaderAPIDx10::GetNearestRenderTargetFormat( ImageFormat fmt ) const { return fmt; }
// Sets the texture state
void CShaderAPIDx10::BindTexture( Sampler_t stage, ShaderAPITextureHandle_t textureHandle ) { }
// Sets the texture state
void CShaderAPIDx10::BindVertexTexture( VertexTextureSampler_t vtSampler, ShaderAPITextureHandle_t textureHandle ) { }
// Indicates we're going to be modifying this texture
// TexImage2D, TexSubImage2D, TexWrap, TexMinFilter, and TexMagFilter
// all use the texture specified by this function.
void CShaderAPIDx10::ModifyTexture( ShaderAPITextureHandle_t textureHandle ) { }
// Texture management methods
void CShaderAPIDx10::TexImage2D( int level, int cubeFace, ImageFormat dstFormat, int zOffset, int width, int height, ImageFormat srcFormat, bool bSrcIsTiled, void *imageData ) { }
void CShaderAPIDx10::TexSubImage2D( int level, int cubeFace, int xOffset, int yOffset, int zOffset, int width, int height, ImageFormat srcFormat, int srcStride, bool bSrcIsTiled, void *imageData ) { }
bool CShaderAPIDx10::TexLock( int level, int cubeFaceID, int xOffset, int yOffset, int width, int height, CPixelWriter& writer ) { return false; }
void CShaderAPIDx10::TexUnlock( ) { }
void CShaderAPIDx10::UpdateTexture( int xOffset, int yOffset, int w, int h, ShaderAPITextureHandle_t hDstTexture, ShaderAPITextureHandle_t hSrcTexture ) { }
void *CShaderAPIDx10::LockTex( ShaderAPITextureHandle_t hTexture ) { return NULL; }
void CShaderAPIDx10::UnlockTex( ShaderAPITextureHandle_t hTexture ) { }
// These are bound to the texture, not the texture environment
void CShaderAPIDx10::TexMinFilter( ShaderTexFilterMode_t texFilterMode ) { }
void CShaderAPIDx10::TexMagFilter( ShaderTexFilterMode_t texFilterMode ) { }
void CShaderAPIDx10::TexWrap( ShaderTexCoordComponent_t coord, ShaderTexWrapMode_t wrapMode ) { }
void CShaderAPIDx10::TexSetPriority( int priority ) { }
ShaderAPITextureHandle_t CShaderAPIDx10::CreateTexture( int width, int height, int depth, ImageFormat dstImageFormat, int numMipLevels, int numCopies, int flags, const char *pDebugName, const char *pTextureGroupName ) { ShaderAPITextureHandle_t handle; CreateTextures( &handle, 1, width, height, depth, dstImageFormat, numMipLevels, numCopies, flags, pDebugName, pTextureGroupName ); return handle; }
void CShaderAPIDx10::CreateTextures( ShaderAPITextureHandle_t *pHandles, int count, int width, int height, int depth, ImageFormat dstImageFormat, int numMipLevels, int numCopies, int flags, const char *pDebugName, const char *pTextureGroupName ) { for ( int k = 0; k < count; ++ k ) { pHandles[ k ] = 0; } }
ShaderAPITextureHandle_t CShaderAPIDx10::CreateDepthTexture( ImageFormat renderFormat, int width, int height, const char *pDebugName, bool bTexture ) { return 0; }
void CShaderAPIDx10::DeleteTexture( ShaderAPITextureHandle_t textureHandle ) { }
bool CShaderAPIDx10::IsTexture( ShaderAPITextureHandle_t textureHandle ) { return true; }
bool CShaderAPIDx10::IsTextureResident( ShaderAPITextureHandle_t textureHandle ) { return false; }
// stuff that isn't to be used from within a shader
void CShaderAPIDx10::ClearBuffersObeyStencil( bool bClearColor, bool bClearDepth ) { }
void CShaderAPIDx10::ClearBuffersObeyStencilEx( bool bClearColor, bool bClearAlpha, bool bClearDepth ) { }
void CShaderAPIDx10::PerformFullScreenStencilOperation( void ) { }
void CShaderAPIDx10::ReadPixels( int x, int y, int width, int height, unsigned char *data, ImageFormat dstFormat ) { }
void CShaderAPIDx10::ReadPixels( Rect_t *pSrcRect, Rect_t *pDstRect, unsigned char *data, ImageFormat dstFormat, int nDstStride ) { }
void CShaderAPIDx10::FlushHardware() { }
// Set the number of bone weights
void CShaderAPIDx10::SetNumBoneWeights( int numBones ) { }
// Selection mode methods
int CShaderAPIDx10::SelectionMode( bool selectionMode ) { return 0; }
void CShaderAPIDx10::SelectionBuffer( unsigned int* pBuffer, int size ) { }
void CShaderAPIDx10::ClearSelectionNames( ) { }
void CShaderAPIDx10::LoadSelectionName( int name ) { }
void CShaderAPIDx10::PushSelectionName( int name ) { }
void CShaderAPIDx10::PopSelectionName() { }
// Board-independent calls, here to unify how shaders set state
// Implementations should chain back to IShaderUtil->BindTexture(), etc.
// Use this to begin and end the frame
void CShaderAPIDx10::BeginFrame() { }
void CShaderAPIDx10::EndFrame() { }
// returns the current time in seconds....
double CShaderAPIDx10::CurrentTime() const { return Sys_FloatTime(); }
// Get the current camera position in world space.
void CShaderAPIDx10::GetWorldSpaceCameraPosition( float* pPos ) const { }
// Get the current camera position in world space.
void CShaderAPIDx10::GetWorldSpaceCameraDirection( float* pDir ) const { }
void CShaderAPIDx10::ForceHardwareSync( void ) { }
void CShaderAPIDx10::SetClipPlane( int index, const float *pPlane ) { }
void CShaderAPIDx10::EnableClipPlane( int index, bool bEnable ) { }
void CShaderAPIDx10::SetFastClipPlane( const float *pPlane ) { }
void CShaderAPIDx10::EnableFastClip( bool bEnable ) { }
int CShaderAPIDx10::GetCurrentNumBones( void ) const { return 0; }
// Is hardware morphing enabled?
bool CShaderAPIDx10::IsHWMorphingEnabled( ) const { return false; }
TessellationMode_t CShaderAPIDx10::GetTessellationMode( ) const { return TESSELLATION_MODE_DISABLED; }
int CShaderAPIDx10::GetCurrentLightCombo( void ) const { return 0; }
int CShaderAPIDx10::MapLightComboToPSLightCombo( int nLightCombo ) const { return 0; }
MaterialFogMode_t CShaderAPIDx10::GetCurrentFogType( void ) const { Assert( 0 ); // deprecated
return MATERIAL_FOG_NONE; }
void CShaderAPIDx10::RecordString( const char *pStr ) { }
void CShaderAPIDx10::DestroyVertexBuffers( bool bExitingLevel ) { }
int CShaderAPIDx10::GetCurrentDynamicVBSize( void ) { return 0; }
void CShaderAPIDx10::EvictManagedResources() { }
void CShaderAPIDx10::GetGPUMemoryStats( GPUMemoryStats &stats ) { // stub (let's face it, DX10 ain't happenin)
memset( &stats, 0, sizeof( stats ) ); }
void CShaderAPIDx10::ReleaseShaderObjects( bool bReleaseManagedResources /*= true*/ ) { }
void CShaderAPIDx10::RestoreShaderObjects() { }
void CShaderAPIDx10::SyncToken( const char *pToken ) { }
void CShaderAPIDx10::OnPresent( void ) { // not implemented
Assert( 0 ); }
|