mirror of
https://github.com/celisej567/cool-source-archive.git
synced 2026-09-15 20:09:19 +03:00
3965 lines
110 KiB
C++
3965 lines
110 KiB
C++
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
|
//
|
|
// Purpose: ShaderAPIDx11 implementation
|
|
//
|
|
// $NoKeywords: $
|
|
//
|
|
//===========================================================================//
|
|
|
|
// HUH???
|
|
#define RAD_TELEMETRY_DISABLED
|
|
|
|
#include "shaderapidx11.h"
|
|
#include "shaderapidx9/shaderapibase.h"
|
|
#include "shaderapi/ishaderutil.h"
|
|
#include "shaderapi/commandbuffer.h"
|
|
#include "materialsystem/idebugtextureinfo.h"
|
|
#include "materialsystem/materialsystem_config.h"
|
|
#include "materialsystem/imorph.h"
|
|
#include "meshdx11.h"
|
|
#include "shadershadowdx11.h"
|
|
#include "shaderdevicedx11.h"
|
|
#include "shaderapidx11_global.h"
|
|
#include "imaterialinternal.h"
|
|
#include "ShaderConstantBufferDx11.h"
|
|
#include "vertexshaderdx11.h"
|
|
#include "VertexBufferDx11.h"
|
|
#include "IndexBufferDx11.h"
|
|
#include "materialsystem/IShader.h"
|
|
#include "../stdshaders/cpp_shader_constant_register_map.h"
|
|
#include "Dx11Global.h"
|
|
#include "ITextureInternal.h"
|
|
|
|
// NOTE: This has to be the last file included!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
template<typename T>
|
|
FORCEINLINE static void XMSetComponent4( T &vec, int comp, float val )
|
|
{
|
|
switch ( comp )
|
|
{
|
|
case 0:
|
|
vec.x = val;
|
|
break;
|
|
case 1:
|
|
vec.y = val;
|
|
break;
|
|
case 2:
|
|
vec.z = val;
|
|
break;
|
|
case 3:
|
|
vec.w = val;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
// Common constant buffers, grouped by frequency of update.
|
|
// NOTE: These need to match the cbuffers in common_cbuffers_fxc.h!!!
|
|
//-------------------------------------------------------------------
|
|
|
|
// In order of most frequent to least frequent...
|
|
|
|
// NOTE: ShaderAPI is not responsible for constant buffers
|
|
// that change every material/draw call/shader, but the shader
|
|
// class itself.
|
|
|
|
ALIGN16 struct DX11LightInfo_t
|
|
{
|
|
DirectX::XMFLOAT4 color;
|
|
DirectX::XMFLOAT4 dir;
|
|
DirectX::XMFLOAT4 pos;
|
|
DirectX::XMFLOAT4 spotParams;
|
|
DirectX::XMFLOAT4 atten;
|
|
};
|
|
|
|
// Constants that can be expected to change for each model.
|
|
ALIGN16 struct PerModel_CBuffer_t
|
|
{
|
|
DirectX::XMMATRIX cModelMatrix; // If using skinning, same as cModel[0]
|
|
// Four lights x 5 constants each = 20 constants
|
|
DX11LightInfo_t cLightInfo[4];
|
|
DirectX::XMINT4 cLightCount;
|
|
DirectX::XMFLOAT3A cAmbientCube[6];
|
|
};
|
|
|
|
// These were split from per-model because they are big
|
|
|
|
ALIGN16 struct Skinning_CBuffer_t
|
|
{
|
|
DirectX::XMFLOAT3X4A cModel[53];
|
|
};
|
|
|
|
ALIGN16 struct Flex_CBuffer_t
|
|
{
|
|
DirectX::XMFLOAT4 cFlexWeights[512];
|
|
};
|
|
|
|
// Constants that can be expected to change each frame.
|
|
// TODO: Can we save a constant by having the vertex shader
|
|
// extract the eye position from the viewmatrix?
|
|
ALIGN16 struct PerFrame_CBuffer_t
|
|
{
|
|
DirectX::XMMATRIX cViewMatrix;
|
|
DirectX::XMFLOAT4 cEyePos;
|
|
DirectX::XMFLOAT4 cTonemappingScale;
|
|
DirectX::XMFLOAT4 cFlashlightPos;
|
|
};
|
|
|
|
// Constants that don't change per-material, per-model, or per-frame.
|
|
// These are expected to be changed whenever and apply to all materials.
|
|
// TODO: Figure out how often these flashlight parameters change,
|
|
// particularly cFlashlightWorldToTexture.
|
|
ALIGN16 struct PerScene_CBuffer_t
|
|
{
|
|
DirectX::XMMATRIX cProjMatrix;
|
|
DirectX::XMMATRIX cFlashlightWorldToTexture;
|
|
DirectX::XMFLOAT4 cFlashlightScreenScale;
|
|
DirectX::XMFLOAT4 cFlashlightColor;
|
|
DirectX::XMFLOAT4 cFlashlightAttenuationFactors;
|
|
DirectX::XMFLOAT4 cShadowTweaks;
|
|
DirectX::XMFLOAT4 cConstants;
|
|
// Only cFlexScale.x is used
|
|
// It is a binary value used to switch on/off the addition of the flex delta stream
|
|
DirectX::XMFLOAT4 cFlexScale;
|
|
// NOTE: Fog has moved to per-material constants, defined and requested by each shader.
|
|
};
|
|
|
|
enum
|
|
{
|
|
MATRIXDX11_DIRTY,
|
|
MATRIXDX11_IDENTITY,
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Shader API Dx11
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Class Factory
|
|
//-----------------------------------------------------------------------------
|
|
static CShaderAPIDx11 s_ShaderAPIDx11;
|
|
CShaderAPIDx11 *g_pShaderAPIDx11 = &s_ShaderAPIDx11;
|
|
|
|
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CShaderAPIDx11, IShaderAPI,
|
|
SHADERAPI_INTERFACE_VERSION, s_ShaderAPIDx11 )
|
|
|
|
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CShaderAPIDx11, IDebugTextureInfo,
|
|
DEBUG_TEXTURE_INFO_VERSION, s_ShaderAPIDx11 )
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constructor, destructor
|
|
//-----------------------------------------------------------------------------
|
|
CShaderAPIDx11::CShaderAPIDx11() :
|
|
m_Textures( 32 ),
|
|
m_SelectionMinZ( FLT_MAX ),
|
|
m_SelectionMaxZ( FLT_MIN ),
|
|
m_pSelectionBuffer( 0 ),
|
|
m_pSelectionBufferEnd( 0 ),
|
|
m_nDynamicVBSize( DYNAMIC_VERTEX_BUFFER_MEMORY ),
|
|
m_TexAnisotropy( 0 )
|
|
{
|
|
m_ModifyTextureHandle = INVALID_SHADERAPI_TEXTURE_HANDLE;
|
|
m_ModifyTextureLockedLevel = -1;
|
|
m_ModifyTextureLockedFace = -1;
|
|
m_bResettingRenderState = false;
|
|
m_ShadowState = NULL;
|
|
m_ShaderState = StatesDx11::ShaderState();
|
|
m_DynamicState = StatesDx11::DynamicState();
|
|
m_StateChangeFlags = STATE_CHANGED_NONE;
|
|
m_bSelectionMode = false;
|
|
m_bFlashlightStateChanged = false;
|
|
m_pFlashlightDepthTexture = NULL;
|
|
|
|
m_CurrentSnapshot = DEFAULT_SHADOW_STATE_ID;
|
|
|
|
memset( IntRenderingParameters, 0, sizeof( IntRenderingParameters ) );
|
|
memset( FloatRenderingParameters, 0, sizeof( FloatRenderingParameters ) );
|
|
memset( VectorRenderingParameters, 0, sizeof( VectorRenderingParameters ) );
|
|
}
|
|
|
|
CShaderAPIDx11::~CShaderAPIDx11()
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::UpdateConstantBuffer( ConstantBufferHandle_t cbuffer, void *pNewData )
|
|
{
|
|
g_pShaderDeviceDx11->UpdateConstantBuffer( cbuffer, pNewData );
|
|
}
|
|
|
|
ConstantBufferHandle_t CShaderAPIDx11::GetInternalConstantBuffer( int type )
|
|
{
|
|
switch ( type )
|
|
{
|
|
case SHADER_CONSTANTBUFFER_PERFRAME:
|
|
return m_hPerFrameConstants;
|
|
case SHADER_CONSTANTBUFFER_PERMODEL:
|
|
return m_hPerModelConstants;
|
|
case SHADER_CONSTANTBUFFER_PERSCENE:
|
|
return m_hPerSceneConstants;
|
|
case SHADER_CONSTANTBUFFER_SKINNING:
|
|
return m_hSkinningConstants;
|
|
//case SHADER_CONSTANTBUFFER_FLEX:
|
|
// return m_hFlexConstants;
|
|
default:
|
|
return CONSTANT_BUFFER_HANDLE_INVALID;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Resets the render state
|
|
//-----------------------------------------------------------------------------
|
|
void CShaderAPIDx11::ResetRenderState( bool bFullReset )
|
|
{
|
|
m_StateChangeFlags = STATE_CHANGED_NONE;
|
|
m_ShadowState = NULL;
|
|
m_CurrentSnapshot = DEFAULT_SHADOW_STATE_ID;
|
|
m_DynamicState.Reset();
|
|
m_DynamicState.m_pDepthStencilView = GetTexture( m_hDepthBuffer ).GetDepthStencilView();
|
|
|
|
m_ShaderState.SetDefault();
|
|
m_pCurMatrixItem = &m_ShaderState.m_MatrixStacks[0].Top();
|
|
|
|
IssueStateChanges( bFullReset );
|
|
}
|
|
|
|
void CShaderAPIDx11::SetRenderTargetEx( int nRenderTargetID, ShaderAPITextureHandle_t colorTextureHandle, ShaderAPITextureHandle_t depthTextureHandle )
|
|
{
|
|
// GR - need to flush batched geometry
|
|
FlushBufferedPrimitives();
|
|
|
|
if ( colorTextureHandle == SHADER_RENDERTARGET_BACKBUFFER )
|
|
{
|
|
colorTextureHandle = m_hBackBuffer;
|
|
}
|
|
else if ( colorTextureHandle == SHADER_RENDERTARGET_NONE )
|
|
{
|
|
colorTextureHandle = INVALID_SHADERAPI_TEXTURE_HANDLE;
|
|
}
|
|
|
|
if ( depthTextureHandle == SHADER_RENDERTARGET_DEPTHBUFFER )
|
|
{
|
|
depthTextureHandle = m_hDepthBuffer;
|
|
}
|
|
else if ( depthTextureHandle == SHADER_RENDERTARGET_NONE )
|
|
{
|
|
depthTextureHandle = INVALID_SHADERAPI_TEXTURE_HANDLE;
|
|
}
|
|
|
|
if ( colorTextureHandle != INVALID_SHADERAPI_TEXTURE_HANDLE )
|
|
{
|
|
CTextureDx11 *pRT = &GetTexture( colorTextureHandle );
|
|
m_DynamicState.m_pRenderTargetViews[nRenderTargetID] = pRT->GetRenderTargetView();
|
|
SetStateFlag( STATE_CHANGED_RENDERTARGET );
|
|
}
|
|
else
|
|
{
|
|
m_DynamicState.m_pRenderTargetViews[nRenderTargetID] = NULL;
|
|
}
|
|
|
|
if ( depthTextureHandle != INVALID_SHADERAPI_TEXTURE_HANDLE )
|
|
{
|
|
CTextureDx11 *pDT = &GetTexture( depthTextureHandle );
|
|
m_DynamicState.m_pDepthStencilView = pDT->GetDepthStencilView();
|
|
SetStateFlag( STATE_CHANGED_DEPTHBUFFER );
|
|
}
|
|
else
|
|
{
|
|
m_DynamicState.m_pDepthStencilView = NULL;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Issues state changes to D3D for states that have been modified
|
|
//-----------------------------------------------------------------------------
|
|
void CShaderAPIDx11::IssueStateChanges( bool bForce )
|
|
{
|
|
// Don't bother committing anything if we're deactivated
|
|
if ( g_pShaderDeviceDx11->IsDeactivated() )
|
|
return;
|
|
|
|
m_ShadowState = g_pShaderShadowDx11->GetShadowState( m_CurrentSnapshot );
|
|
//const StatesDx11::ShadowState *shadow = m_ShadowState;
|
|
StatesDx11::DynamicState &dynamic = m_DynamicState;
|
|
|
|
DoIssueShaderState( bForce );
|
|
|
|
if ( bForce || IsStateSet( STATE_CHANGED_RENDERTARGET ) ||
|
|
IsStateSet( STATE_CHANGED_DEPTHBUFFER ) )
|
|
{
|
|
DoIssueRenderTargets();
|
|
}
|
|
|
|
if ( bForce || IsStateSet( STATE_CHANGED_VIEWPORTS ) )
|
|
{
|
|
DoIssueViewports();
|
|
}
|
|
|
|
if ( bForce || IsStateSet( STATE_CHANGED_INPUTLAYOUT ) )
|
|
{
|
|
DoIssueInputLayout();
|
|
}
|
|
|
|
if ( bForce || IsStateSet( STATE_CHANGED_VERTEXBUFFER ) )
|
|
{
|
|
DoIssueVertexBuffer();
|
|
}
|
|
|
|
if ( bForce || IsStateSet( STATE_CHANGED_INDEXBUFFER ) )
|
|
{
|
|
DoIssueIndexBuffer();
|
|
}
|
|
|
|
if ( bForce || IsStateSet( STATE_CHANGED_TOPOLOGY ) )
|
|
{
|
|
DoIssueTopology();
|
|
}
|
|
|
|
if ( bForce || IsStateSet( STATE_CHANGED_VERTEXSHADER ) )
|
|
{
|
|
DoIssueVertexShader();
|
|
}
|
|
|
|
if ( bForce || IsStateSet( STATE_CHANGED_GEOMETRYSHADER ) )
|
|
{
|
|
DoIssueGeometryShader();
|
|
}
|
|
|
|
if ( bForce || IsStateSet( STATE_CHANGED_PIXELSHADER ) )
|
|
{
|
|
DoIssuePixelShader();
|
|
}
|
|
|
|
DoIssueConstantBuffers( bForce );
|
|
|
|
bool bPixel = bForce || IsStateSet( STATE_CHANGED_SAMPLERS );
|
|
bool bVertex = bForce || IsStateSet( STATE_CHANGED_VERTEXSAMPLERS );
|
|
if ( bPixel || bVertex )
|
|
{
|
|
DoIssueSampler( bPixel, bVertex );
|
|
dynamic.m_PrevMaxPSSampler = dynamic.m_MaxPSSampler;
|
|
dynamic.m_PrevMaxVSSampler = dynamic.m_MaxVSSampler;
|
|
}
|
|
|
|
bPixel = bForce || IsStateSet( STATE_CHANGED_TEXTURES );
|
|
bVertex = bForce || IsStateSet( STATE_CHANGED_VERTEXTEXTURES );
|
|
if ( bPixel || bVertex )
|
|
{
|
|
DoIssueTexture( bPixel, bVertex );
|
|
}
|
|
|
|
if ( bForce ||
|
|
IsStateSet( STATE_CHANGED_DEPTHSTENCIL ) )
|
|
{
|
|
DoIssueDepthStencilState();
|
|
}
|
|
|
|
if ( bForce ||
|
|
IsStateSet( STATE_CHANGED_BLEND ) )
|
|
{
|
|
DoIssueBlendState();
|
|
}
|
|
|
|
if ( bForce ||
|
|
IsStateSet( STATE_CHANGED_RASTERIZER ) )
|
|
{
|
|
DoIssueRasterState();
|
|
}
|
|
|
|
m_StateChangeFlags = STATE_CHANGED_NONE;
|
|
|
|
m_ShadowState = NULL;
|
|
}
|
|
|
|
//------------------------------
|
|
// Issue state changes
|
|
//------------------------------
|
|
|
|
FORCEINLINE static void OutputMatrixRow( const DirectX::XMFLOAT4X4 &mat, int r )
|
|
{
|
|
Log( "\t%f\t%f\t%f\t%f\n", mat.m[r][0], mat.m[r][1], mat.m[r][2], mat.m[r][3] );
|
|
}
|
|
|
|
FORCEINLINE static void OutputMatrix( const DirectX::XMFLOAT4X4 &mat, const char *pszMatName )
|
|
{
|
|
Log( "DX11 %s Matrix:\n", pszMatName );
|
|
|
|
for ( int i = 0; i < 4; i++ )
|
|
{
|
|
OutputMatrixRow( mat, i );
|
|
}
|
|
}
|
|
|
|
int CShaderAPIDx11::ComputeNumLights() const
|
|
{
|
|
int numLights = 0;
|
|
for ( int i = 0; i < MAX_NUM_LIGHTS; i++ )
|
|
{
|
|
if ( m_ShaderState.light.m_Lights[i].m_Type != MATERIAL_LIGHT_DISABLE )
|
|
numLights++;
|
|
}
|
|
return numLights;
|
|
}
|
|
|
|
void CShaderAPIDx11::SortLights( int *index )
|
|
{
|
|
m_ShaderState.light.m_NumLights = 0;
|
|
for ( int i = 0; i < MAX_NUM_LIGHTS; i++ )
|
|
{
|
|
const LightDesc_t &light = m_ShaderState.light.m_Lights[i];
|
|
LightType_t type = light.m_Type;
|
|
int j = m_ShaderState.light.m_NumLights;
|
|
if ( type != MATERIAL_LIGHT_DISABLE )
|
|
{
|
|
while ( --j >= 0 )
|
|
{
|
|
if ( m_ShaderState.light.m_LightType[j] <= type )
|
|
break;
|
|
|
|
// shift...
|
|
m_ShaderState.light.m_LightType[j + 1] = m_ShaderState.light.m_LightType[j];
|
|
if ( index )
|
|
index[j + 1] = index[j];
|
|
}
|
|
++j;
|
|
|
|
m_ShaderState.light.m_LightType[j] = type;
|
|
if ( index )
|
|
index[j] = i;
|
|
++m_ShaderState.light.m_NumLights;
|
|
}
|
|
}
|
|
}
|
|
|
|
FORCEINLINE static float ShadowAttenFromState( FlashlightState_t const &state )
|
|
{
|
|
// DX10 requires some hackery due to sRGB/blend ordering change from DX9, which makes the shadows too light
|
|
if ( g_pHardwareConfig->UsesSRGBCorrectBlending() )
|
|
return state.m_flShadowAtten * 0.1f; // magic number
|
|
|
|
return state.m_flShadowAtten;
|
|
}
|
|
|
|
FORCEINLINE static float ShadowFilterFromState( FlashlightState_t const &state )
|
|
{
|
|
return state.m_flShadowFilterSize / state.m_flShadowMapResolution;
|
|
}
|
|
|
|
FORCEINLINE static void HashShadow2DJitter( const float fJitterSeed, float *fU, float *fV )
|
|
{
|
|
const int nTexRes = 32;
|
|
int nSeed = fmod( fJitterSeed, 1.0f ) * nTexRes * nTexRes;
|
|
|
|
int nRow = nSeed / nTexRes;
|
|
int nCol = nSeed % nTexRes;
|
|
|
|
// Div and mod to get an individual texel in the fTexRes x fTexRes grid
|
|
*fU = nRow / (float)nTexRes; // Row
|
|
*fV = nCol / (float)nTexRes; // Column
|
|
}
|
|
|
|
void CShaderAPIDx11::DoIssueShaderState( bool bForce )
|
|
{
|
|
//
|
|
// Transforms
|
|
//
|
|
|
|
bool bViewChanged = m_ShaderState.m_ChangedMatrices[MATERIAL_VIEW];
|
|
bool bProjChanged = m_ShaderState.m_ChangedMatrices[MATERIAL_PROJECTION];
|
|
bool bModelChanged = m_ShaderState.m_ChangedMatrices[MATERIAL_MODEL];
|
|
|
|
PerFrame_CBuffer_t *pPerFrameConstants;
|
|
PerModel_CBuffer_t *pPerModelConstants;
|
|
PerScene_CBuffer_t *pPerSceneConstants;
|
|
//{
|
|
//VPROF_BUDGET( "GetCBufferPointers", VPROF_BUDGETGROUP_OTHER_UNACCOUNTED );
|
|
|
|
// To avoid an extra memcmp + memcpy...
|
|
pPerFrameConstants = (PerFrame_CBuffer_t *)
|
|
( (CShaderConstantBufferDx11 *)m_hPerFrameConstants )->GetData();
|
|
pPerModelConstants = (PerModel_CBuffer_t *)
|
|
( (CShaderConstantBufferDx11 *)m_hPerModelConstants )->GetData();
|
|
pPerSceneConstants = (PerScene_CBuffer_t *)
|
|
( (CShaderConstantBufferDx11 *)m_hPerSceneConstants )->GetData();
|
|
//}
|
|
|
|
|
|
bool bPerFrameChanged = false;
|
|
bool bPerModelChanged = false;
|
|
bool bPerSceneChanged = false;
|
|
|
|
if ( bForce || bViewChanged )
|
|
{
|
|
//VPROF_BUDGET( "CShaderAPIDx11::IssueViewMatrix", VPROF_BUDGETGROUP_OTHER_UNACCOUNTED );
|
|
|
|
#ifdef _DEBUG
|
|
const DirectX::XMMATRIX view = GetMatrix( MATERIAL_VIEW );
|
|
#else
|
|
const DirectX::XMMATRIX &view = GetMatrix( MATERIAL_VIEW );
|
|
#endif
|
|
// Row-major -> column-major
|
|
pPerFrameConstants->cViewMatrix = DirectX::XMMatrixTranspose( view );
|
|
|
|
// Store new view position.
|
|
DirectX::XMFLOAT4X4 flt4x4view;
|
|
DirectX::XMStoreFloat4x4( &flt4x4view, DirectX::XMMatrixInverse( NULL, view ) );
|
|
pPerFrameConstants->cEyePos.x = flt4x4view.m[3][0];
|
|
pPerFrameConstants->cEyePos.y = flt4x4view.m[3][1];
|
|
pPerFrameConstants->cEyePos.z = flt4x4view.m[3][2];
|
|
|
|
m_ShaderState.m_ChangedMatrices[MATERIAL_VIEW] = false;
|
|
|
|
bPerFrameChanged = true;
|
|
}
|
|
|
|
if ( bForce || bModelChanged )
|
|
{
|
|
//VPROF_BUDGET( "CShaderAPIDx11::IssueModelMatrix", VPROF_BUDGETGROUP_OTHER_UNACCOUNTED );
|
|
|
|
#ifdef _DEBUG
|
|
const DirectX::XMMATRIX model = GetMatrix( MATERIAL_MODEL );
|
|
#else
|
|
const DirectX::XMMATRIX &model = GetMatrix( MATERIAL_MODEL );
|
|
#endif
|
|
// Row-major -> column-major
|
|
pPerModelConstants->cModelMatrix = DirectX::XMMatrixTranspose( model );
|
|
|
|
m_ShaderState.m_ChangedMatrices[MATERIAL_MODEL] = false;
|
|
|
|
bPerModelChanged = true;
|
|
}
|
|
|
|
if ( bForce || bProjChanged )
|
|
{
|
|
//VPROF_BUDGET( "CShaderAPIDx11::IssueProjMatrix", VPROF_BUDGETGROUP_OTHER_UNACCOUNTED );
|
|
|
|
#ifdef _DEBUG
|
|
const DirectX::XMMATRIX proj = GetMatrix( MATERIAL_PROJECTION );
|
|
#else
|
|
const DirectX::XMMATRIX &proj = GetMatrix( MATERIAL_PROJECTION );
|
|
#endif
|
|
// Row-major -> column-major
|
|
pPerSceneConstants->cProjMatrix = DirectX::XMMatrixTranspose( proj );
|
|
|
|
m_ShaderState.m_ChangedMatrices[MATERIAL_PROJECTION] = false;
|
|
|
|
bPerSceneChanged = true;
|
|
}
|
|
|
|
//
|
|
// Lighting
|
|
//
|
|
|
|
if ( bForce || m_ShaderState.light.m_bLightChanged )
|
|
{
|
|
//VPROF_BUDGET( "CShaderAPIDx11::IssueLightState", VPROF_BUDGETGROUP_OTHER_UNACCOUNTED );
|
|
|
|
int lightIndex[MAX_NUM_LIGHTS];
|
|
memset( lightIndex, 0, sizeof( lightIndex ) );
|
|
SortLights( lightIndex );
|
|
|
|
pPerModelConstants->cLightCount.x = m_ShaderState.light.m_NumLights;
|
|
|
|
//if ( m_ShaderState.light.m_NumLights == 0 )
|
|
//{
|
|
// memset( &pPerModelConstants->cLightEnabled, 0, sizeof( DirectX::XMINT4 ) );
|
|
//}
|
|
|
|
for ( int i = 0; i < m_ShaderState.light.m_NumLights; i++ )
|
|
{
|
|
const LightDesc_t &light = m_ShaderState.light.m_Lights[lightIndex[i]];
|
|
//XMSetComponent4( pPerModelConstants->cLightEnabled, i, light.m_Type != MATERIAL_LIGHT_DISABLE );
|
|
|
|
// The first one is the light color ( and light type code )
|
|
float w = ( light.m_Type == MATERIAL_LIGHT_DIRECTIONAL ) ? 1.0f : 0.0f;
|
|
pPerModelConstants->cLightInfo[i].color =
|
|
DirectX::XMFLOAT4( light.m_Color.x, light.m_Color.y, light.m_Color.z, w );
|
|
|
|
// The next constant holds the light direction ( and light type code )
|
|
w = ( light.m_Type == MATERIAL_LIGHT_SPOT ) ? 1.0f : 0.0f;
|
|
pPerModelConstants->cLightInfo[i].dir =
|
|
DirectX::XMFLOAT4( light.m_Direction.x, light.m_Direction.y, light.m_Direction.z, w );
|
|
|
|
// The next constant holds the light position
|
|
pPerModelConstants->cLightInfo[i].pos =
|
|
DirectX::XMFLOAT4( light.m_Position.x, light.m_Position.y, light.m_Position.z, 1.0f );
|
|
|
|
// The next constant holds exponent, stopdot, stopdot2, 1 / (stopdot - stopdot2)
|
|
if ( light.m_Type == MATERIAL_LIGHT_SPOT )
|
|
{
|
|
float stopdot = cos( light.m_Theta * 0.5f );
|
|
float stopdot2 = cos( light.m_Phi * 0.5f );
|
|
float oodot = ( stopdot > stopdot2 ) ? 1.0f / ( stopdot - stopdot2 ) : 0.0f;
|
|
pPerModelConstants->cLightInfo[i].spotParams =
|
|
DirectX::XMFLOAT4( light.m_Falloff, stopdot, stopdot2, oodot );
|
|
}
|
|
else
|
|
{
|
|
pPerModelConstants->cLightInfo[i].spotParams =
|
|
DirectX::XMFLOAT4( 0, 1, 1, 1 );
|
|
}
|
|
|
|
// The last constant holds atten0, atten1, atten2
|
|
pPerModelConstants->cLightInfo[i].atten =
|
|
DirectX::XMFLOAT4( light.m_Attenuation0, light.m_Attenuation1, light.m_Attenuation2, 0.0f );
|
|
}
|
|
m_ShaderState.light.m_bLightChanged = false;
|
|
|
|
bPerModelChanged = true;
|
|
}
|
|
|
|
if ( bForce || m_ShaderState.light.m_bAmbientChanged )
|
|
{
|
|
//VPROF_BUDGET( "CShaderAPIDx11::IssueAmbientState", VPROF_BUDGETGROUP_OTHER_UNACCOUNTED );
|
|
memcpy( pPerModelConstants->cAmbientCube, m_ShaderState.light.m_AmbientLightCube, sizeof( DirectX::XMFLOAT3A ) * 6 );
|
|
m_ShaderState.light.m_bAmbientChanged = false;
|
|
bPerModelChanged = true;
|
|
}
|
|
|
|
//
|
|
// Skinning
|
|
//
|
|
|
|
if ( bForce || m_ShaderState.bone.m_bBonesChanged )
|
|
{
|
|
//VPROF_BUDGET( "CShaderAPIDx11::IssueBoneState", VPROF_BUDGETGROUP_OTHER_UNACCOUNTED );
|
|
|
|
// Since skinning is in it's own constant buffer and we are updating the whole
|
|
// thing if bones have changed, be more efficient and lock the buffer to
|
|
// avoid an extra memcpy.
|
|
|
|
Skinning_CBuffer_t *pSkinningConstants = (Skinning_CBuffer_t *)
|
|
( (CShaderConstantBufferDx11 *)m_hSkinningConstants )->Lock();
|
|
|
|
// Load the model matrix from the matrix stack into the
|
|
// first bone matrix.
|
|
DirectX::XMMATRIX model = GetMatrix( MATERIAL_MODEL );
|
|
// This is stored row-major, needs to be column-major in shader.
|
|
// 3x4 in DirectXMath becomes 4x3 in HLSL shader
|
|
DirectX::XMStoreFloat3x4A( m_ShaderState.bone.m_BoneMatrix, model );
|
|
m_ShaderState.bone.m_MaxBoneLoaded++;
|
|
int matricesLoaded = max( 1, m_ShaderState.bone.m_MaxBoneLoaded );
|
|
m_ShaderState.bone.m_MaxBoneLoaded = 0;
|
|
|
|
// Copy bone matrices into cModel constant
|
|
memcpy( pSkinningConstants->cModel, m_ShaderState.bone.m_BoneMatrix,
|
|
sizeof( DirectX::XMFLOAT3X4A ) * matricesLoaded );
|
|
|
|
m_ShaderState.bone.m_bBonesChanged = false;
|
|
|
|
( (CShaderConstantBufferDx11 *)m_hSkinningConstants )->Unlock();
|
|
}
|
|
|
|
//
|
|
// Morphing
|
|
//
|
|
if ( bForce || m_ShaderState.morph.m_bMorphChanged )
|
|
{
|
|
//VPROF_BUDGET( "CShaderAPIDx11::IssueMorphState", VPROF_BUDGETGROUP_OTHER_UNACCOUNTED );
|
|
|
|
// Since flex is in it's own constant buffer and we are updating the whole
|
|
// thing if flex has changed, be more efficient and lock the buffer to
|
|
// avoid an extra memcpy.
|
|
|
|
//Flex_CBuffer_t *pFlexConstants = (Flex_CBuffer_t *)
|
|
// ( (CShaderConstantBufferDx11 *)m_hFlexConstants )->Lock();
|
|
|
|
//memcpy( pFlexConstants->cFlexWeights, m_ShaderState.morph.m_pWeights,
|
|
// sizeof( MorphWeight_t ) * m_ShaderState.morph.m_nMaxWeightLoaded );
|
|
//m_ShaderState.morph.m_nMaxWeightLoaded = 0;
|
|
//pPerModelConstants->cFlexScale = DirectX::XMFLOAT4( 0.0f, 0.0f, 0.0f, 0.0f );
|
|
//m_ShaderState.morph.m_bMorphChanged = false;
|
|
|
|
//bPerModelChanged = true;
|
|
|
|
//( (CShaderConstantBufferDx11 *)m_hFlexConstants )->Unlock();
|
|
}
|
|
|
|
//
|
|
// Flashlight
|
|
//
|
|
if ( m_bFlashlightStateChanged )
|
|
{
|
|
//VPROF_BUDGET( "CShaderAPIDx11::IssueFlashLightState", VPROF_BUDGETGROUP_OTHER_UNACCOUNTED );
|
|
|
|
float flFlashlightScale = 0.25f;
|
|
if ( !g_pHardwareConfig->GetHDREnabled() )
|
|
{
|
|
// Non-HDR path requires 2.0 flashlight
|
|
flFlashlightScale = 2.0f;
|
|
}
|
|
// DX10 requires some hackery due to sRGB/blend ordering change from DX9
|
|
if ( g_pHardwareConfig->UsesSRGBCorrectBlending() )
|
|
{
|
|
flFlashlightScale *= 2.5f; // Magic number that works well on the NVIDIA 8800
|
|
}
|
|
float const *pFlashlightColor = m_FlashlightState.m_Color;
|
|
float vPsConst[4] = { flFlashlightScale * pFlashlightColor[0], flFlashlightScale * pFlashlightColor[1],
|
|
flFlashlightScale * pFlashlightColor[2], pFlashlightColor[3] };
|
|
vPsConst[3] = 0.0f; // This will be added to N.L before saturate to force a 1.0 N.L term
|
|
pPerSceneConstants->cFlashlightColor = DirectX::XMFLOAT4( vPsConst );
|
|
DirectX::XMFLOAT4X4 flashlightWorldToTexture4x4 = DirectX::XMFLOAT4X4( m_FlashlightWorldToTexture.Base() );
|
|
pPerSceneConstants->cFlashlightWorldToTexture = DirectX::XMLoadFloat4x4( &flashlightWorldToTexture4x4 );
|
|
// Dimensions of screen, used for screen-space noise map sampling
|
|
float vScreenScale[4] = { 1280.0f / 32.0f, 720.0f / 32.0f, 0, 0 };
|
|
int nWidth, nHeight;
|
|
GetBackBufferDimensions( nWidth, nHeight );
|
|
vScreenScale[0] = (float)nWidth / 32.0f;
|
|
vScreenScale[1] = (float)nHeight / 32.0f;
|
|
pPerSceneConstants->cFlashlightScreenScale = DirectX::XMFLOAT4( vScreenScale );
|
|
// Tweaks associated with a given flashlight
|
|
float tweaks[4];
|
|
tweaks[0] = m_FlashlightState.m_flShadowFilterSize / m_FlashlightState.m_flShadowMapResolution;
|
|
tweaks[1] = ShadowAttenFromState( m_FlashlightState );
|
|
HashShadow2DJitter( m_FlashlightState.m_flShadowJitterSeed, &tweaks[2], &tweaks[3] );
|
|
pPerSceneConstants->cShadowTweaks = DirectX::XMFLOAT4( tweaks );
|
|
pPerFrameConstants->cFlashlightPos = DirectX::XMFLOAT4( m_FlashlightState.m_vecLightOrigin[0],
|
|
m_FlashlightState.m_vecLightOrigin[1],
|
|
m_FlashlightState.m_vecLightOrigin[2],
|
|
1.0f );
|
|
pPerSceneConstants->cFlashlightAttenuationFactors = DirectX::XMFLOAT4(
|
|
m_FlashlightState.m_fConstantAtten,
|
|
m_FlashlightState.m_fLinearAtten,
|
|
m_FlashlightState.m_fQuadraticAtten,
|
|
m_FlashlightState.m_FarZ
|
|
);
|
|
|
|
bPerSceneChanged = true;
|
|
bPerFrameChanged = true;
|
|
|
|
m_bFlashlightStateChanged = false;
|
|
}
|
|
|
|
if ( bForce || m_ShaderState.m_bToneMappingScaleChanged )
|
|
{
|
|
pPerFrameConstants->cTonemappingScale = DirectX::XMFLOAT4( m_ShaderState.m_ToneMappingScale.Base() );
|
|
m_ShaderState.m_bToneMappingScaleChanged = false;
|
|
}
|
|
|
|
//{
|
|
//VPROF_BUDGET( "ForceUpdate constants", VPROF_BUDGETGROUP_OTHER_UNACCOUNTED );
|
|
|
|
//
|
|
// Supply the new constants.
|
|
//
|
|
if ( bPerModelChanged )
|
|
( (CShaderConstantBufferDx11 *)m_hPerModelConstants )->ForceUpdate();
|
|
if ( bPerFrameChanged )
|
|
( (CShaderConstantBufferDx11 *)m_hPerFrameConstants )->ForceUpdate();
|
|
if ( bPerSceneChanged )
|
|
( (CShaderConstantBufferDx11 *)m_hPerSceneConstants )->ForceUpdate();
|
|
//}
|
|
|
|
}
|
|
|
|
void CShaderAPIDx11::DoIssueVertexShader()
|
|
{
|
|
D3D11DeviceContext()->VSSetShader( m_DynamicState.m_pVertexShader, NULL, 0 );
|
|
}
|
|
|
|
void CShaderAPIDx11::DoIssuePixelShader()
|
|
{
|
|
D3D11DeviceContext()->PSSetShader( m_DynamicState.m_pPixelShader, NULL, 0 );
|
|
}
|
|
|
|
void CShaderAPIDx11::DoIssueGeometryShader()
|
|
{
|
|
D3D11DeviceContext()->GSSetShader( m_DynamicState.m_pGeometryShader, NULL, 0 );
|
|
}
|
|
|
|
bool CShaderAPIDx11::DoIssueConstantBuffers( bool bForce )
|
|
{
|
|
const StatesDx11::ShadowState *shadow = m_ShadowState;
|
|
|
|
if ( bForce || IsStateSet( STATE_CHANGED_VSCONSTANTBUFFERS ) )
|
|
{
|
|
D3D11DeviceContext()->VSSetConstantBuffers( 0, shadow->desc.vsConstantBuffers.m_MaxSlot + 1,
|
|
shadow->desc.vsConstantBuffers.m_ppBuffers );
|
|
}
|
|
|
|
if ( bForce || IsStateSet( STATE_CHANGED_GSCONSTANTBUFFERS ) )
|
|
{
|
|
D3D11DeviceContext()->GSSetConstantBuffers( 0, shadow->desc.gsConstantBuffers.m_MaxSlot + 1,
|
|
shadow->desc.gsConstantBuffers.m_ppBuffers );
|
|
}
|
|
|
|
if ( bForce || IsStateSet( STATE_CHANGED_PSCONSTANTBUFFERS ) )
|
|
{
|
|
D3D11DeviceContext()->PSSetConstantBuffers( 0, shadow->desc.psConstantBuffers.m_MaxSlot + 1,
|
|
shadow->desc.psConstantBuffers.m_ppBuffers );
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void CShaderAPIDx11::DoIssueSampler( bool bPixel, bool bVertex )
|
|
{
|
|
if ( bPixel )
|
|
{
|
|
int nSamplers = m_DynamicState.m_MaxPSSampler + 1;
|
|
D3D11DeviceContext()->PSSetSamplers( 0, nSamplers, m_DynamicState.m_ppSamplers );
|
|
}
|
|
|
|
if ( bVertex )
|
|
{
|
|
int nSamplers = m_DynamicState.m_MaxVSSampler + 1;
|
|
D3D11DeviceContext()->VSSetSamplers( 0, nSamplers, m_DynamicState.m_ppVertexSamplers );
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::DoIssueTexture( bool bPixel, bool bVertex )
|
|
{
|
|
if ( bPixel )
|
|
{
|
|
int nSamplers = m_DynamicState.m_MaxPSSampler + 1;
|
|
D3D11DeviceContext()->PSSetShaderResources( 0, nSamplers, m_DynamicState.m_ppTextures );
|
|
}
|
|
|
|
if ( bVertex )
|
|
{
|
|
int nSamplers = m_DynamicState.m_MaxVSSampler + 1;
|
|
D3D11DeviceContext()->VSSetShaderResources( 0, nSamplers, m_DynamicState.m_ppVertexTextures );
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::DoIssueRasterState()
|
|
{
|
|
D3D11DeviceContext()->RSSetState( m_ShadowState->desc.rasterizer.m_pD3DState );
|
|
}
|
|
|
|
void CShaderAPIDx11::DoIssueBlendState()
|
|
{
|
|
D3D11DeviceContext()->OMSetBlendState( m_ShadowState->desc.blend.m_pD3DState,
|
|
m_ShadowState->desc.blend.BlendColor,
|
|
m_ShadowState->desc.blend.SampleMask );
|
|
}
|
|
|
|
void CShaderAPIDx11::DoIssueDepthStencilState()
|
|
{
|
|
D3D11DeviceContext()->OMSetDepthStencilState( m_ShadowState->desc.depthStencil.m_pD3DState,
|
|
m_ShadowState->desc.depthStencil.StencilRef );
|
|
}
|
|
|
|
bool CShaderAPIDx11::DoIssueVertexBuffer()
|
|
{
|
|
D3D11DeviceContext()->IASetVertexBuffers( 0, m_DynamicState.m_MaxVertexBuffer + 1, m_DynamicState.m_pVertexBuffer,
|
|
m_DynamicState.m_pVBStrides, m_DynamicState.m_pVBOffsets );
|
|
m_DynamicState.m_PrevMaxVertexBuffer = m_DynamicState.m_MaxVertexBuffer;
|
|
m_DynamicState.m_MaxVertexBuffer = -1;
|
|
return true;
|
|
}
|
|
|
|
void CShaderAPIDx11::DoIssueIndexBuffer()
|
|
{
|
|
StatesDx11::DynamicState &dynamic = m_DynamicState;
|
|
D3D11DeviceContext()->IASetIndexBuffer( dynamic.m_IndexBuffer.m_pBuffer,
|
|
dynamic.m_IndexBuffer.m_Format,
|
|
dynamic.m_IndexBuffer.m_nOffset );
|
|
}
|
|
|
|
void CShaderAPIDx11::DoIssueInputLayout()
|
|
{
|
|
StatesDx11::DynamicState &dynamic = m_DynamicState;
|
|
|
|
ID3D11InputLayout *pInputLayout = g_pShaderDeviceDx11->GetInputLayout(
|
|
dynamic.m_InputLayout.m_hVertexShader,
|
|
dynamic.m_InputLayout.m_pVertexDecl[0], dynamic.m_InputLayout.m_bStaticLit,
|
|
dynamic.m_InputLayout.m_bUsingFlex, dynamic.m_InputLayout.m_bUsingMorph );
|
|
|
|
D3D11DeviceContext()->IASetInputLayout( pInputLayout );
|
|
}
|
|
|
|
void CShaderAPIDx11::DoIssueTopology()
|
|
{
|
|
D3D11DeviceContext()->IASetPrimitiveTopology( m_DynamicState.m_Topology );
|
|
}
|
|
|
|
void CShaderAPIDx11::DoIssueViewports()
|
|
{
|
|
D3D11DeviceContext()->RSSetViewports( m_DynamicState.m_nViewportCount,
|
|
m_DynamicState.m_pViewports );
|
|
}
|
|
|
|
void CShaderAPIDx11::DoIssueRenderTargets()
|
|
{
|
|
int nCount = 0;
|
|
ID3D11RenderTargetView *rt;
|
|
for ( ; nCount < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; nCount++ )
|
|
{
|
|
rt = m_DynamicState.m_pRenderTargetViews[nCount];
|
|
if ( rt == NULL )
|
|
break;
|
|
}
|
|
|
|
if ( nCount > 0 )
|
|
{
|
|
D3D11DeviceContext()->OMSetRenderTargets( nCount, m_DynamicState.m_pRenderTargetViews, NULL );
|
|
}
|
|
else
|
|
{
|
|
// push the back buffer
|
|
rt = GetTexture( m_hBackBuffer ).GetRenderTargetView();
|
|
D3D11DeviceContext()->OMSetRenderTargets( 1, &rt, m_DynamicState.m_pDepthStencilView );
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Methods of IShaderDynamicAPI
|
|
//-----------------------------------------------------------------------------
|
|
void CShaderAPIDx11::GetBackBufferDimensions( int &nWidth, int &nHeight ) const
|
|
{
|
|
g_pShaderDeviceDx11->GetBackBufferDimensions( nWidth, nHeight );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Viewport-related methods
|
|
//-----------------------------------------------------------------------------
|
|
void CShaderAPIDx11::SetViewports( int nCount, const ShaderViewport_t *pViewports )
|
|
{
|
|
nCount = min( nCount, MAX_DX11_VIEWPORTS );
|
|
m_DynamicState.m_nViewportCount = nCount;
|
|
|
|
for ( int i = 0; i < nCount; ++i )
|
|
{
|
|
Assert( pViewports[i].m_nVersion == SHADER_VIEWPORT_VERSION );
|
|
|
|
D3D11_VIEWPORT &viewport = m_DynamicState.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;
|
|
}
|
|
|
|
SetStateFlag( STATE_CHANGED_VIEWPORTS );
|
|
}
|
|
|
|
int CShaderAPIDx11::GetViewports( ShaderViewport_t *pViewports, int nMax ) const
|
|
{
|
|
int nCount = m_DynamicState.m_nViewportCount;
|
|
if ( pViewports && nMax )
|
|
{
|
|
nCount = min( nCount, nMax );
|
|
for ( int i = 0; i < nCount; i++ )
|
|
{
|
|
const D3D11_VIEWPORT &vp = m_DynamicState.m_pViewports[i];
|
|
pViewports[i].m_nVersion = SHADER_VIEWPORT_VERSION;
|
|
pViewports[i].m_nTopLeftX = vp.TopLeftX;
|
|
pViewports[i].m_nTopLeftY = vp.TopLeftY;
|
|
pViewports[i].m_nWidth = vp.Width;
|
|
pViewports[i].m_nHeight = vp.Height;
|
|
pViewports[i].m_flMaxZ = vp.MaxDepth;
|
|
pViewports[i].m_flMinZ = vp.MinDepth;
|
|
}
|
|
}
|
|
return nCount;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Methods related to clearing buffers
|
|
//-----------------------------------------------------------------------------
|
|
void CShaderAPIDx11::ClearColor3ub( unsigned char r, unsigned char g, unsigned char b )
|
|
{
|
|
m_DynamicState.m_ClearColor[0] = r / 255.0f;
|
|
m_DynamicState.m_ClearColor[1] = g / 255.0f;
|
|
m_DynamicState.m_ClearColor[2] = b / 255.0f;
|
|
m_DynamicState.m_ClearColor[3] = 1.0f;
|
|
}
|
|
|
|
void CShaderAPIDx11::ClearColor4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a )
|
|
{
|
|
m_DynamicState.m_ClearColor[0] = r / 255.0f;
|
|
m_DynamicState.m_ClearColor[1] = g / 255.0f;
|
|
m_DynamicState.m_ClearColor[2] = b / 255.0f;
|
|
m_DynamicState.m_ClearColor[3] = a / 255.0f;
|
|
}
|
|
|
|
void CShaderAPIDx11::ClearBuffers( bool bClearColor, bool bClearDepth, bool bClearStencil, int renderTargetWidth, int renderTargetHeight )
|
|
{
|
|
// NOTE: State change commit isn't necessary since clearing doesn't use state
|
|
// IssueStateChanges();
|
|
|
|
// State changed... need to flush the dynamic buffer
|
|
FlushBufferedPrimitives();
|
|
|
|
// FIXME: This implementation is totally bust0red [doesn't guarantee exact color specified]
|
|
if ( bClearColor && D3D11DeviceContext() )
|
|
{
|
|
ID3D11RenderTargetView* rt;
|
|
for ( int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++ )
|
|
{
|
|
rt = m_DynamicState.m_pRenderTargetViews[i];
|
|
if ( rt == NULL )
|
|
break;
|
|
|
|
D3D11DeviceContext()->ClearRenderTargetView( rt, m_DynamicState.m_ClearColor );
|
|
}
|
|
|
|
// finally, free the back buffer
|
|
rt = GetTexture( m_hBackBuffer ).GetRenderTargetView();
|
|
D3D11DeviceContext()->ClearRenderTargetView( rt, m_DynamicState.m_ClearColor );
|
|
}
|
|
|
|
if ( bClearDepth && D3D11DeviceContext() && m_DynamicState.m_pDepthStencilView )
|
|
{
|
|
UINT clearFlags = 0;
|
|
if ( bClearDepth )
|
|
{
|
|
clearFlags |= D3D11_CLEAR_DEPTH;
|
|
}
|
|
if ( bClearStencil )
|
|
{
|
|
clearFlags |= D3D11_CLEAR_STENCIL;
|
|
}
|
|
D3D11DeviceContext()->ClearDepthStencilView( m_DynamicState.m_pDepthStencilView, clearFlags, 1.0f, 0 );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Methods related to binding shaders
|
|
//-----------------------------------------------------------------------------
|
|
void CShaderAPIDx11::BindVertexShader( VertexShaderHandle_t hVertexShader )
|
|
{
|
|
ID3D11VertexShader *pVertexShader = g_pShaderDeviceDx11->GetVertexShader( hVertexShader );
|
|
if ( m_DynamicState.m_pVertexShader != pVertexShader )
|
|
{
|
|
SetStateFlag( STATE_CHANGED_VERTEXSHADER );
|
|
}
|
|
if ( m_DynamicState.m_InputLayout.m_hVertexShader != hVertexShader )
|
|
{
|
|
SetStateFlag( STATE_CHANGED_INPUTLAYOUT );
|
|
}
|
|
m_DynamicState.m_pVertexShader = pVertexShader;
|
|
m_DynamicState.m_InputLayout.m_hVertexShader = hVertexShader;
|
|
}
|
|
|
|
void CShaderAPIDx11::BindGeometryShader( GeometryShaderHandle_t hGeometryShader )
|
|
{
|
|
ID3D11GeometryShader *pGeometryShader = g_pShaderDeviceDx11->GetGeometryShader( hGeometryShader );
|
|
if ( m_DynamicState.m_pGeometryShader != pGeometryShader )
|
|
{
|
|
SetStateFlag( STATE_CHANGED_GEOMETRYSHADER );
|
|
}
|
|
m_DynamicState.m_pGeometryShader = pGeometryShader;
|
|
}
|
|
|
|
void CShaderAPIDx11::BindPixelShader( PixelShaderHandle_t hPixelShader )
|
|
{
|
|
ID3D11PixelShader *pPixelShader = g_pShaderDeviceDx11->GetPixelShader( hPixelShader );
|
|
if ( m_DynamicState.m_pPixelShader != pPixelShader )
|
|
{
|
|
SetStateFlag( STATE_CHANGED_PIXELSHADER );
|
|
}
|
|
m_DynamicState.m_pPixelShader = pPixelShader;
|
|
}
|
|
|
|
void CShaderAPIDx11::BindVertexBuffer( int nStreamID, IVertexBuffer *pVertexBuffer, int nOffsetInBytes,
|
|
int nFirstVertex, int nVertexCount, VertexFormat_t fmt, int nRepetitions )
|
|
{
|
|
StatesDx11::DynamicState &dynamic = m_DynamicState;
|
|
|
|
// FIXME: What to do about repetitions?
|
|
CVertexBufferDx11 *pVertexBufferDx11 = static_cast<CVertexBufferDx11 *>( pVertexBuffer );
|
|
|
|
|
|
ID3D11Buffer *pBuffer = NULL;
|
|
UINT stride = 0;
|
|
if ( pVertexBufferDx11 )
|
|
{
|
|
pBuffer = pVertexBufferDx11->GetDx11Buffer();
|
|
stride = pVertexBufferDx11->VertexSize();
|
|
}
|
|
|
|
// Offset can be provided by first index
|
|
if ( nOffsetInBytes < 0 )
|
|
{
|
|
nOffsetInBytes = nFirstVertex * stride;
|
|
}
|
|
|
|
UINT offset = nOffsetInBytes;
|
|
|
|
if ( pBuffer != dynamic.m_pVertexBuffer[nStreamID] )
|
|
{
|
|
dynamic.m_pVertexBuffer[nStreamID] = pBuffer;
|
|
SetStateFlag( STATE_CHANGED_VERTEXBUFFER );
|
|
}
|
|
|
|
if ( stride != dynamic.m_pVBStrides[nStreamID] )
|
|
{
|
|
dynamic.m_pVBStrides[nStreamID] = stride;
|
|
SetStateFlag( STATE_CHANGED_VERTEXBUFFER );
|
|
}
|
|
|
|
if ( offset != dynamic.m_pVBOffsets[nStreamID] )
|
|
{
|
|
dynamic.m_pVBOffsets[nStreamID] = offset;
|
|
SetStateFlag( STATE_CHANGED_VERTEXBUFFER );
|
|
}
|
|
|
|
if ( nStreamID > dynamic.m_MaxVertexBuffer )
|
|
{
|
|
dynamic.m_MaxVertexBuffer = nStreamID;
|
|
if ( dynamic.m_MaxVertexBuffer > dynamic.m_PrevMaxVertexBuffer )
|
|
{
|
|
SetStateFlag( STATE_CHANGED_VERTEXBUFFER );
|
|
}
|
|
}
|
|
|
|
if ( dynamic.m_InputLayout.m_pVertexDecl[nStreamID] != fmt )
|
|
{
|
|
m_DynamicState.m_InputLayout.m_pVertexDecl[nStreamID] = fmt;
|
|
SetStateFlag( STATE_CHANGED_INPUTLAYOUT );
|
|
}
|
|
|
|
}
|
|
|
|
void CShaderAPIDx11::SetUsingExtraVertexBuffers( bool bStaticLit, bool bUsingFlex, bool bUsingMorph )
|
|
{
|
|
if ( m_DynamicState.m_InputLayout.m_bStaticLit != bStaticLit ||
|
|
m_DynamicState.m_InputLayout.m_bUsingFlex != bUsingFlex ||
|
|
m_DynamicState.m_InputLayout.m_bUsingMorph != bUsingMorph )
|
|
{
|
|
SetStateFlag( STATE_CHANGED_INPUTLAYOUT );
|
|
}
|
|
|
|
m_DynamicState.m_InputLayout.m_bStaticLit = bStaticLit;
|
|
m_DynamicState.m_InputLayout.m_bUsingFlex = bUsingFlex;
|
|
m_DynamicState.m_InputLayout.m_bUsingMorph = bUsingMorph;
|
|
}
|
|
|
|
void CShaderAPIDx11::BindIndexBuffer( IIndexBuffer *pIndexBuffer, int nOffsetInBytes )
|
|
{
|
|
CIndexBufferDx11 *pIndexBufferDx11 = static_cast<CIndexBufferDx11 *>( pIndexBuffer );
|
|
|
|
ID3D11Buffer *pBuffer = NULL;
|
|
DXGI_FORMAT fmt = DXGI_FORMAT_R16_UINT;
|
|
UINT offset = nOffsetInBytes;
|
|
if ( pIndexBufferDx11 )
|
|
{
|
|
pBuffer = pIndexBufferDx11->GetDx11Buffer();
|
|
fmt = ( pIndexBufferDx11->GetIndexFormat() == MATERIAL_INDEX_FORMAT_16BIT ) ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT;
|
|
}
|
|
|
|
if ( pBuffer != m_DynamicState.m_IndexBuffer.m_pBuffer ||
|
|
fmt != m_DynamicState.m_IndexBuffer.m_Format ||
|
|
offset != m_DynamicState.m_IndexBuffer.m_nOffset)
|
|
{
|
|
SetStateFlag( STATE_CHANGED_INDEXBUFFER );
|
|
}
|
|
|
|
m_DynamicState.m_IndexBuffer.m_pBuffer = pBuffer;
|
|
m_DynamicState.m_IndexBuffer.m_Format = fmt;
|
|
m_DynamicState.m_IndexBuffer.m_nOffset = offset;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Unbinds resources because they are about to be deleted
|
|
//-----------------------------------------------------------------------------
|
|
void CShaderAPIDx11::Unbind( VertexShaderHandle_t hShader )
|
|
{
|
|
ID3D11VertexShader *pShader = g_pShaderDeviceDx11->GetVertexShader( hShader );
|
|
Assert( pShader );
|
|
if ( m_DynamicState.m_pVertexShader == pShader )
|
|
{
|
|
BindVertexShader( VERTEX_SHADER_HANDLE_INVALID );
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::Unbind( GeometryShaderHandle_t hShader )
|
|
{
|
|
ID3D11GeometryShader *pShader = g_pShaderDeviceDx11->GetGeometryShader( hShader );
|
|
Assert( pShader );
|
|
if ( m_DynamicState.m_pGeometryShader == pShader )
|
|
{
|
|
BindGeometryShader( GEOMETRY_SHADER_HANDLE_INVALID );
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::Unbind( PixelShaderHandle_t hShader )
|
|
{
|
|
ID3D11PixelShader *pShader = g_pShaderDeviceDx11->GetPixelShader( hShader );
|
|
Assert( pShader );
|
|
if ( m_DynamicState.m_pPixelShader == pShader )
|
|
{
|
|
BindPixelShader( PIXEL_SHADER_HANDLE_INVALID );
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::UnbindVertexBuffer( ID3D11Buffer *pBuffer )
|
|
{
|
|
Assert( pBuffer );
|
|
|
|
for ( int i = 0; i < MAX_DX11_STREAMS; ++i )
|
|
{
|
|
if ( m_DynamicState.m_pVertexBuffer[i] == pBuffer )
|
|
{
|
|
BindVertexBuffer( i, NULL, 0, 0, 0, VERTEX_POSITION, 0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::UnbindIndexBuffer( ID3D11Buffer *pBuffer )
|
|
{
|
|
Assert( pBuffer );
|
|
|
|
if ( m_DynamicState.m_IndexBuffer.m_pBuffer == pBuffer )
|
|
{
|
|
BindIndexBuffer( NULL, 0 );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Sets the topology state
|
|
//-----------------------------------------------------------------------------
|
|
void CShaderAPIDx11::SetTopology( MaterialPrimitiveType_t topology )
|
|
{
|
|
D3D11_PRIMITIVE_TOPOLOGY d3dTopology;
|
|
switch ( topology )
|
|
{
|
|
case MATERIAL_POINTS:
|
|
d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST;
|
|
break;
|
|
|
|
case MATERIAL_LINES:
|
|
d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_LINELIST;
|
|
break;
|
|
|
|
case MATERIAL_TRIANGLES:
|
|
d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
|
|
break;
|
|
|
|
case MATERIAL_TRIANGLE_STRIP:
|
|
d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
|
|
break;
|
|
|
|
case MATERIAL_LINE_STRIP:
|
|
d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP;
|
|
break;
|
|
|
|
default:
|
|
case MATERIAL_LINE_LOOP:
|
|
case MATERIAL_POLYGON:
|
|
case MATERIAL_QUADS:
|
|
Assert( 0 );
|
|
d3dTopology = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED;
|
|
break;
|
|
}
|
|
|
|
////Log( "Set topology to %i\n", d3dTopology );
|
|
if ( d3dTopology != m_DynamicState.m_Topology )
|
|
{
|
|
FlushBufferedPrimitives();
|
|
SetStateFlag( STATE_CHANGED_TOPOLOGY );
|
|
}
|
|
m_DynamicState.m_Topology = d3dTopology;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Mesh/Material rendering
|
|
//-----------------------------------------------------------------------------
|
|
void CShaderAPIDx11::DrawMesh( IMesh *pMesh )
|
|
{
|
|
VPROF( "CShaderAPIDx11::DrawMesh" );
|
|
if ( ShaderUtil()->GetConfig().m_bSuppressRendering )
|
|
return;
|
|
|
|
//Log( "CShaderAPIDx11::DrawMesh %p\n", pMesh );
|
|
|
|
m_pMesh = static_cast<CMeshBase *>( pMesh );
|
|
if ( !m_pMesh || !m_pMaterial )
|
|
{
|
|
Warning( "Tried to render mesh with NULL mesh or NULL material!\n" );
|
|
return;
|
|
}
|
|
SetUsingExtraVertexBuffers( m_pMesh->HasColorMesh(), m_pMesh->HasFlexMesh(), m_pMaterial->IsUsingVertexID() );
|
|
m_pMaterial->DrawMesh( CompressionType( pMesh->GetVertexFormat() ) );
|
|
m_pMesh = NULL;
|
|
}
|
|
|
|
static int s_nPassesRendered = 0;
|
|
|
|
// Begins a rendering pass that uses a state snapshot
|
|
void CShaderAPIDx11::BeginPass( StateSnapshot_t snapshot )
|
|
{
|
|
// Apply the snapshot state
|
|
//if ( snapshot != -1 )
|
|
UseSnapshot( snapshot );
|
|
}
|
|
|
|
// Renders a single pass of a material
|
|
void CShaderAPIDx11::RenderPass( int nPass, int nPassCount )
|
|
{
|
|
if ( g_pShaderDeviceDx11->IsDeactivated() )
|
|
return;
|
|
|
|
//IssueStateChanges();
|
|
|
|
// Now actually render
|
|
|
|
if ( m_pMesh )
|
|
{
|
|
m_pMesh->RenderPass();
|
|
}
|
|
else
|
|
{
|
|
Assert( 0 );
|
|
RenderPassWithVertexAndIndexBuffers();
|
|
}
|
|
|
|
//m_CurrentSnapshot = -1;
|
|
}
|
|
|
|
void CShaderAPIDx11::RenderPassWithVertexAndIndexBuffers()
|
|
{
|
|
if ( m_DynamicState.m_Topology == D3D11_PRIMITIVE_TOPOLOGY_POINTLIST )
|
|
{
|
|
Assert( 0 );
|
|
}
|
|
else
|
|
{
|
|
//DrawIndexed(m_State.dynamic.m_IndexBuffer.)
|
|
}
|
|
}
|
|
|
|
// Draws primitives
|
|
void CShaderAPIDx11::Draw( MaterialPrimitiveType_t primitiveType, int nFirstIndex, int nIndexCount )
|
|
{
|
|
//Log( "ShaderAPIDx11: Draw\n" );
|
|
|
|
SetTopology( primitiveType );
|
|
|
|
IssueStateChanges();
|
|
|
|
// FIXME: How do I set the base vertex location!?
|
|
DrawIndexed( nFirstIndex, nIndexCount, 0 );
|
|
}
|
|
|
|
void CShaderAPIDx11::DrawIndexed( int nFirstIndex, int nIndexCount, int nBaseVertexLocation )
|
|
{
|
|
//Assert( m_State.dynamic.m_pVertexShader != NULL );
|
|
D3D11DeviceContext()->DrawIndexed( (UINT)nIndexCount, (UINT)nFirstIndex, (UINT)nBaseVertexLocation );
|
|
//g_pShaderDeviceDx11->Present();
|
|
//Log( "Presented" );
|
|
//Log( "\n" );
|
|
}
|
|
|
|
void CShaderAPIDx11::DrawNotIndexed( int nFirstVertex, int nVertCount )
|
|
{
|
|
D3D11DeviceContext()->Draw( (UINT)nVertCount, (UINT)nFirstVertex );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------//
|
|
|
|
bool CShaderAPIDx11::OnDeviceInit()
|
|
{
|
|
// Initialize the mesh manager
|
|
MeshMgr()->Init();
|
|
|
|
int w, h;
|
|
g_pShaderDeviceDx11->GetBackBufferDimensions( w, h );
|
|
|
|
{
|
|
LOCK_SHADERAPI();
|
|
// Create a the back buffer view
|
|
// UNDONE: Should texture creation and access be moved to ShaderDeviceDx11?
|
|
ID3D11Texture2D *pBackBuffer;
|
|
DXGI_SWAP_CHAIN_DESC swapChainDesc;
|
|
D3D11SwapChain()->GetDesc( &swapChainDesc );
|
|
HRESULT hr = D3D11SwapChain()->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (LPVOID *)&pBackBuffer );
|
|
if ( FAILED( hr ) )
|
|
return FALSE;
|
|
m_hBackBuffer = CreateTextureHandle();
|
|
CTextureDx11 *pTex = &GetTexture( m_hBackBuffer );
|
|
pTex->SetupBackBuffer( w, h, "dx11BackBuffer", pBackBuffer, pTex->GetImageFormat( swapChainDesc.BufferDesc.Format ) );
|
|
}
|
|
|
|
// Create the depth buffer
|
|
m_hDepthBuffer = CreateDepthTexture( IMAGE_FORMAT_NV_DST24, w, h, "dx11DepthBuffer", true );
|
|
|
|
m_hPerFrameConstants = g_pShaderDeviceDx11->CreateConstantBuffer( sizeof( PerFrame_CBuffer_t ) );
|
|
m_hPerModelConstants = g_pShaderDeviceDx11->CreateConstantBuffer( sizeof( PerModel_CBuffer_t ) );
|
|
m_hPerSceneConstants = g_pShaderDeviceDx11->CreateConstantBuffer( sizeof( PerScene_CBuffer_t ) );
|
|
m_hSkinningConstants = g_pShaderDeviceDx11->CreateConstantBuffer( sizeof( Skinning_CBuffer_t ) );
|
|
m_hFlexConstants = g_pShaderDeviceDx11->CreateConstantBuffer( sizeof( Flex_CBuffer_t ) );
|
|
|
|
// Write some constants that don't change
|
|
PerScene_CBuffer_t *pPerScene = (PerScene_CBuffer_t *)( (CShaderConstantBufferDx11 *)m_hPerSceneConstants )->GetData();
|
|
// [ gamma, overbright, 1/3, 1/overbright]
|
|
pPerScene->cConstants.x = 1.0f / 2.2f;
|
|
pPerScene->cConstants.y = OVERBRIGHT;
|
|
pPerScene->cConstants.z = 1.0f / 3.0f;
|
|
pPerScene->cConstants.w = 1.0f / OVERBRIGHT;
|
|
pPerScene->cFlexScale.x = 1.0f;
|
|
pPerScene->cFlexScale.y = 1.0f;
|
|
pPerScene->cFlexScale.z = 0.0f;
|
|
pPerScene->cFlexScale.w = 0.0f;
|
|
|
|
( (CShaderConstantBufferDx11 *)m_hPerSceneConstants )->ForceUpdate();
|
|
|
|
ResetRenderState( true );
|
|
|
|
return true;
|
|
}
|
|
|
|
void CShaderAPIDx11::OnDeviceShutdown()
|
|
{
|
|
for ( int i = 0; i < m_Textures.Count(); i++ )
|
|
{
|
|
CTextureDx11 *pTex = &m_Textures[i];
|
|
pTex->Delete();
|
|
}
|
|
m_Textures.RemoveAll();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Abandon all hope below this point
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool CShaderAPIDx11::DoRenderTargetsNeedSeparateDepthBuffer() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Can we download textures?
|
|
bool CShaderAPIDx11::CanDownloadTextures() const
|
|
{
|
|
if ( IsDeactivated() )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
// Used to clear the transition table when we know it's become invalid.
|
|
void CShaderAPIDx11::ClearSnapshots()
|
|
{
|
|
LOCK_SHADERAPI();
|
|
FlushBufferedPrimitives();
|
|
g_pShaderShadowDx11->m_ShadowStates.RemoveAll();
|
|
ResetRenderState( true );
|
|
}
|
|
|
|
// Sets the default *dynamic* state
|
|
void CShaderAPIDx11::SetDefaultState()
|
|
{
|
|
m_DynamicState.m_MaxPSSampler = -1;
|
|
m_DynamicState.m_MaxVSSampler = -1;
|
|
|
|
m_DynamicState.m_pVertexShader = 0;
|
|
m_DynamicState.m_pGeometryShader = 0;
|
|
m_DynamicState.m_pPixelShader = 0;
|
|
}
|
|
|
|
// Returns the snapshot id for the current shadow state
|
|
StateSnapshot_t CShaderAPIDx11::TakeSnapshot()
|
|
{
|
|
return g_pShaderShadowDx11->FindOrCreateSnapshot();
|
|
}
|
|
|
|
void CShaderAPIDx11::OverrideAlphaWriteEnable(bool bOverrideEnable, bool bAlphaWriteEnable)
|
|
{
|
|
LOCK_SHADERAPI();
|
|
// NOT IMPLEMENTED
|
|
}
|
|
|
|
void CShaderAPIDx11::OverrideColorWriteEnable(bool bOverrideEnable, bool bColorWriteEnable)
|
|
{
|
|
LOCK_SHADERAPI();
|
|
// NOT IMPLEMENTED
|
|
}
|
|
|
|
// Returns true if the state snapshot is transparent
|
|
bool CShaderAPIDx11::IsTranslucent( StateSnapshot_t id ) const
|
|
{
|
|
LOCK_SHADERAPI();
|
|
return g_pShaderShadowDx11->GetShadowState( id )->desc.blend.BlendEnabled();
|
|
}
|
|
|
|
bool CShaderAPIDx11::IsAlphaTested( StateSnapshot_t id ) const
|
|
{
|
|
LOCK_SHADERAPI();
|
|
return false;
|
|
//return g_pShaderShadowDx11->GetShadowState( id )->desc.bEnableAlphaTest;
|
|
}
|
|
|
|
bool CShaderAPIDx11::IsDepthWriteEnabled( StateSnapshot_t id ) const
|
|
{
|
|
LOCK_SHADERAPI();
|
|
return g_pShaderShadowDx11->GetShadowState( id )->desc.depthStencil.DepthWriteMask != 0;
|
|
}
|
|
|
|
bool CShaderAPIDx11::UsesVertexAndPixelShaders( StateSnapshot_t id ) const
|
|
{
|
|
// It has to in DX11
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Gets the bound morph's vertex format; returns 0 if no morph is bound
|
|
//-----------------------------------------------------------------------------
|
|
MorphFormat_t CShaderAPIDx11::GetBoundMorphFormat()
|
|
{
|
|
return ShaderUtil()->GetBoundMorphFormat();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// What fields in the morph do we actually use?
|
|
//-----------------------------------------------------------------------------
|
|
MorphFormat_t CShaderAPIDx11::ComputeMorphFormat( int numSnapshots, StateSnapshot_t *pIds ) const
|
|
{
|
|
LOCK_SHADERAPI();
|
|
MorphFormat_t format = 0;
|
|
for ( int i = 0; i < numSnapshots; ++i )
|
|
{
|
|
MorphFormat_t fmt = g_pShaderShadowDx11->GetShadowState( pIds[i] )->desc.morphFormat;
|
|
format |= VertexFlags( fmt );
|
|
}
|
|
return format;
|
|
}
|
|
|
|
// Gets the vertex format for a set of snapshot ids
|
|
VertexFormat_t CShaderAPIDx11::ComputeVertexFormat( int numSnapshots, StateSnapshot_t *pIds ) const
|
|
{
|
|
LOCK_SHADERAPI();
|
|
VertexFormat_t fmt = ComputeVertexUsage( numSnapshots, pIds );
|
|
return fmt;
|
|
}
|
|
|
|
// Gets the vertex format for a set of snapshot ids
|
|
VertexFormat_t CShaderAPIDx11::ComputeVertexUsage( int num, StateSnapshot_t *pIds ) const
|
|
{
|
|
LOCK_SHADERAPI();
|
|
if ( num == 0 )
|
|
return 0;
|
|
|
|
// We don't have to all sorts of crazy stuff if there's only one snapshot
|
|
if ( num == 1 )
|
|
{
|
|
const StatesDx11::ShadowState *state = g_pShaderShadowDx11->GetShadowState( pIds[0] );
|
|
return (VertexFormat_t)( state->desc.vertexFormat );
|
|
}
|
|
|
|
Assert( pIds );
|
|
|
|
// Aggregating vertex formats is a little tricky;
|
|
// For example, what do we do when two passes want user data?
|
|
// Can we assume they are the same? For now, I'm going to
|
|
// just print a warning in debug.
|
|
|
|
VertexCompressionType_t compression = VERTEX_COMPRESSION_INVALID;
|
|
int userDataSize = 0;
|
|
int numBones = 0;
|
|
int texCoordSize[VERTEX_MAX_TEXTURE_COORDINATES] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
int flags = 0;
|
|
|
|
for ( int i = num; --i >= 0; )
|
|
{
|
|
//Log( "Applying vertex format from snapshot num %i, %i\n", i, pIds[i] );
|
|
const StatesDx11::ShadowState *state = g_pShaderShadowDx11->GetShadowState( pIds[i] );
|
|
VertexFormat_t fmt = state->desc.vertexFormat;
|
|
flags |= VertexFlags( fmt );
|
|
|
|
VertexCompressionType_t newCompression = CompressionType( fmt );
|
|
if ( ( compression != newCompression ) && ( compression != VERTEX_COMPRESSION_INVALID ) )
|
|
{
|
|
Warning( "Encountered a material with two passes that specify different vertex compression types!\n" );
|
|
compression = VERTEX_COMPRESSION_NONE; // Be safe, disable compression
|
|
}
|
|
|
|
int newNumBones = NumBoneWeights( fmt );
|
|
if ( ( numBones != newNumBones ) && ( newNumBones != 0 ) )
|
|
{
|
|
if ( numBones != 0 )
|
|
{
|
|
Warning( "Encountered a material with two passes that use different numbers of bones!\n" );
|
|
}
|
|
numBones = newNumBones;
|
|
}
|
|
|
|
int newUserSize = UserDataSize( fmt );
|
|
if ( ( userDataSize != newUserSize ) && ( newUserSize != 0 ) )
|
|
{
|
|
if ( userDataSize != 0 )
|
|
{
|
|
Warning( "Encountered a material with two passes that use different user data sizes!\n" );
|
|
}
|
|
userDataSize = newUserSize;
|
|
}
|
|
|
|
for ( int j = 0; j < VERTEX_MAX_TEXTURE_COORDINATES; ++j )
|
|
{
|
|
int newSize = TexCoordSize( (TextureStage_t)j, fmt );
|
|
if ( ( texCoordSize[j] != newSize ) && ( newSize != 0 ) )
|
|
{
|
|
if ( texCoordSize[j] != 0 )
|
|
{
|
|
Warning( "Encountered a material with two passes that use different texture coord sizes!\n" );
|
|
}
|
|
if ( texCoordSize[j] < newSize )
|
|
{
|
|
texCoordSize[j] = newSize;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return MeshMgr()->ComputeVertexFormat( flags, VERTEX_MAX_TEXTURE_COORDINATES,
|
|
texCoordSize, numBones, userDataSize );
|
|
}
|
|
|
|
// Uses a state snapshot
|
|
void CShaderAPIDx11::UseSnapshot( StateSnapshot_t snapshot )
|
|
{
|
|
const StatesDx11::ShadowState *curr = g_pShaderShadowDx11->GetShadowState( m_CurrentSnapshot );
|
|
const StatesDx11::ShadowState *entry = g_pShaderShadowDx11->GetShadowState( snapshot );
|
|
|
|
if ( entry->m_iBlendState != curr->m_iBlendState )
|
|
{
|
|
SetStateFlag( STATE_CHANGED_BLEND );
|
|
}
|
|
|
|
if ( entry->m_iDepthStencilState != curr->m_iDepthStencilState )
|
|
{
|
|
SetStateFlag( STATE_CHANGED_DEPTHSTENCIL );
|
|
}
|
|
|
|
if ( entry->m_iRasterState != curr->m_iRasterState )
|
|
{
|
|
SetStateFlag( STATE_CHANGED_RASTERIZER );
|
|
}
|
|
|
|
if ( entry->m_iVSConstantBufferState != curr->m_iVSConstantBufferState )
|
|
{
|
|
SetStateFlag( STATE_CHANGED_VSCONSTANTBUFFERS );
|
|
}
|
|
|
|
if ( entry->m_iGSConstantBufferState != curr->m_iGSConstantBufferState )
|
|
{
|
|
SetStateFlag( STATE_CHANGED_GSCONSTANTBUFFERS );
|
|
}
|
|
|
|
if ( entry->m_iPSConstantBufferState != curr->m_iPSConstantBufferState )
|
|
{
|
|
SetStateFlag( STATE_CHANGED_PSCONSTANTBUFFERS );
|
|
}
|
|
|
|
m_CurrentSnapshot = snapshot;
|
|
}
|
|
|
|
// Sets the color to modulate by
|
|
void CShaderAPIDx11::Color3f( float r, float g, float b )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::Color3fv( float const *pColor )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::Color4f( float r, float g, float b, float a )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::Color4fv( float const *pColor )
|
|
{
|
|
}
|
|
|
|
// Faster versions of color
|
|
void CShaderAPIDx11::Color3ub( unsigned char r, unsigned char g, unsigned char b )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::Color3ubv( unsigned char const *rgb )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::Color4ub( unsigned char r, unsigned char g, unsigned char b, unsigned char a )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::Color4ubv( unsigned char const *rgba )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::GetStandardTextureDimensions( int *pWidth, int *pHeight, StandardTextureId_t id )
|
|
{
|
|
ShaderUtil()->GetStandardTextureDimensions( pWidth, pHeight, id );
|
|
}
|
|
|
|
// Binds a particular material to render with
|
|
void CShaderAPIDx11::Bind( IMaterial *pMaterial )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
IMaterialInternal *pMatInt = static_cast<IMaterialInternal *>( pMaterial );
|
|
|
|
bool bMaterialChanged;
|
|
if ( m_pMaterial && pMatInt && m_pMaterial->InMaterialPage() && pMatInt->InMaterialPage() )
|
|
{
|
|
bMaterialChanged = ( m_pMaterial->GetMaterialPage() != pMatInt->GetMaterialPage() );
|
|
}
|
|
else
|
|
{
|
|
bMaterialChanged = ( m_pMaterial != pMatInt ) || ( m_pMaterial && m_pMaterial->InMaterialPage() ) || ( pMatInt && pMatInt->InMaterialPage() );
|
|
}
|
|
|
|
if ( bMaterialChanged )
|
|
{
|
|
FlushBufferedPrimitives();
|
|
m_pMaterial = pMatInt;
|
|
}
|
|
}
|
|
|
|
IMaterialInternal *CShaderAPIDx11::GetBoundMaterial() const
|
|
{
|
|
return m_pMaterial;
|
|
}
|
|
|
|
// Cull mode
|
|
void CShaderAPIDx11::CullMode( MaterialCullMode_t cullMode )
|
|
{
|
|
// This has to be set in shadow state
|
|
Assert( 0 );
|
|
}
|
|
|
|
D3D11_CULL_MODE CShaderAPIDx11::GetCullMode() const
|
|
{
|
|
return g_pShaderShadowDx11->GetShadowState( m_CurrentSnapshot )->desc.rasterizer.CullMode;
|
|
}
|
|
|
|
void CShaderAPIDx11::ForceDepthFuncEquals( bool bEnable )
|
|
{
|
|
}
|
|
|
|
// Forces Z buffering on or off
|
|
void CShaderAPIDx11::OverrideDepthEnable( bool bEnable, bool bDepthEnable )
|
|
{
|
|
}
|
|
|
|
//legacy fast clipping linkage
|
|
void CShaderAPIDx11::SetHeightClipZ( float z )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::SetHeightClipMode( enum MaterialHeightClipMode_t heightClipMode )
|
|
{
|
|
}
|
|
|
|
// Sets the lights
|
|
void CShaderAPIDx11::SetLight( int lightNum, const LightDesc_t &desc )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
//if ( )
|
|
//{
|
|
|
|
FlushBufferedPrimitives();
|
|
if ( !m_ShaderState.light.m_bLightChanged && FastMemCompare( &desc, &m_ShaderState.light.m_Lights[lightNum], sizeof( LightDesc_t ) ) )
|
|
{
|
|
m_ShaderState.light.m_bLightChanged = true;
|
|
}
|
|
m_ShaderState.light.m_Lights[lightNum] = desc;
|
|
m_ShaderState.light.m_NumLights = ComputeNumLights();
|
|
//m_ShaderState.light.m_bLightChanged = true;
|
|
//SortLights();
|
|
//if ( lightNum == 2 && desc.m_Type != MATERIAL_LIGHT_DISABLE)
|
|
// DebuggerBreak();
|
|
//m_ShaderState.light.m_bLightChanged = true;
|
|
//}
|
|
}
|
|
|
|
void CShaderAPIDx11::SetAmbientLightCube( Vector4D cube[6] )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
if ( !m_ShaderState.light.m_bAmbientChanged && FastMemCompare( m_ShaderState.light.m_AmbientLightCube, cube, sizeof( VectorAligned ) * 6 ) )
|
|
{
|
|
m_ShaderState.light.m_bAmbientChanged = true;
|
|
}
|
|
memcpy( m_ShaderState.light.m_AmbientLightCube, cube, 6 * sizeof( VectorAligned ) );
|
|
}
|
|
|
|
// Get lights
|
|
int CShaderAPIDx11::GetMaxLights( void ) const
|
|
{
|
|
return HardwareConfig()->MaxNumLights();
|
|
}
|
|
|
|
const LightDesc_t &CShaderAPIDx11::GetLight( int lightNum ) const
|
|
{
|
|
return m_ShaderState.light.m_Lights[lightNum];
|
|
}
|
|
|
|
int CShaderAPIDx11::GetCurrentLightCombo( void ) const
|
|
{
|
|
// UNUSED
|
|
return 0;
|
|
}
|
|
|
|
void CShaderAPIDx11::DisableAllLocalLights()
|
|
{
|
|
LOCK_SHADERAPI();
|
|
bool bFlushed = false;
|
|
for ( int lightNum = 0; lightNum < MAX_NUM_LIGHTS; lightNum++ )
|
|
{
|
|
if ( m_ShaderState.light.m_Lights[lightNum].m_Type != MATERIAL_LIGHT_DISABLE )
|
|
{
|
|
if ( !bFlushed )
|
|
{
|
|
FlushBufferedPrimitives();
|
|
bFlushed = true;
|
|
}
|
|
m_ShaderState.light.m_Lights[lightNum].m_Type = MATERIAL_LIGHT_DISABLE;
|
|
m_ShaderState.light.m_bLightChanged = true;
|
|
}
|
|
}
|
|
m_ShaderState.light.m_NumLights = 0;
|
|
}
|
|
|
|
float CShaderAPIDx11::GetAmbientLightCubeLuminance( void )
|
|
{
|
|
Vector4DAligned vLuminance( 0.3f, 0.59f, 0.11f, 0.0f );
|
|
float fLuminance = 0.0f;
|
|
|
|
for ( int i = 0; i < 6; i++ )
|
|
{
|
|
fLuminance += vLuminance.Dot( m_ShaderState.light.m_AmbientLightCube[i].Base() );
|
|
}
|
|
|
|
return fLuminance / 6.0f;
|
|
}
|
|
|
|
void CShaderAPIDx11::SetSkinningMatrices()
|
|
{
|
|
}
|
|
|
|
float CShaderAPIDx11::GetLightMapScaleFactor() const
|
|
{
|
|
switch ( HardwareConfig()->GetHDRType() )
|
|
{
|
|
|
|
case HDR_TYPE_FLOAT:
|
|
return 1.0;
|
|
break;
|
|
|
|
case HDR_TYPE_INTEGER:
|
|
return 16.0;
|
|
|
|
case HDR_TYPE_NONE:
|
|
default:
|
|
return GammaToLinearFullRange( 2.0 ); // light map scale
|
|
}
|
|
}
|
|
|
|
// Gets the lightmap dimensions
|
|
void CShaderAPIDx11::GetLightmapDimensions( int *w, int *h )
|
|
{
|
|
g_pShaderUtil->GetLightmapDimensions( w, h );
|
|
}
|
|
|
|
// Flushes any primitives that are buffered
|
|
void CShaderAPIDx11::FlushBufferedPrimitives()
|
|
{
|
|
if ( ShaderUtil() )
|
|
{
|
|
if ( !ShaderUtil()->OnFlushBufferedPrimitives() )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
LOCK_SHADERAPI();
|
|
// This shouldn't happen in the inner rendering loop!
|
|
//Assert( m_pMesh == 0 );
|
|
|
|
// NOTE: We've gotta store off the matrix mode because
|
|
// it'll get reset by the default state application caused by the flush
|
|
MaterialMatrixMode_t oldMatMode = m_MatrixMode;
|
|
|
|
MeshMgr()->Flush();
|
|
|
|
m_MatrixMode = oldMatMode;
|
|
}
|
|
|
|
// Creates/destroys Mesh
|
|
IMesh *CShaderAPIDx11::CreateStaticMesh( VertexFormat_t fmt, const char *pTextureBudgetGroup, IMaterial *pMaterial )
|
|
{
|
|
return MeshMgr()->CreateStaticMesh( fmt, pTextureBudgetGroup, pMaterial );
|
|
}
|
|
|
|
void CShaderAPIDx11::DestroyStaticMesh( IMesh *mesh )
|
|
{
|
|
MeshMgr()->DestroyStaticMesh( 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 *CShaderAPIDx11::GetDynamicMesh( IMaterial *pMaterial, int nHWSkinBoneCount, bool buffered, IMesh *pVertexOverride, IMesh *pIndexOverride )
|
|
{
|
|
return MeshMgr()->GetDynamicMesh( pMaterial, 0, nHWSkinBoneCount, buffered, pVertexOverride, pIndexOverride );
|
|
}
|
|
|
|
IMesh *CShaderAPIDx11::GetDynamicMeshEx( IMaterial *pMaterial, VertexFormat_t fmt, int nHWSkinBoneCount, bool buffered, IMesh *pVertexOverride, IMesh *pIndexOverride )
|
|
{
|
|
return MeshMgr()->GetDynamicMesh( pMaterial, fmt, nHWSkinBoneCount, buffered, pVertexOverride, pIndexOverride );
|
|
}
|
|
|
|
IVertexBuffer *CShaderAPIDx11::GetDynamicVertexBuffer( IMaterial *pMaterial, bool buffered )
|
|
{
|
|
return MeshMgr()->GetDynamicVertexBuffer( pMaterial, buffered );
|
|
}
|
|
|
|
IIndexBuffer *CShaderAPIDx11::GetDynamicIndexBuffer( IMaterial *pMaterial, bool buffered )
|
|
{
|
|
return MeshMgr()->GetDynamicIndexBuffer( pMaterial, buffered );
|
|
}
|
|
|
|
IMesh *CShaderAPIDx11::GetFlexMesh()
|
|
{
|
|
return MeshMgr()->GetFlexMesh();
|
|
}
|
|
|
|
bool CShaderAPIDx11::IsDeactivated() const
|
|
{
|
|
return g_pShaderDeviceDx11->IsDeactivated();
|
|
}
|
|
|
|
// stuff related to matrix stacks
|
|
//
|
|
// Note Dx11 doesn't have a matrix stack, you just supply
|
|
// the matrices to the shader in a constant buffer, so we will
|
|
// not break compatibility with Dx9 and just emulate the behavior.
|
|
|
|
bool CShaderAPIDx11::MatrixIsChanging()
|
|
{
|
|
if ( IsDeactivated() )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( m_MatrixMode == MATERIAL_MODEL || m_MatrixMode == MATERIAL_VIEW || m_MatrixMode == MATERIAL_PROJECTION )
|
|
{
|
|
FlushBufferedPrimitives();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void CShaderAPIDx11::HandleMatrixModified()
|
|
{
|
|
m_ShaderState.m_ChangedMatrices[m_MatrixMode] = true;
|
|
if ( m_MatrixMode == MATERIAL_MODEL )
|
|
{
|
|
// The model matrix is also the first bone matrix
|
|
m_ShaderState.bone.m_bBonesChanged = true;
|
|
}
|
|
}
|
|
|
|
static DirectX::XMMATRIX s_DXMatIdent = DirectX::XMMatrixIdentity();
|
|
|
|
DirectX::XMMATRIX &CShaderAPIDx11::GetMatrix( MaterialMatrixMode_t mode )
|
|
{
|
|
CUtlStack<StatesDx11::MatrixItem_t> &curStack = m_ShaderState.m_MatrixStacks[mode];
|
|
if ( !curStack.Count() )
|
|
{
|
|
return s_DXMatIdent;
|
|
}
|
|
|
|
return m_ShaderState.m_MatrixStacks[mode].Top().m_Matrix;
|
|
}
|
|
|
|
DirectX::XMMATRIX &CShaderAPIDx11::GetCurrentMatrix()
|
|
{
|
|
return m_pCurMatrixItem->m_Matrix;
|
|
}
|
|
|
|
DirectX::XMMATRIX CShaderAPIDx11::GetMatrixCopy( MaterialMatrixMode_t mode ) const
|
|
{
|
|
const CUtlStack<StatesDx11::MatrixItem_t> &curStack = m_ShaderState.m_MatrixStacks[mode];
|
|
if ( !curStack.Count() )
|
|
{
|
|
return DirectX::XMMatrixIdentity();
|
|
}
|
|
|
|
return m_ShaderState.m_MatrixStacks[mode].Top().m_Matrix;
|
|
}
|
|
|
|
DirectX::XMMATRIX CShaderAPIDx11::GetCurrentMatrixCopy() const
|
|
{
|
|
return m_pCurMatrixItem->m_Matrix;
|
|
}
|
|
|
|
void CShaderAPIDx11::MatrixMode( MaterialMatrixMode_t matrixMode )
|
|
{
|
|
Assert( m_ShaderState.m_MatrixStacks[matrixMode].Count() );
|
|
m_MatrixMode = matrixMode;
|
|
m_pCurMatrixItem = &m_ShaderState.m_MatrixStacks[matrixMode].Top();
|
|
}
|
|
|
|
void CShaderAPIDx11::PushMatrix()
|
|
{
|
|
// Does nothing in Dx11
|
|
//GetCurrentMatrix() = DirectX::XMMatrixTranspose( GetCurrentMatrix() );
|
|
|
|
CUtlStack<StatesDx11::MatrixItem_t> &curStack = m_ShaderState.m_MatrixStacks[m_MatrixMode];
|
|
Assert( curStack.Count() );
|
|
int iNew = m_ShaderState.m_MatrixStacks[m_MatrixMode].Push();
|
|
curStack[iNew] = curStack[iNew - 1];
|
|
m_pCurMatrixItem = &m_ShaderState.m_MatrixStacks[m_MatrixMode].Top();
|
|
|
|
HandleMatrixModified();
|
|
}
|
|
|
|
void CShaderAPIDx11::PopMatrix()
|
|
{
|
|
MatrixIsChanging();
|
|
|
|
Assert( m_ShaderState.m_MatrixStacks[m_MatrixMode].Count() > 1 );
|
|
m_ShaderState.m_MatrixStacks[m_MatrixMode].Pop();
|
|
m_pCurMatrixItem = &m_ShaderState.m_MatrixStacks[m_MatrixMode].Top();
|
|
|
|
HandleMatrixModified();
|
|
}
|
|
|
|
void CShaderAPIDx11::LoadMatrix( float *m )
|
|
{
|
|
MatrixIsChanging();
|
|
|
|
DirectX::XMFLOAT4X4 flt4x4( m );
|
|
GetCurrentMatrix() = DirectX::XMLoadFloat4x4( &flt4x4 );
|
|
HandleMatrixModified();
|
|
}
|
|
|
|
void CShaderAPIDx11::LoadBoneMatrix( int boneIndex, const float *m )
|
|
{
|
|
// NOTE: Bone matrices are column major, and HLSL is column-major,
|
|
// so we don't have to transpose anything.
|
|
|
|
m_ShaderState.bone.m_BoneMatrix[boneIndex] = DirectX::XMFLOAT3X4A( m );
|
|
m_ShaderState.bone.m_bBonesChanged = true;
|
|
if ( boneIndex > m_ShaderState.bone.m_MaxBoneLoaded )
|
|
{
|
|
m_ShaderState.bone.m_MaxBoneLoaded = boneIndex;
|
|
}
|
|
if ( boneIndex == 0 )
|
|
{
|
|
// We have to transpose here because when loading
|
|
// the model matrix into the shader it gets transposed again.
|
|
MatrixMode( MATERIAL_MODEL );
|
|
VMatrix boneMatrix;
|
|
boneMatrix.Init( *(matrix3x4_t *)m );
|
|
MatrixTranspose( boneMatrix, boneMatrix );
|
|
LoadMatrix( boneMatrix.Base() );
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::MultMatrix( float *m )
|
|
{
|
|
MatrixIsChanging();
|
|
DirectX::XMFLOAT4X4 flt4x4( m );
|
|
GetCurrentMatrix() = DirectX::XMMatrixMultiply(
|
|
GetCurrentMatrix(), DirectX::XMLoadFloat4x4( &flt4x4 ) );
|
|
HandleMatrixModified();
|
|
}
|
|
|
|
void CShaderAPIDx11::MultMatrixLocal( float *m )
|
|
{
|
|
MatrixIsChanging();
|
|
// DX11FIXME: Local multiply
|
|
DirectX::XMFLOAT4X4 flt4x4( m );
|
|
GetCurrentMatrix() = DirectX::XMMatrixMultiply(
|
|
DirectX::XMLoadFloat4x4( &flt4x4 ), GetCurrentMatrix() );
|
|
HandleMatrixModified();
|
|
}
|
|
|
|
void CShaderAPIDx11::GetMatrix( MaterialMatrixMode_t matrixMode, float *dst )
|
|
{
|
|
DirectX::XMFLOAT4X4 flt4x4;
|
|
DirectX::XMStoreFloat4x4( &flt4x4, GetMatrix( matrixMode ) );
|
|
memcpy( dst, &flt4x4, sizeof( DirectX::XMFLOAT4X4 ) );
|
|
}
|
|
|
|
void CShaderAPIDx11::GetMatrix( MaterialMatrixMode_t matrixMode, DirectX::XMMATRIX &mat )
|
|
{
|
|
mat = GetMatrix( matrixMode );
|
|
}
|
|
|
|
void CShaderAPIDx11::LoadIdentity( void )
|
|
{
|
|
MatrixIsChanging();
|
|
m_pCurMatrixItem->m_Matrix = DirectX::XMMatrixIdentity();
|
|
HandleMatrixModified();
|
|
}
|
|
|
|
void CShaderAPIDx11::LoadCameraToWorld( void )
|
|
{
|
|
MatrixIsChanging();
|
|
|
|
DirectX::XMMATRIX inv;
|
|
inv = DirectX::XMMatrixInverse( NULL, GetMatrix( MATERIAL_VIEW ) );
|
|
|
|
DirectX::XMFLOAT4X4 flt4x4inv;
|
|
DirectX::XMStoreFloat4x4( &flt4x4inv, inv );
|
|
|
|
// Kill translation
|
|
flt4x4inv.m[3][0] = flt4x4inv.m[3][1] = flt4x4inv.m[3][2] = 0.0f;
|
|
inv = DirectX::XMLoadFloat4x4( &flt4x4inv );
|
|
|
|
m_pCurMatrixItem->m_Matrix = inv;
|
|
|
|
HandleMatrixModified();
|
|
}
|
|
|
|
// Get the current camera position in world space.
|
|
void CShaderAPIDx11::GetWorldSpaceCameraPosition( float *pPos ) const
|
|
{
|
|
DirectX::XMFLOAT4X4 flt4x4;
|
|
const DirectX::XMMATRIX &view = GetMatrixCopy( MATERIAL_VIEW );
|
|
DirectX::XMStoreFloat4x4( &flt4x4, view );
|
|
memcpy( pPos, &flt4x4, sizeof( DirectX::XMFLOAT4X4 ) );
|
|
}
|
|
|
|
void CShaderAPIDx11::Ortho( double left, double top, double right, double bottom, double zNear, double zFar )
|
|
{
|
|
MatrixIsChanging();
|
|
|
|
DirectX::XMMATRIX mat = DirectX::XMMatrixOrthographicOffCenterRH( left, right, bottom, top, zNear, zFar );
|
|
|
|
// DX11FIXME: Local multiply
|
|
GetCurrentMatrix() = DirectX::XMMatrixMultiply( mat, GetCurrentMatrix() );
|
|
|
|
HandleMatrixModified();
|
|
}
|
|
|
|
void CShaderAPIDx11::PerspectiveX( double fovx, double aspect, double zNear, double zFar )
|
|
{
|
|
MatrixIsChanging();
|
|
|
|
float width = 2 * zNear * tan( fovx * M_PI / 360.0 );
|
|
float height = width / aspect;
|
|
DirectX::XMMATRIX mat;
|
|
mat = DirectX::XMMatrixPerspectiveRH( width, height, zNear, zFar );
|
|
|
|
// DX11FIXME: Local multiply
|
|
GetCurrentMatrix() = DirectX::XMMatrixMultiply( mat, GetCurrentMatrix() );
|
|
|
|
HandleMatrixModified();
|
|
}
|
|
|
|
void CShaderAPIDx11::PerspectiveOffCenterX( double fovx, double aspect, double zNear, double zFar, double bottom, double top, double left, double right )
|
|
{
|
|
MatrixIsChanging();
|
|
|
|
float width = 2 * zNear * tan( fovx * M_PI / 360.0 );
|
|
float height = width / aspect;
|
|
|
|
// bottom, top, left, right are 0..1 so convert to -1..1
|
|
float flFrontPlaneLeft = -( width / 2.0f ) * ( 1.0f - left ) + left * ( width / 2.0f );
|
|
float flFrontPlaneRight = -( width / 2.0f ) * ( 1.0f - right ) + right * ( width / 2.0f );
|
|
float flFrontPlaneBottom = -( height / 2.0f ) * ( 1.0f - bottom ) + bottom * ( height / 2.0f );
|
|
float flFrontPlaneTop = -( height / 2.0f ) * ( 1.0f - top ) + top * ( height / 2.0f );
|
|
|
|
DirectX::XMMATRIX mat;
|
|
mat = DirectX::XMMatrixPerspectiveOffCenterRH( flFrontPlaneLeft, flFrontPlaneRight, flFrontPlaneBottom,
|
|
flFrontPlaneTop, zNear, zFar );
|
|
|
|
// DX11FIXME: Local multiply
|
|
GetCurrentMatrix() = DirectX::XMMatrixMultiply( mat, GetCurrentMatrix() );
|
|
|
|
HandleMatrixModified();
|
|
}
|
|
|
|
void CShaderAPIDx11::PickMatrix( int x, int y, int width, int height )
|
|
{
|
|
MatrixIsChanging();
|
|
|
|
ShaderViewport_t viewport;
|
|
GetViewports( &viewport, 1 );
|
|
|
|
int vx = viewport.m_nTopLeftX;
|
|
int vy = viewport.m_nTopLeftX;
|
|
int vwidth = viewport.m_nWidth;
|
|
int vheight = viewport.m_nHeight;
|
|
|
|
// Compute the location of the pick region in projection space...
|
|
float px = 2.0 * (float)( x - vx ) / (float)vwidth - 1;
|
|
float py = 2.0 * (float)( y - vy ) / (float)vheight - 1;
|
|
float pw = 2.0 * (float)width / (float)vwidth;
|
|
float ph = 2.0 * (float)height / (float)vheight;
|
|
|
|
// we need to translate (px, py) to the origin
|
|
// and scale so (pw,ph) -> (2, 2)
|
|
DirectX::XMMATRIX mat;
|
|
mat = DirectX::XMMatrixTranslation( -2.0f * py / ph, -2.0f * px / pw, 0.0f );
|
|
mat = DirectX::XMMatrixMultiply( mat, DirectX::XMMatrixScaling( 2.0f / pw, 2.0f / ph, 1.0f ) );
|
|
|
|
// DX11FIXME: Local multiply
|
|
GetCurrentMatrix() = DirectX::XMMatrixMultiply( mat, GetCurrentMatrix() );
|
|
|
|
HandleMatrixModified();
|
|
}
|
|
|
|
void CShaderAPIDx11::Rotate( float angle, float x, float y, float z )
|
|
{
|
|
MatrixIsChanging();
|
|
|
|
DirectX::XMVECTOR axis;
|
|
axis = DirectX::XMVectorSet( x, y, z, 0 );
|
|
|
|
// DX11FIXME: Local multiply
|
|
GetCurrentMatrix() = DirectX::XMMatrixMultiply( DirectX::XMMatrixRotationAxis( axis, M_PI * angle / 180.0f ), GetCurrentMatrix() );
|
|
|
|
HandleMatrixModified();
|
|
}
|
|
|
|
void CShaderAPIDx11::Translate( float x, float y, float z )
|
|
{
|
|
MatrixIsChanging();
|
|
|
|
// DX11FIXME: Local multiply
|
|
GetCurrentMatrix() = DirectX::XMMatrixMultiply( DirectX::XMMatrixTranslation( x, y, z ), GetCurrentMatrix() );
|
|
HandleMatrixModified();
|
|
}
|
|
|
|
void CShaderAPIDx11::Scale( float x, float y, float z )
|
|
{
|
|
MatrixIsChanging();
|
|
|
|
// DX11FIXME: Local multiply
|
|
GetCurrentMatrix() = DirectX::XMMatrixMultiply( DirectX::XMMatrixScaling( x, y, z ), GetCurrentMatrix() );
|
|
HandleMatrixModified();
|
|
}
|
|
|
|
void CShaderAPIDx11::ScaleXY( float x, float y )
|
|
{
|
|
MatrixIsChanging();
|
|
|
|
// DX11FIXME: Local multiply
|
|
GetCurrentMatrix() = DirectX::XMMatrixMultiply( DirectX::XMMatrixScaling( x, y, 1.0f ), GetCurrentMatrix() );
|
|
HandleMatrixModified();
|
|
}
|
|
|
|
// Fog methods...
|
|
void CShaderAPIDx11::FogMode( MaterialFogMode_t fogMode )
|
|
{
|
|
if ( fogMode != m_ShaderState.fog.m_FogMode )
|
|
{
|
|
m_ShaderState.fog.m_FogMode = fogMode;
|
|
m_ShaderState.fog.m_bFogChanged = true;
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::FogStart( float fStart )
|
|
{
|
|
if ( fStart != m_ShaderState.fog.m_flFogStart )
|
|
{
|
|
m_ShaderState.fog.m_flFogStart = fStart;
|
|
m_ShaderState.fog.m_bFogChanged = true;
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::FogEnd( float fEnd )
|
|
{
|
|
if ( m_ShaderState.fog.m_flFogEnd != fEnd )
|
|
{
|
|
m_ShaderState.fog.m_flFogStart = fEnd;
|
|
m_ShaderState.fog.m_bFogChanged = true;
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::SetFogZ( float fogZ )
|
|
{
|
|
if ( m_ShaderState.fog.m_flFogZ != fogZ )
|
|
{
|
|
m_ShaderState.fog.m_flFogZ = fogZ;
|
|
m_ShaderState.fog.m_bFogChanged = true;
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::FogMaxDensity( float flMaxDensity )
|
|
{
|
|
if ( m_ShaderState.fog.m_flFogMaxDensity != flMaxDensity )
|
|
{
|
|
m_ShaderState.fog.m_flFogMaxDensity = flMaxDensity;
|
|
m_ShaderState.fog.m_bFogChanged = true;
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::GetFogDistances( float *fStart, float *fEnd, float *fFogZ )
|
|
{
|
|
*fStart = m_ShaderState.fog.m_flFogStart;
|
|
*fEnd = m_ShaderState.fog.m_flFogEnd;
|
|
*fFogZ = m_ShaderState.fog.m_flFogZ;
|
|
}
|
|
|
|
void CShaderAPIDx11::SceneFogColor3ub( unsigned char r, unsigned char g, unsigned char b )
|
|
{
|
|
m_ShaderState.fog.m_FogColor[0] = r / 255.0f;
|
|
m_ShaderState.fog.m_FogColor[1] = g / 255.0f;
|
|
m_ShaderState.fog.m_FogColor[2] = b / 255.0f;
|
|
m_ShaderState.fog.m_bFogChanged = true;
|
|
}
|
|
|
|
void CShaderAPIDx11::SceneFogMode( MaterialFogMode_t fogMode )
|
|
{
|
|
if ( fogMode != m_ShaderState.fog.m_FogMode )
|
|
{
|
|
m_ShaderState.fog.m_FogMode = fogMode;
|
|
m_ShaderState.fog.m_bFogChanged = true;
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::GetSceneFogColor( unsigned char *rgb )
|
|
{
|
|
rgb[0] = (unsigned char)( m_ShaderState.fog.m_FogColor[0] * 255 );
|
|
rgb[1] = (unsigned char)( m_ShaderState.fog.m_FogColor[1] * 255 );
|
|
rgb[2] = (unsigned char)( m_ShaderState.fog.m_FogColor[2] * 255 );
|
|
}
|
|
|
|
// Sigh... I don't understand why there's two different fog settings
|
|
MaterialFogMode_t CShaderAPIDx11::GetSceneFogMode()
|
|
{
|
|
return m_ShaderState.fog.m_FogMode;
|
|
}
|
|
|
|
int CShaderAPIDx11::GetPixelFogCombo()
|
|
{
|
|
if ( m_ShaderState.fog.m_FogMode != MATERIAL_FOG_NONE )
|
|
return m_ShaderState.fog.m_FogMode - 1;
|
|
else
|
|
return MATERIAL_FOG_NONE;
|
|
}
|
|
|
|
void CShaderAPIDx11::FogColor3f( float r, float g, float b )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::FogColor3fv( float const *rgb )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::FogColor3ub( unsigned char r, unsigned char g, unsigned char b )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::FogColor3ubv( unsigned char const *rgb )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::GetFogColor( float *rgb )
|
|
{
|
|
//const StatesDx11::ShadowState *state = g_pShaderShadowDx11->GetShadowState( m_CurrentSnapshot );
|
|
}
|
|
|
|
void CShaderAPIDx11::GetFogParamsAndColor( float *fogParams, float *rgba )
|
|
{
|
|
const StatesDx11::ShadowState *state = g_pShaderShadowDx11->GetShadowState( m_CurrentSnapshot );
|
|
|
|
// Compute fog parameters
|
|
|
|
if ( GetSceneFogMode() != MATERIAL_FOG_NONE && state->desc.fogMode != SHADER_FOGMODE_DISABLED )
|
|
{
|
|
float fStart = m_ShaderState.fog.m_flFogStart;
|
|
float fEnd = m_ShaderState.fog.m_flFogEnd;
|
|
|
|
fogParams[0] = fStart * 2; // fog begin distance
|
|
fogParams[1] = fEnd * 1.5f; // fog end distance (fully fogged)
|
|
fogParams[2] = clamp( m_ShaderState.fog.m_flFogMaxDensity, 0.0f, 1.0f ); // Max fog factor
|
|
fogParams[3] = m_ShaderState.fog.m_flFogZ; // water height
|
|
}
|
|
else
|
|
{
|
|
//emulating MATERIAL_FOG_NONE by setting the parameters so that CalcRangeFog() always returns 0. Gets rid of a dynamic combo across the ps2x set.
|
|
fogParams[0] = 1.0f; // begin
|
|
fogParams[1] = 1.0f; // end
|
|
fogParams[2] = 0.0f; // Max fog density
|
|
fogParams[3] = 0.0f; // water height
|
|
|
|
rgba[0] = 0.0f;
|
|
rgba[1] = 0.0f;
|
|
rgba[2] = 0.0f;
|
|
rgba[3] = 0.0f;
|
|
|
|
return;
|
|
}
|
|
|
|
// Compute fog color
|
|
|
|
ShaderFogMode_t fogMode = state->desc.fogMode;
|
|
bool bDisableFogGammaCorrection = state->desc.disableFogGammaCorrection;
|
|
bool bShouldGammaCorrect = true; // By default, we'll gamma correct.
|
|
unsigned char rgb[3] = { 0 };
|
|
|
|
switch ( fogMode )
|
|
{
|
|
case SHADER_FOGMODE_BLACK: // Additive decals
|
|
bShouldGammaCorrect = false;
|
|
break;
|
|
case SHADER_FOGMODE_OO_OVERBRIGHT:
|
|
case SHADER_FOGMODE_GREY: // Mod2x decals
|
|
rgb[0] = rgb[1] = rgb[2] = 128;
|
|
break;
|
|
case SHADER_FOGMODE_WHITE: // Multiplicative decals
|
|
rgb[0] = rgb[1] = rgb[2] = 255;
|
|
bShouldGammaCorrect = false;
|
|
break;
|
|
case SHADER_FOGMODE_FOGCOLOR:
|
|
GetSceneFogColor( rgb ); // Scene fog color
|
|
break;
|
|
NO_DEFAULT
|
|
}
|
|
|
|
rgba[0] = rgb[0] / 255.0f;
|
|
rgba[1] = rgb[1] / 255.0f;
|
|
rgba[2] = rgb[2] / 255.0f;
|
|
rgba[3] = 1.0f;
|
|
|
|
bShouldGammaCorrect &= !bDisableFogGammaCorrection;
|
|
if ( bShouldGammaCorrect )
|
|
{
|
|
GammaCorrectFogColor( rgba );
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::GammaCorrectFogColor( float *rgb )
|
|
{
|
|
bool bLinearSpace = g_pHardwareConfig->GetHDRType() == HDR_TYPE_FLOAT;
|
|
|
|
bool bScaleFogByToneMappingScale = false;//g_pHardwareConfig->GetHDRType() == HDR_TYPE_INTEGER;
|
|
|
|
float fr = rgb[0];
|
|
float fg = rgb[1];
|
|
float fb = rgb[2];
|
|
if ( bLinearSpace )
|
|
{
|
|
fr = GammaToLinear( fr );
|
|
fg = GammaToLinear( fg );
|
|
fb = GammaToLinear( fb );
|
|
if ( bScaleFogByToneMappingScale )
|
|
{
|
|
fr *= m_ShaderState.m_ToneMappingScale.x; //
|
|
fg *= m_ShaderState.m_ToneMappingScale.x; // Linear
|
|
fb *= m_ShaderState.m_ToneMappingScale.x; //
|
|
}
|
|
}
|
|
|
|
else if ( bScaleFogByToneMappingScale )
|
|
{
|
|
fr *= m_ShaderState.m_ToneMappingScale.w; //
|
|
fg *= m_ShaderState.m_ToneMappingScale.w; // Gamma
|
|
fb *= m_ShaderState.m_ToneMappingScale.w; //
|
|
}
|
|
|
|
fr = min( fr, 1.0f );
|
|
fg = min( fg, 1.0f );
|
|
fb = min( fb, 1.0f );
|
|
|
|
rgb[0] = fr;
|
|
rgb[1] = fg;
|
|
rgb[2] = fb;
|
|
}
|
|
|
|
// KMS
|
|
MaterialFogMode_t CShaderAPIDx11::GetCurrentFogType( void ) const
|
|
{
|
|
return m_ShaderState.fog.m_FogMode;
|
|
}
|
|
|
|
// Sets the *dynamic* vertex and pixel shaders
|
|
void CShaderAPIDx11::SetVertexShaderIndex( ShaderIndex_t vshIndex )
|
|
{
|
|
ShaderManager()->SetVertexShaderIndex( vshIndex );
|
|
ShaderManager()->SetVertexShader( g_pShaderShadowDx11->GetShadowState( m_CurrentSnapshot )->desc.vertexShader );
|
|
}
|
|
|
|
void CShaderAPIDx11::SetPixelShaderIndex( ShaderIndex_t pshIndex )
|
|
{
|
|
ShaderManager()->SetPixelShaderIndex( pshIndex );
|
|
ShaderManager()->SetPixelShader( g_pShaderShadowDx11->GetShadowState( m_CurrentSnapshot )->desc.pixelShader );
|
|
}
|
|
|
|
// Returns the nearest supported format
|
|
ImageFormat CShaderAPIDx11::GetNearestSupportedFormat( ImageFormat fmt, bool bFilteringRequired /* = true */ ) const
|
|
{
|
|
return CTextureDx11::GetClosestSupportedImageFormatForD3D11( fmt );
|
|
}
|
|
|
|
ImageFormat CShaderAPIDx11::GetNearestRenderTargetFormat( ImageFormat fmt ) const
|
|
{
|
|
return CTextureDx11::GetClosestSupportedImageFormatForD3D11( fmt );
|
|
}
|
|
|
|
// Sets the texture state
|
|
void CShaderAPIDx11::BindTexture( Sampler_t stage, ShaderAPITextureHandle_t textureHandle )
|
|
{
|
|
CTextureDx11 *pTex = &GetTexture( textureHandle );
|
|
|
|
if ( !pTex )
|
|
return;
|
|
|
|
StatesDx11::DynamicState &dynamic = m_DynamicState;
|
|
|
|
ID3D11ShaderResourceView *pView = pTex->GetView();
|
|
ID3D11SamplerState *pSampler = pTex->GetSamplerState();
|
|
|
|
if ( pView != dynamic.m_ppTextures[stage] )
|
|
{
|
|
dynamic.m_ppTextures[stage] = pView;
|
|
|
|
SetStateFlag( STATE_CHANGED_TEXTURES );
|
|
}
|
|
|
|
if ( pSampler != dynamic.m_ppSamplers[stage] )
|
|
{
|
|
dynamic.m_ppSamplers[stage] = pSampler;
|
|
|
|
SetStateFlag( STATE_CHANGED_SAMPLERS );
|
|
}
|
|
|
|
if ( stage > dynamic.m_MaxPSSampler )
|
|
{
|
|
dynamic.m_MaxPSSampler = stage;
|
|
|
|
if ( dynamic.m_MaxPSSampler > dynamic.m_PrevMaxPSSampler )
|
|
{
|
|
SetStateFlag( STATE_CHANGED_SAMPLERS | STATE_CHANGED_TEXTURES );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::UnbindTexture( ShaderAPITextureHandle_t textureHandle )
|
|
{
|
|
|
|
CTextureDx11 *pTex = &GetTexture( textureHandle );
|
|
|
|
// Unbind the sampler
|
|
|
|
int iSampler = -1;
|
|
for ( int i = 0; i < m_DynamicState.m_MaxPSSampler + 1; i++ )
|
|
{
|
|
if ( m_DynamicState.m_ppTextures[i] == pTex->GetView() )
|
|
{
|
|
iSampler = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( iSampler == -1 )
|
|
return;
|
|
|
|
m_DynamicState.m_ppSamplers[iSampler] = NULL;
|
|
m_DynamicState.m_ppTextures[iSampler] = NULL;
|
|
|
|
int maxSampler = -1;
|
|
for ( int i = 0; i < MAX_DX11_SAMPLERS; i++ )
|
|
{
|
|
if ( m_DynamicState.m_ppTextures[i] != NULL )
|
|
{
|
|
maxSampler = i;
|
|
}
|
|
}
|
|
|
|
m_DynamicState.m_MaxPSSampler = maxSampler;
|
|
|
|
SetStateFlag( STATE_CHANGED_SAMPLERS | STATE_CHANGED_TEXTURES );
|
|
|
|
}
|
|
|
|
// Indicates we're going to be modifying this texture
|
|
// TexImage2D, TexSubImage2D, TexWrap, TexMinFilter, and TexMagFilter
|
|
// all use the texture specified by this function.
|
|
void CShaderAPIDx11::ModifyTexture( ShaderAPITextureHandle_t textureHandle )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
// Can't do this if we're locked!
|
|
Assert( m_ModifyTextureLockedLevel < 0 );
|
|
|
|
m_ModifyTextureHandle = textureHandle;
|
|
|
|
// If we've got a multi-copy texture, we need to up the current copy count
|
|
CTextureDx11 &tex = GetTexture( textureHandle );
|
|
if ( tex.m_NumCopies > 1 )
|
|
{
|
|
// Each time we modify a texture, we'll want to switch texture
|
|
// as soon as a TexImage2D call is made...
|
|
tex.m_SwitchNeeded = true;
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::AdvanceCurrentTextureCopy( ShaderAPITextureHandle_t texture )
|
|
{
|
|
// May need to switch textures....
|
|
CTextureDx11 &tex = GetTexture( texture );
|
|
if ( tex.m_NumCopies > 1 )
|
|
{
|
|
if ( ++tex.m_CurrentCopy >= tex.m_NumCopies )
|
|
tex.m_CurrentCopy = 0;
|
|
|
|
// When the current copy changes, we need to make sure this texture
|
|
// isn't bound to any stages any more; thereby guaranteeing the new
|
|
// copy will be re-bound.
|
|
UnbindTexture( texture );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Texture image upload
|
|
//
|
|
// level: mipmap level we are writing to
|
|
// cubeFace: face of the cubemap/array texture we are writing to
|
|
// dstFormat: unused
|
|
// zOffset: not sure
|
|
// width: image width
|
|
// height image height
|
|
// srcFormat: format of the source image data
|
|
// bSrcIsTiled: is the source image a tiled image
|
|
// imageData: pointer to the beginning of the source image data
|
|
//-----------------------------------------------------------------------------
|
|
void CShaderAPIDx11::TexImage2D( int level, int cubeFace, ImageFormat dstFormat, int zOffset, int width, int height,
|
|
ImageFormat srcFormat, bool bSrcIsTiled, void *imageData )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
Assert( imageData );
|
|
ShaderAPITextureHandle_t hModifyTexture = m_ModifyTextureHandle;
|
|
if ( !m_Textures.IsValidIndex( hModifyTexture ) )
|
|
{
|
|
Log( "Invalid modify texture handle!\n" );
|
|
return;
|
|
|
|
}
|
|
|
|
//if ( zOffset != 0 )
|
|
//DebuggerBreak();
|
|
|
|
|
|
Assert( ( width <= g_pHardwareConfig->Caps().m_MaxTextureWidth ) &&
|
|
( height <= g_pHardwareConfig->Caps().m_MaxTextureHeight ) );
|
|
|
|
// Blow off mip levels if we don't support mipmapping
|
|
if ( !g_pHardwareConfig->SupportsMipmapping() && ( level > 0 ) )
|
|
{
|
|
Log( "Trying to image mip but we don't support mips!\n" );
|
|
return;
|
|
}
|
|
|
|
// This test here just makes sure we don't try to download mipmap levels
|
|
// if we weren't able to create them in the first place
|
|
CTextureDx11 &tex = GetTexture( hModifyTexture );
|
|
if ( level >= tex.m_NumLevels )
|
|
{
|
|
Log( "level >= tex.m_NumLevels\n" );
|
|
return;
|
|
}
|
|
|
|
// May need to switch textures....
|
|
if ( tex.m_SwitchNeeded )
|
|
{
|
|
AdvanceCurrentTextureCopy( hModifyTexture );
|
|
tex.m_SwitchNeeded = false;
|
|
}
|
|
|
|
CTextureDx11::TextureLoadInfo_t info;
|
|
info.m_TextureHandle = hModifyTexture;
|
|
info.m_pTexture = GetD3DTexture( hModifyTexture );
|
|
info.m_pView = tex.GetView();
|
|
info.m_nLevel = level;
|
|
info.m_nCopy = tex.m_CurrentCopy;
|
|
info.m_CubeFaceID = (D3D11_TEXTURECUBE_FACE)cubeFace;
|
|
info.m_nWidth = width;
|
|
info.m_nHeight = height;
|
|
info.m_nZOffset = zOffset;
|
|
info.m_SrcFormat = srcFormat;
|
|
info.m_pSrcData = (unsigned char *)imageData;
|
|
tex.LoadTexImage( info );
|
|
}
|
|
|
|
void CShaderAPIDx11::TexSubImage2D( int level, int cubeFace, int xOffset, int yOffset, int zOffset, int width, int height,
|
|
ImageFormat srcFormat, int srcStride, bool bSrcIsTiled, void *imageData )
|
|
{
|
|
//Log( "TexSubImage2D!\n" );
|
|
|
|
LOCK_SHADERAPI();
|
|
Assert( imageData );
|
|
ShaderAPITextureHandle_t hModifyTexture = m_ModifyTextureHandle;
|
|
if ( !m_Textures.IsValidIndex( hModifyTexture ) )
|
|
{
|
|
Log( "Invalid modify texture handle!\n" );
|
|
return;
|
|
|
|
}
|
|
|
|
//if ( zOffset != 0 )
|
|
//DebuggerBreak();
|
|
|
|
// Blow off mip levels if we don't support mipmapping
|
|
if ( !g_pHardwareConfig->SupportsMipmapping() && ( level > 0 ) )
|
|
{
|
|
Log( "Trying to image mip but we don't support mips!\n" );
|
|
return;
|
|
}
|
|
|
|
CTextureDx11 &tex = GetTexture( hModifyTexture );
|
|
|
|
// NOTE: This can only be done with procedural textures if this method is
|
|
// being used to download the entire texture, cause last frame's partial update
|
|
// may be in a completely different texture! Sadly, I don't have all of the
|
|
// information I need, but I can at least check a couple things....
|
|
#ifdef _DEBUG
|
|
if ( tex.m_NumCopies > 1 )
|
|
{
|
|
Assert( ( xOffset == 0 ) && ( yOffset == 0 ) );
|
|
}
|
|
#endif
|
|
|
|
// This test here just makes sure we don't try to download mipmap levels
|
|
// if we weren't able to create them in the first place
|
|
if ( level >= tex.m_NumLevels )
|
|
{
|
|
Log( "level >= tex.m_NumLevels\n" );
|
|
return;
|
|
}
|
|
|
|
// May need to switch textures....
|
|
if ( tex.m_SwitchNeeded )
|
|
{
|
|
AdvanceCurrentTextureCopy( hModifyTexture );
|
|
tex.m_SwitchNeeded = false;
|
|
}
|
|
|
|
CTextureDx11::TextureLoadInfo_t info;
|
|
info.m_TextureHandle = hModifyTexture;
|
|
info.m_pTexture = GetD3DTexture( hModifyTexture );
|
|
info.m_pView = tex.GetView();
|
|
info.m_nLevel = level;
|
|
info.m_nCopy = tex.m_CurrentCopy;
|
|
info.m_CubeFaceID = (D3D11_TEXTURECUBE_FACE)cubeFace;
|
|
info.m_nWidth = width;
|
|
info.m_nHeight = height;
|
|
info.m_nZOffset = zOffset;
|
|
info.m_SrcFormat = srcFormat;
|
|
info.m_pSrcData = (unsigned char *)imageData;
|
|
tex.LoadTexImage( info, xOffset, yOffset, srcStride );
|
|
}
|
|
|
|
void CShaderAPIDx11::TexImageFromVTF(IVTFTexture* pVTF, int iVTFFrame)
|
|
{
|
|
TexImage2D(0, 0, pVTF->Format(), 0, pVTF->Width(), pVTF->Height(), pVTF->Format(), false, pVTF->ImageData(iVTFFrame, 0, 0));
|
|
}
|
|
|
|
bool CShaderAPIDx11::TexLock( int level, int cubeFaceID, int xOffset, int yOffset,
|
|
int width, int height, CPixelWriter &writer )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
Assert( m_ModifyTextureHandle > 0 );
|
|
|
|
ShaderAPITextureHandle_t hTexture = m_ModifyTextureHandle;
|
|
if ( !m_Textures.IsValidIndex( hTexture ) )
|
|
return false;
|
|
|
|
// Blow off mip levels if we don't support mipmapping
|
|
if ( !g_pHardwareConfig->SupportsMipmapping() && ( level > 0 ) )
|
|
return false;
|
|
|
|
// This test here just makes sure we don't try to download mipmap levels
|
|
// if we weren't able to create them in the first place
|
|
CTextureDx11 &tex = GetTexture( hTexture );
|
|
if ( level >= tex.m_NumLevels )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// May need to switch textures....
|
|
if ( tex.m_SwitchNeeded )
|
|
{
|
|
AdvanceCurrentTextureCopy( hTexture );
|
|
tex.m_SwitchNeeded = false;
|
|
}
|
|
|
|
bool ret = tex.Lock( tex.m_CurrentCopy, level, cubeFaceID, xOffset, yOffset,
|
|
width, height, false, writer );
|
|
if ( ret )
|
|
{
|
|
m_ModifyTextureLockedLevel = level;
|
|
m_ModifyTextureLockedFace = cubeFaceID;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void CShaderAPIDx11::TexUnlock()
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
if ( m_ModifyTextureLockedLevel >= 0 )
|
|
{
|
|
CTextureDx11 &tex = GetTexture( m_ModifyTextureHandle );
|
|
tex.Unlock( tex.m_CurrentCopy, m_ModifyTextureLockedLevel,
|
|
m_ModifyTextureLockedFace );
|
|
|
|
m_ModifyTextureLockedLevel = -1;
|
|
}
|
|
}
|
|
|
|
// These are bound to the texture, not the texture environment
|
|
void CShaderAPIDx11::TexMinFilter( ShaderTexFilterMode_t texFilterMode )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
ShaderAPITextureHandle_t hModifyTexture = m_ModifyTextureHandle;
|
|
if ( hModifyTexture == INVALID_SHADERAPI_TEXTURE_HANDLE )
|
|
return;
|
|
|
|
GetTexture( hModifyTexture ).SetMinFilter( texFilterMode );
|
|
}
|
|
|
|
void CShaderAPIDx11::TexMagFilter( ShaderTexFilterMode_t texFilterMode )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
ShaderAPITextureHandle_t hModifyTexture = m_ModifyTextureHandle;
|
|
if ( hModifyTexture == INVALID_SHADERAPI_TEXTURE_HANDLE )
|
|
return;
|
|
|
|
GetTexture( hModifyTexture ).SetMagFilter( texFilterMode );
|
|
}
|
|
|
|
void CShaderAPIDx11::TexWrap( ShaderTexCoordComponent_t coord, ShaderTexWrapMode_t wrapMode )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
ShaderAPITextureHandle_t hModifyTexture = m_ModifyTextureHandle;
|
|
if ( hModifyTexture == INVALID_SHADERAPI_TEXTURE_HANDLE )
|
|
return;
|
|
|
|
GetTexture( hModifyTexture ).SetWrap( coord, wrapMode );
|
|
}
|
|
|
|
ShaderAPITextureHandle_t CShaderAPIDx11::CreateTexture(
|
|
int width,
|
|
int height,
|
|
int depth,
|
|
ImageFormat dstImageFormat,
|
|
int numMipLevels,
|
|
int numCopies,
|
|
int flags,
|
|
const char *pDebugName,
|
|
const char *pTextureGroupName )
|
|
{
|
|
Log( "Create Texture with format: %s\n", ImageLoader::GetName( dstImageFormat ) );
|
|
ShaderAPITextureHandle_t handle;
|
|
CreateTextures( &handle, 1, width, height, depth, dstImageFormat, numMipLevels, numCopies, flags, pDebugName, pTextureGroupName );
|
|
return handle;
|
|
}
|
|
|
|
void CShaderAPIDx11::CreateTextureHandles( ShaderAPITextureHandle_t *handles, int count )
|
|
{
|
|
if ( count <= 0 )
|
|
return;
|
|
|
|
MEM_ALLOC_CREDIT();
|
|
|
|
int idxCreating = 0;
|
|
ShaderAPITextureHandle_t hTexture;
|
|
for ( hTexture = 0; hTexture < m_Textures.Count(); hTexture++ )
|
|
{
|
|
if ( !( m_Textures[hTexture].m_nFlags & CTextureDx11::IS_ALLOCATED ) )
|
|
{
|
|
handles[idxCreating++] = hTexture;
|
|
if ( idxCreating >= count )
|
|
return;
|
|
}
|
|
}
|
|
|
|
while ( idxCreating < count )
|
|
handles[idxCreating++] = m_Textures.AddToTail();
|
|
}
|
|
|
|
void CShaderAPIDx11::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 )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
// Create a set of texture handles
|
|
CreateTextureHandles( pHandles, count );
|
|
CTextureDx11 **arrTxp = new CTextureDx11 * [count];
|
|
|
|
Log( "Creating Textures with format: %s\n", ImageLoader::GetName( dstImageFormat ) );
|
|
|
|
for ( int idxFrame = 0; idxFrame < count; ++idxFrame )
|
|
{
|
|
arrTxp[idxFrame] = &GetTexture( pHandles[idxFrame] );
|
|
CTextureDx11 *pTexture = arrTxp[idxFrame];
|
|
pTexture->SetupTexture2D( width, height, depth, count, idxFrame, flags,
|
|
numCopies, numMipLevels, dstImageFormat );
|
|
pTexture->SetAnisotropicLevel( m_TexAnisotropy );
|
|
|
|
}
|
|
|
|
delete[] arrTxp;
|
|
}
|
|
|
|
CTextureDx11 &CShaderAPIDx11::GetTexture( ShaderAPITextureHandle_t handle )
|
|
{
|
|
return m_Textures[handle];
|
|
}
|
|
|
|
ShaderAPITextureHandle_t CShaderAPIDx11::CreateTextureHandle()
|
|
{
|
|
ShaderAPITextureHandle_t handle;
|
|
CreateTextureHandles( &handle, 1 );
|
|
return handle;
|
|
}
|
|
|
|
ShaderAPITextureHandle_t CShaderAPIDx11::CreateDepthTexture( ImageFormat renderFormat, int width, int height, const char *pDebugName, bool bTexture )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
ShaderAPITextureHandle_t i = CreateTextureHandle();
|
|
CTextureDx11 *pTexture = &GetTexture( i );
|
|
pTexture->SetupDepthTexture( renderFormat, width, height, pDebugName, bTexture );
|
|
|
|
return i;
|
|
}
|
|
|
|
void CShaderAPIDx11::DeleteTexture( ShaderAPITextureHandle_t textureHandle )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
if ( !TextureIsAllocated( textureHandle ) )
|
|
{
|
|
// already deallocated
|
|
return;
|
|
}
|
|
|
|
// Unbind it!
|
|
|
|
// Delete it baby
|
|
GetTexture( textureHandle ).Delete();
|
|
}
|
|
|
|
bool CShaderAPIDx11::IsTexture( ShaderAPITextureHandle_t textureHandle )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
if ( !TextureIsAllocated( textureHandle ) )
|
|
return false;
|
|
|
|
if ( GetTexture( textureHandle ).m_nFlags & CTextureDx11::IS_DEPTH_STENCIL )
|
|
{
|
|
return GetTexture( textureHandle ).GetDepthStencilView() != 0;
|
|
}
|
|
else if ( ( GetTexture( textureHandle ).m_NumCopies == 1 && GetTexture( textureHandle ).GetTexture() != 0 ) ||
|
|
( GetTexture( textureHandle ).m_NumCopies > 1 && GetTexture( textureHandle ).GetTexture( 0 ) != 0 ) )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void CShaderAPIDx11::SetAnisotropicLevel( int nAnisotropyLevel )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
// NOTE: This must be called before the rest of the code in this function so
|
|
// anisotropic can be set per-texture to force it on! This will also avoid
|
|
// a possible infinite loop that existed before.
|
|
g_pShaderUtil->NoteAnisotropicLevel( nAnisotropyLevel );
|
|
|
|
// Never set this to 1. In the case we want it set to 1, we will use this to override
|
|
// aniso per-texture, so set it to something reasonable
|
|
if ( nAnisotropyLevel > g_pHardwareConfig->Caps().m_nMaxAnisotropy || nAnisotropyLevel <= 1 )
|
|
{
|
|
// Set it to 1/4 the max but between 2-8
|
|
nAnisotropyLevel = max( 2, min( 8, ( g_pHardwareConfig->Caps().m_nMaxAnisotropy / 4 ) ) );
|
|
}
|
|
|
|
m_TexAnisotropy = nAnisotropyLevel;
|
|
|
|
// Set the D3D max aninsotropy state for all samplers
|
|
for ( ShaderAPITextureHandle_t handle = 0;
|
|
handle < m_Textures.Count();
|
|
handle++ )
|
|
{
|
|
CTextureDx11 &tex = GetTexture( handle );
|
|
tex.SetAnisotropicLevel( m_TexAnisotropy );
|
|
}
|
|
}
|
|
|
|
bool CShaderAPIDx11::IsTextureResident( ShaderAPITextureHandle_t textureHandle )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// stuff that isn't to be used from within a shader
|
|
void CShaderAPIDx11::ClearBuffersObeyStencil(bool bClearColor, bool bClearDepth)
|
|
{
|
|
ClearBuffersObeyStencilEx(bClearColor, bClearColor, bClearDepth);
|
|
}
|
|
|
|
// stuff that isn't to be used from within a shader
|
|
void CShaderAPIDx11::ClearBuffersObeyStencilEx( bool bClearColor, bool bClearAlpha, bool bClearDepth )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
if ( !bClearColor && !bClearDepth )
|
|
return;
|
|
|
|
FlushBufferedPrimitives();
|
|
|
|
ShaderUtil()->DrawClearBufferQuad( m_DynamicState.m_ClearColor[0] * 255,
|
|
m_DynamicState.m_ClearColor[1] * 255,
|
|
m_DynamicState.m_ClearColor[2] * 255,
|
|
m_DynamicState.m_ClearColor[3] * 255,
|
|
bClearColor, bClearAlpha, bClearDepth );
|
|
|
|
FlushBufferedPrimitives();
|
|
}
|
|
|
|
void CShaderAPIDx11::PerformFullScreenStencilOperation( void )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::ReadPixels( int x, int y, int width, int height, unsigned char *data, ImageFormat dstFormat )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::ReadPixels( Rect_t *pSrcRect, Rect_t *pDstRect, unsigned char *data, ImageFormat dstFormat, int nDstStride )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::FlushHardware()
|
|
{
|
|
}
|
|
|
|
// Set the number of bone weights
|
|
void CShaderAPIDx11::SetNumBoneWeights( int numBones )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
if ( m_ShaderState.bone.m_NumBones != numBones )
|
|
{
|
|
FlushBufferedPrimitives();
|
|
m_ShaderState.bone.m_NumBones = numBones;
|
|
m_ShaderState.bone.m_bBonesChanged = true;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Selection mode methods
|
|
//-----------------------------------------------------------------------------
|
|
int CShaderAPIDx11::SelectionMode( bool selectionMode )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
int numHits = m_NumHits;
|
|
if ( m_InSelectionMode )
|
|
{
|
|
WriteHitRecord();
|
|
}
|
|
m_InSelectionMode = selectionMode;
|
|
m_pCurrSelectionRecord = m_pSelectionBuffer;
|
|
m_NumHits = 0;
|
|
return numHits;
|
|
}
|
|
|
|
bool CShaderAPIDx11::IsInSelectionMode() const
|
|
{
|
|
return m_InSelectionMode;
|
|
}
|
|
|
|
void CShaderAPIDx11::SelectionBuffer( unsigned int *pBuffer, int size )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
Assert( !m_InSelectionMode );
|
|
Assert( pBuffer && size );
|
|
m_pSelectionBufferEnd = pBuffer + size;
|
|
m_pSelectionBuffer = pBuffer;
|
|
m_pCurrSelectionRecord = pBuffer;
|
|
}
|
|
|
|
void CShaderAPIDx11::ClearSelectionNames()
|
|
{
|
|
LOCK_SHADERAPI();
|
|
if ( m_InSelectionMode )
|
|
{
|
|
WriteHitRecord();
|
|
}
|
|
m_SelectionNames.Clear();
|
|
}
|
|
|
|
void CShaderAPIDx11::LoadSelectionName( int name )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
if ( m_InSelectionMode )
|
|
{
|
|
WriteHitRecord();
|
|
Assert( m_SelectionNames.Count() > 0 );
|
|
m_SelectionNames.Top() = name;
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::PushSelectionName( int name )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
if ( m_InSelectionMode )
|
|
{
|
|
WriteHitRecord();
|
|
m_SelectionNames.Push( name );
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::PopSelectionName()
|
|
{
|
|
LOCK_SHADERAPI();
|
|
if ( m_InSelectionMode )
|
|
{
|
|
WriteHitRecord();
|
|
m_SelectionNames.Pop();
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::WriteHitRecord()
|
|
{
|
|
FlushBufferedPrimitives();
|
|
|
|
if ( m_SelectionNames.Count() && ( m_SelectionMinZ != FLT_MAX ) )
|
|
{
|
|
Assert( m_pCurrSelectionRecord + m_SelectionNames.Count() + 3 < m_pSelectionBufferEnd );
|
|
*m_pCurrSelectionRecord++ = m_SelectionNames.Count();
|
|
*m_pCurrSelectionRecord++ = (int)( (double)m_SelectionMinZ * (double)0xFFFFFFFF );
|
|
*m_pCurrSelectionRecord++ = (int)( (double)m_SelectionMaxZ * (double)0xFFFFFFFF );
|
|
for ( int i = 0; i < m_SelectionNames.Count(); ++i )
|
|
{
|
|
*m_pCurrSelectionRecord++ = m_SelectionNames[i];
|
|
}
|
|
|
|
++m_NumHits;
|
|
}
|
|
|
|
m_SelectionMinZ = FLT_MAX;
|
|
m_SelectionMaxZ = FLT_MIN;
|
|
}
|
|
|
|
// We hit somefin in selection mode
|
|
void CShaderAPIDx11::RegisterSelectionHit( float minz, float maxz )
|
|
{
|
|
if ( minz < 0 )
|
|
minz = 0;
|
|
if ( maxz > 1 )
|
|
maxz = 1;
|
|
if ( m_SelectionMinZ > minz )
|
|
m_SelectionMinZ = minz;
|
|
if ( m_SelectionMaxZ < maxz )
|
|
m_SelectionMaxZ = maxz;
|
|
}
|
|
|
|
|
|
// Use this to get the mesh builder that allows us to modify vertex data
|
|
CMeshBuilder *CShaderAPIDx11::GetVertexModifyBuilder()
|
|
{
|
|
return &m_ModifyBuilder;
|
|
}
|
|
|
|
// Board-independent calls, here to unify how shaders set state
|
|
// Implementations should chain back to IShaderUtil->BindTexture(), etc.
|
|
|
|
void CShaderAPIDx11::CopyRenderTargetToScratchTexture(ShaderAPITextureHandle_t srcRt, ShaderAPITextureHandle_t dstTex, Rect_t* pSrcRect, Rect_t* pDstRect)
|
|
{
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// Allows locking and unlocking of very specific surface types. pOutBits and pOutPitch will not be touched if
|
|
// the lock fails.
|
|
//-------------------------------------------------------------------------
|
|
void CShaderAPIDx11::LockRect(void** pOutBits, int* pOutPitch, ShaderAPITextureHandle_t texHandle, int mipmap, int x, int y, int w, int h, bool bWrite, bool bRead)
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::UnlockRect(ShaderAPITextureHandle_t texHandle, int mipmap)
|
|
{
|
|
}
|
|
|
|
// Use this to begin and end the frame
|
|
void CShaderAPIDx11::BeginFrame()
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::EndFrame()
|
|
{
|
|
}
|
|
|
|
// returns the current time in seconds....
|
|
double CShaderAPIDx11::CurrentTime() const
|
|
{
|
|
return Sys_FloatTime();
|
|
}
|
|
|
|
void CShaderAPIDx11::ForceHardwareSync( void )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::SetClipPlane( int index, const float *pPlane )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::EnableClipPlane( int index, bool bEnable )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::SetFastClipPlane( const float *pPlane )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::EnableFastClip( bool bEnable )
|
|
{
|
|
}
|
|
|
|
int CShaderAPIDx11::GetCurrentNumBones( void ) const
|
|
{
|
|
return m_ShaderState.bone.m_NumBones;
|
|
}
|
|
|
|
// Is hardware morphing enabled?
|
|
bool CShaderAPIDx11::IsHWMorphingEnabled() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
int CShaderAPIDx11::MapLightComboToPSLightCombo( int nLightCombo ) const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void CShaderAPIDx11::RecordString( const char *pStr )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::DestroyVertexBuffers( bool bExitingLevel )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
MeshMgr()->DestroyVertexBuffers();
|
|
// After a map is shut down, we switch to using smaller dynamic VBs
|
|
// (VGUI shouldn't need much), so that we have more memory free during map loading
|
|
m_nDynamicVBSize = bExitingLevel ? DYNAMIC_VERTEX_BUFFER_MEMORY_SMALL : DYNAMIC_VERTEX_BUFFER_MEMORY;
|
|
}
|
|
|
|
int CShaderAPIDx11::GetCurrentDynamicVBSize( void )
|
|
{
|
|
return m_nDynamicVBSize;
|
|
}
|
|
|
|
void CShaderAPIDx11::EvictManagedResources()
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::ReleaseShaderObjects()
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::RestoreShaderObjects()
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::SyncToken( const char *pToken )
|
|
{
|
|
}
|
|
|
|
// Rendering parameters
|
|
|
|
void CShaderAPIDx11::SetFloatRenderingParameter( int parm_number, float value )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
if ( parm_number < ARRAYSIZE( FloatRenderingParameters ) )
|
|
FloatRenderingParameters[parm_number] = value;
|
|
}
|
|
|
|
void CShaderAPIDx11::SetIntRenderingParameter( int parm_number, int value )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
if ( parm_number < ARRAYSIZE( IntRenderingParameters ) )
|
|
IntRenderingParameters[parm_number] = value;
|
|
}
|
|
|
|
void CShaderAPIDx11::SetVectorRenderingParameter( int parm_number, Vector const &value )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
if ( parm_number < ARRAYSIZE( VectorRenderingParameters ) )
|
|
VectorRenderingParameters[parm_number] = value;
|
|
}
|
|
|
|
float CShaderAPIDx11::GetFloatRenderingParameter( int parm_number ) const
|
|
{
|
|
LOCK_SHADERAPI();
|
|
if ( parm_number < ARRAYSIZE( FloatRenderingParameters ) )
|
|
return FloatRenderingParameters[parm_number];
|
|
else
|
|
return 0.0;
|
|
}
|
|
|
|
int CShaderAPIDx11::GetIntRenderingParameter( int parm_number ) const
|
|
{
|
|
LOCK_SHADERAPI();
|
|
if ( parm_number < ARRAYSIZE( IntRenderingParameters ) )
|
|
return IntRenderingParameters[parm_number];
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
Vector CShaderAPIDx11::GetVectorRenderingParameter( int parm_number ) const
|
|
{
|
|
LOCK_SHADERAPI();
|
|
if ( parm_number < ARRAYSIZE( VectorRenderingParameters ) )
|
|
return VectorRenderingParameters[parm_number];
|
|
else
|
|
return Vector( 0, 0, 0 );
|
|
}
|
|
|
|
// Stencils
|
|
|
|
void CShaderAPIDx11::SetStencilEnable( bool onoff )
|
|
{
|
|
//m_TargetState.shadow.depthStencil.StencilEnable = onoff;
|
|
}
|
|
|
|
void CShaderAPIDx11::SetStencilFailOperation( StencilOperation_t op )
|
|
{
|
|
//m_TargetState.shadow.depthStencil.FrontFace.StencilFailOp = (D3D11_STENCIL_OP)op;
|
|
}
|
|
|
|
void CShaderAPIDx11::SetStencilZFailOperation( StencilOperation_t op )
|
|
{
|
|
//m_TargetState.shadow.depthStencil.FrontFace.StencilDepthFailOp = (D3D11_STENCIL_OP)op;
|
|
}
|
|
|
|
void CShaderAPIDx11::SetStencilPassOperation( StencilOperation_t op )
|
|
{
|
|
//m_TargetState.shadow.depthStencil.FrontFace.StencilPassOp = (D3D11_STENCIL_OP)op;
|
|
}
|
|
|
|
void CShaderAPIDx11::SetStencilCompareFunction( StencilComparisonFunction_t cmpfn )
|
|
{
|
|
//m_TargetState.shadow.depthStencil.FrontFace.StencilFunc = (D3D11_COMPARISON_FUNC)cmpfn;
|
|
}
|
|
|
|
void CShaderAPIDx11::SetStencilReferenceValue( int ref )
|
|
{
|
|
//m_TargetState.shadow.depthStencil.StencilRef = ref;
|
|
}
|
|
|
|
void CShaderAPIDx11::SetStencilTestMask( uint32 msk )
|
|
{
|
|
//m_TargetState.shadow.depthStencil.StencilReadMask = msk;
|
|
}
|
|
|
|
void CShaderAPIDx11::SetStencilWriteMask( uint32 msk )
|
|
{
|
|
//m_TargetState.shadow.depthStencil.StencilWriteMask = msk;
|
|
}
|
|
|
|
int CShaderAPIDx11::CompareSnapshots( StateSnapshot_t snapshot0, StateSnapshot_t snapshot1 )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
const StatesDx11::ShadowState *shadow0 = g_pShaderShadowDx11->GetShadowState( snapshot0 );
|
|
const StatesDx11::ShadowState *shadow1 = g_pShaderShadowDx11->GetShadowState( snapshot1 );
|
|
|
|
if ( shadow0 == shadow1 )
|
|
return 0;
|
|
return shadow0 > shadow1 ? -1 : 1;
|
|
}
|
|
|
|
IDirect3DBaseTexture *CShaderAPIDx11::GetD3DTexture( ShaderAPITextureHandle_t handle )
|
|
{
|
|
if ( handle == INVALID_SHADERAPI_TEXTURE_HANDLE )
|
|
return NULL;
|
|
|
|
CTextureDx11 &tex = GetTexture( handle );
|
|
if ( tex.m_NumCopies == 1 )
|
|
return tex.GetTexture();
|
|
else
|
|
return tex.GetTexture( tex.m_CurrentCopy );
|
|
}
|
|
|
|
bool CShaderAPIDx11::SetMode( void *hwnd, int nAdapter, const ShaderDeviceInfo_t &mode )
|
|
{
|
|
return g_pShaderDeviceMgr->SetMode( hwnd, nAdapter, mode ) != NULL;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// Occlusion queries
|
|
//--------------------------------------------------------------------
|
|
|
|
ShaderAPIOcclusionQuery_t CShaderAPIDx11::CreateOcclusionQueryObject( void )
|
|
{
|
|
return g_pShaderDeviceDx11->CreateOcclusionQuery();
|
|
}
|
|
|
|
void CShaderAPIDx11::DestroyOcclusionQueryObject( ShaderAPIOcclusionQuery_t handle )
|
|
{
|
|
g_pShaderDeviceDx11->DestroyOcclusionQuery( handle );
|
|
}
|
|
|
|
void CShaderAPIDx11::BeginOcclusionQueryDrawing( ShaderAPIOcclusionQuery_t handle )
|
|
{
|
|
if ( handle != INVALID_SHADERAPI_OCCLUSION_QUERY_HANDLE )
|
|
{
|
|
D3D11DeviceContext()->Begin( (ID3D11Query *)handle );
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::EndOcclusionQueryDrawing( ShaderAPIOcclusionQuery_t handle )
|
|
{
|
|
if ( handle != INVALID_SHADERAPI_OCCLUSION_QUERY_HANDLE )
|
|
{
|
|
D3D11DeviceContext()->End( (ID3D11Query *)handle );
|
|
}
|
|
}
|
|
|
|
int CShaderAPIDx11::OcclusionQuery_GetNumPixelsRendered( ShaderAPIOcclusionQuery_t handle, bool bFlush )
|
|
{
|
|
if ( handle == INVALID_SHADERAPI_OCCLUSION_QUERY_HANDLE )
|
|
{
|
|
return OCCLUSION_QUERY_RESULT_ERROR;
|
|
}
|
|
|
|
uint64 nPixels;
|
|
HRESULT hr = D3D11DeviceContext()->GetData( (ID3D11Query *)handle, &nPixels, sizeof( uint64 ),
|
|
bFlush ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return OCCLUSION_QUERY_RESULT_ERROR;
|
|
}
|
|
|
|
if ( hr == S_FALSE ) // not ready yet
|
|
{
|
|
return OCCLUSION_QUERY_RESULT_PENDING;
|
|
}
|
|
|
|
return (int)nPixels;
|
|
}
|
|
|
|
void CShaderAPIDx11::BindStandardTexture( Sampler_t stage, StandardTextureId_t id )
|
|
{
|
|
ShaderUtil()->BindStandardTexture( stage, id );
|
|
}
|
|
|
|
void CShaderAPIDx11::BindVertexTexture( VertexTextureSampler_t stage, ShaderAPITextureHandle_t hTexture )
|
|
{
|
|
CTextureDx11 *pTex = &GetTexture( hTexture );
|
|
|
|
if ( !pTex )
|
|
return;
|
|
|
|
StatesDx11::DynamicState &dynamic = m_DynamicState;
|
|
|
|
ID3D11ShaderResourceView *pView = pTex->GetView();
|
|
ID3D11SamplerState *pSampler = pTex->GetSamplerState();
|
|
|
|
if ( pView != dynamic.m_ppVertexTextures[stage] )
|
|
{
|
|
dynamic.m_ppVertexTextures[stage] = pView;
|
|
SetStateFlag( STATE_CHANGED_VERTEXTEXTURES );
|
|
}
|
|
|
|
if ( pSampler != dynamic.m_ppVertexSamplers[stage] )
|
|
{
|
|
dynamic.m_ppVertexSamplers[stage] = pSampler;
|
|
SetStateFlag( STATE_CHANGED_VERTEXSAMPLERS );
|
|
}
|
|
|
|
if ( stage > dynamic.m_MaxVSSampler )
|
|
{
|
|
dynamic.m_MaxVSSampler = stage;
|
|
if ( dynamic.m_MaxVSSampler > dynamic.m_PrevMaxVSSampler )
|
|
{
|
|
SetStateFlag( STATE_CHANGED_VERTEXSAMPLERS | STATE_CHANGED_VERTEXTEXTURES );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::SetFlexWeights( int nFirstWeight, int nCount, const MorphWeight_t *pWeights )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
//m_ShaderState.morph.m_nFirstWeight = nFirstWeight;
|
|
//m_ShaderState.morph.m_nCount = nCount;
|
|
//int numLoaded = nFirstWeight + nCount;
|
|
//if ( numLoaded > m_ShaderState.morph.m_nMaxWeightLoaded )
|
|
//{
|
|
// m_ShaderState.morph.m_nMaxWeightLoaded = numLoaded;
|
|
//}
|
|
//memcpy( m_ShaderState.morph.m_pWeights + nFirstWeight, pWeights, sizeof( MorphWeight_t ) * nCount );
|
|
//m_ShaderState.morph.m_bMorphChanged = true;
|
|
}
|
|
|
|
void CShaderAPIDx11::SetToneMappingScaleLinear( const Vector &scale )
|
|
{
|
|
// Flush buffered primitives before changing the tone map scalar!
|
|
FlushBufferedPrimitives();
|
|
|
|
Vector4D old = m_ShaderState.m_ToneMappingScale;
|
|
|
|
Vector scale_to_use = scale;
|
|
m_ShaderState.m_ToneMappingScale.AsVector3D() = scale_to_use;
|
|
|
|
bool mode_uses_srgb = false;
|
|
|
|
switch ( HardwareConfig()->GetHDRType() )
|
|
{
|
|
case HDR_TYPE_NONE:
|
|
m_ShaderState.m_ToneMappingScale.x = 1.0; // output scale
|
|
m_ShaderState.m_ToneMappingScale.z = 1.0; // reflection map scale
|
|
break;
|
|
|
|
case HDR_TYPE_FLOAT:
|
|
m_ShaderState.m_ToneMappingScale.x = scale_to_use.x; // output scale
|
|
m_ShaderState.m_ToneMappingScale.z = 1.0; // reflection map scale
|
|
break;
|
|
|
|
case HDR_TYPE_INTEGER:
|
|
mode_uses_srgb = true;
|
|
m_ShaderState.m_ToneMappingScale.x = scale_to_use.x; // output scale
|
|
m_ShaderState.m_ToneMappingScale.z = 16.0; // reflection map scale
|
|
break;
|
|
}
|
|
|
|
m_ShaderState.m_ToneMappingScale.y = GetLightMapScaleFactor(); // light map scale
|
|
|
|
// w component gets gamma scale
|
|
m_ShaderState.m_ToneMappingScale.w = LinearToGammaFullRange( m_ShaderState.m_ToneMappingScale.x );
|
|
|
|
if ( old != m_ShaderState.m_ToneMappingScale )
|
|
{
|
|
m_ShaderState.m_bToneMappingScaleChanged = true;
|
|
}
|
|
}
|
|
|
|
void CShaderAPIDx11::BindStandardVertexTexture( VertexTextureSampler_t stage, StandardTextureId_t id )
|
|
{
|
|
ShaderUtil()->BindStandardVertexTexture( stage, id );
|
|
}
|
|
|
|
template<class T> FORCEINLINE T GetData( uint8 const *pData )
|
|
{
|
|
return *( reinterpret_cast<T const *>( pData ) );
|
|
}
|
|
|
|
void CShaderAPIDx11::ExecuteCommandBuffer( uint8 *pCmdBuf )
|
|
{
|
|
uint8 *pReturnStack[20];
|
|
uint8 **pSP = &pReturnStack[ARRAYSIZE( pReturnStack )];
|
|
uint8 *pLastCmd;
|
|
for ( ;;)
|
|
{
|
|
uint8 *pCmd = pCmdBuf;
|
|
int nCmd = GetData<int>( pCmdBuf );
|
|
switch ( nCmd )
|
|
{
|
|
case CBCMD_END:
|
|
{
|
|
if ( pSP == &pReturnStack[ARRAYSIZE( pReturnStack )] )
|
|
return;
|
|
else
|
|
{
|
|
// pop pc
|
|
pCmdBuf = *( pSP++ );
|
|
break;
|
|
}
|
|
}
|
|
|
|
case CBCMD_JUMP:
|
|
pCmdBuf = GetData<uint8 *>( pCmdBuf + sizeof( int ) );
|
|
break;
|
|
|
|
case CBCMD_JSR:
|
|
{
|
|
Assert( pSP > &( pReturnStack[0] ) );
|
|
ExecuteCommandBuffer( GetData<uint8 *>( pCmdBuf + sizeof( int ) ) );
|
|
pCmdBuf = pCmdBuf + sizeof( int ) + sizeof( uint8 * );
|
|
break;
|
|
}
|
|
case CBCMD_BIND_STANDARD_TEXTURE:
|
|
{
|
|
int nSampler = GetData<int>( pCmdBuf + sizeof( int ) );
|
|
int nTextureID = GetData<int>( pCmdBuf + 2 * sizeof( int ) );
|
|
pCmdBuf += 3 * sizeof( int );
|
|
ShaderUtil()->BindStandardTexture( (Sampler_t)nSampler, (StandardTextureId_t)nTextureID );
|
|
break;
|
|
}
|
|
|
|
case CBCMD_BIND_SHADERAPI_TEXTURE_HANDLE:
|
|
{
|
|
int nSampler = GetData<int>( pCmdBuf + sizeof( int ) );
|
|
ShaderAPITextureHandle_t hTexture = GetData<ShaderAPITextureHandle_t>( pCmdBuf + 2 * sizeof( int ) );
|
|
Assert( hTexture != INVALID_SHADERAPI_TEXTURE_HANDLE );
|
|
pCmdBuf += 2 * sizeof( int ) + sizeof( ShaderAPITextureHandle_t );
|
|
BindTexture( (Sampler_t)nSampler, hTexture );
|
|
break;
|
|
}
|
|
|
|
case CBCMD_SET_PSHINDEX:
|
|
{
|
|
int nIdx = GetData<int>( pCmdBuf + sizeof( int ) );
|
|
SetPixelShaderIndex( nIdx );
|
|
pCmdBuf += 2 * sizeof( int );
|
|
break;
|
|
}
|
|
|
|
case CBCMD_SET_VSHINDEX:
|
|
{
|
|
int nIdx = GetData<int>( pCmdBuf + sizeof( int ) );
|
|
SetVertexShaderIndex( nIdx );
|
|
pCmdBuf += 2 * sizeof( int );
|
|
break;
|
|
}
|
|
#ifndef NDEBUG
|
|
default:
|
|
{
|
|
Assert( 0 );
|
|
}
|
|
#endif
|
|
}
|
|
pLastCmd = pCmd;
|
|
}
|
|
}
|
|
|
|
bool CShaderAPIDx11::ShouldWriteDepthToDestAlpha() const
|
|
{
|
|
return IsPC() && g_pHardwareConfig->SupportsPixelShaders_2_b() &&
|
|
( m_ShaderState.fog.m_FogMode != MATERIAL_FOG_LINEAR_BELOW_FOG_Z ) &&
|
|
( GetIntRenderingParameter( INT_RENDERPARM_WRITE_DEPTH_TO_DESTALPHA ) != 0 );
|
|
}
|
|
|
|
void CShaderAPIDx11::ClearVertexAndPixelShaderRefCounts()
|
|
{
|
|
LOCK_SHADERAPI();
|
|
ShaderManager()->ClearVertexAndPixelShaderRefCounts();
|
|
}
|
|
|
|
void CShaderAPIDx11::PurgeUnusedVertexAndPixelShaders()
|
|
{
|
|
LOCK_SHADERAPI();
|
|
ShaderManager()->PurgeUnusedVertexAndPixelShaders();
|
|
}
|
|
|
|
void CShaderAPIDx11::SetFlashlightState( const FlashlightState_t &state, const VMatrix &worldToTexture )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
SetFlashlightStateEx( state, worldToTexture, NULL );
|
|
}
|
|
|
|
void CShaderAPIDx11::SetFlashlightStateEx( const FlashlightState_t &state, const VMatrix &worldToTexture, ITexture *pFlashlightDepthTexture )
|
|
{
|
|
LOCK_SHADERAPI();
|
|
|
|
bool bFlushed = false;
|
|
if ( memcmp( &state, &m_FlashlightState, sizeof( FlashlightState_t ) ) )
|
|
{
|
|
FlushBufferedPrimitives();
|
|
bFlushed = true;
|
|
|
|
m_FlashlightState = state;
|
|
m_bFlashlightStateChanged = true;
|
|
}
|
|
if ( worldToTexture != m_FlashlightWorldToTexture )
|
|
{
|
|
if ( !bFlushed )
|
|
{
|
|
FlushBufferedPrimitives();
|
|
bFlushed = true;
|
|
}
|
|
m_FlashlightWorldToTexture = worldToTexture;
|
|
m_bFlashlightStateChanged = true;
|
|
}
|
|
if ( pFlashlightDepthTexture != m_pFlashlightDepthTexture )
|
|
{
|
|
if ( !bFlushed )
|
|
{
|
|
FlushBufferedPrimitives();
|
|
bFlushed = true;
|
|
}
|
|
m_pFlashlightDepthTexture = pFlashlightDepthTexture;
|
|
m_bFlashlightStateChanged = true;
|
|
}
|
|
}
|
|
|
|
const FlashlightState_t &CShaderAPIDx11::GetFlashlightState( VMatrix &worldToTexture ) const
|
|
{
|
|
worldToTexture = m_FlashlightWorldToTexture;
|
|
return m_FlashlightState;
|
|
}
|
|
|
|
const FlashlightState_t &CShaderAPIDx11::GetFlashlightStateEx( VMatrix &worldToTexture, ITexture **pFlashlightDepthTexture ) const
|
|
{
|
|
worldToTexture = m_FlashlightWorldToTexture;
|
|
*pFlashlightDepthTexture = m_pFlashlightDepthTexture;
|
|
return m_FlashlightState;
|
|
}
|
|
|
|
#define MAX_LIGHTS 4
|
|
|
|
void CShaderAPIDx11::GetDX9LightState( LightState_t *state ) const
|
|
{
|
|
// hack . . do this a cheaper way.
|
|
if ( m_ShaderState.light.m_AmbientLightCube[0][0] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[0][1] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[0][2] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[1][0] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[1][1] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[1][2] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[2][0] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[2][1] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[2][2] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[3][0] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[3][1] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[3][2] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[4][0] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[4][1] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[4][2] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[5][0] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[5][1] == 0.0f &&
|
|
m_ShaderState.light.m_AmbientLightCube[5][2] == 0.0f )
|
|
{
|
|
state->m_bAmbientLight = false;
|
|
}
|
|
else
|
|
{
|
|
state->m_bAmbientLight = true;
|
|
}
|
|
|
|
Assert( m_pMesh );
|
|
Assert( m_ShaderState.light.m_NumLights <= 4 );
|
|
|
|
if ( g_pHardwareConfig->SupportsPixelShaders_2_b() )
|
|
{
|
|
Assert( m_ShaderState.light.m_NumLights <= MAX_LIGHTS ); // 2b hardware gets four lights
|
|
}
|
|
else
|
|
{
|
|
Assert( m_ShaderState.light.m_NumLights <= ( MAX_LIGHTS - 2 ) ); // 2.0 hardware gets two less
|
|
}
|
|
|
|
state->m_nNumLights = m_ShaderState.light.m_NumLights;
|
|
state->m_bStaticLightVertex = m_pMesh->HasColorMesh();
|
|
state->m_bStaticLightTexel = false; // For now
|
|
}
|
|
|
|
|
|
void CShaderAPIDx11::CopyRenderTargetToTextureEx( ShaderAPITextureHandle_t textureHandle, int nRenderTargetID, Rect_t *pSrcRect, Rect_t *pDstRect )
|
|
{
|
|
// don't use this
|
|
return;
|
|
|
|
// LOCK_SHADERAPI();
|
|
//VPROF_BUDGET( "CShaderAPIDx11::CopyRenderTargetToTexture", "Refraction overhead" );
|
|
|
|
/*if ( !TextureIsAllocated( textureHandle ) )
|
|
return;
|
|
|
|
CTextureDx11 *pTexture = &GetTexture( textureHandle );
|
|
Assert( pTexture );
|
|
ID3D11Resource *pD3DTexture = pTexture->GetTexture();
|
|
Assert( pD3DTexture );
|
|
|
|
ITexture *rt = g_pShaderUtil->GetRenderTargetEx( nRenderTargetID );
|
|
|
|
CTextureDx11 *pTextureRT;
|
|
if ( rt == NULL )
|
|
{
|
|
pTextureRT = &GetTexture( 0 ); // copy back buffer
|
|
}
|
|
else
|
|
{
|
|
ITextureInternal* texInt = static_cast<ITextureInternal*>(rt);
|
|
ShaderAPITextureHandle_t texHandle = texInt->GetTextureHandle( 0 );
|
|
pTextureRT = &GetTexture( texHandle );
|
|
}
|
|
|
|
ID3D11Resource *pD3DTextureRT = pTextureRT->GetTexture();
|
|
Assert( pD3DTextureRT );*/
|
|
|
|
// need to draw a quad with the texture and downscale it
|
|
}
|
|
|
|
void CShaderAPIDx11::CopyTextureToRenderTargetEx(int nRenderTargetID, ShaderAPITextureHandle_t textureHandle, Rect_t* pSrcRect, Rect_t* pDstRect)
|
|
{
|
|
// don't use this
|
|
return;
|
|
|
|
// LOCK_SHADERAPI();
|
|
//VPROF_BUDGET( "CShaderAPIDx11::CopyRenderTargetToTexture", "Refraction overhead" );
|
|
|
|
/*if (!TextureIsAllocated(textureHandle))
|
|
return;
|
|
|
|
CTextureDx11* pTexture = &GetTexture(textureHandle);
|
|
Assert(pTexture);
|
|
ID3D11Resource* pD3DTexture = pTexture->GetTexture();
|
|
Assert(pD3DTexture);
|
|
|
|
ITexture* rt = g_pShaderUtil->GetRenderTargetEx(nRenderTargetID);
|
|
|
|
CTextureDx11* pTextureRT;
|
|
if (rt == NULL)
|
|
{
|
|
pTextureRT = &GetTexture(0); // copy back buffer
|
|
}
|
|
else
|
|
{
|
|
ITextureInternal* texInt = static_cast<ITextureInternal*>(rt);
|
|
ShaderAPITextureHandle_t texHandle = texInt->GetTextureHandle(0);
|
|
pTextureRT = &GetTexture(texHandle);
|
|
}
|
|
|
|
ID3D11Resource* pD3DTextureRT = pTextureRT->GetTexture();
|
|
Assert(pD3DTextureRT);*/
|
|
|
|
// need to draw a quad with the texture and downscale it
|
|
}
|
|
|
|
//------------------------------------------------------------------------------------
|
|
// UNUSED/UNSUPPORTED FUNCTIONS!!!
|
|
//------------------------------------------------------------------------------------
|
|
|
|
// Lightmap texture binding
|
|
void CShaderAPIDx11::BindLightmap( TextureStage_t stage )
|
|
{
|
|
// Unused
|
|
}
|
|
|
|
void CShaderAPIDx11::BindBumpLightmap( TextureStage_t stage )
|
|
{
|
|
// Unused
|
|
}
|
|
|
|
void CShaderAPIDx11::BindFullbrightLightmap( TextureStage_t stage )
|
|
{
|
|
// Unused
|
|
}
|
|
|
|
void CShaderAPIDx11::BindWhite( TextureStage_t stage )
|
|
{
|
|
// Unused
|
|
}
|
|
|
|
void CShaderAPIDx11::BindBlack( TextureStage_t stage )
|
|
{
|
|
// Unused
|
|
}
|
|
|
|
void CShaderAPIDx11::BindGrey( TextureStage_t stage )
|
|
{
|
|
// Unused
|
|
}
|
|
|
|
void CShaderAPIDx11::SetTextureTransformDimension( TextureStage_t textureStage, int dimension, bool projected )
|
|
{
|
|
//Warning( "Unsupported CShaderAPIDx11::SetTextureTransformDimension() called!\n" );
|
|
}
|
|
|
|
void CShaderAPIDx11::SetBumpEnvMatrix( TextureStage_t textureStage, float m00, float m01, float m10, float m11 )
|
|
{
|
|
//Warning( "Unsupported CShaderAPIDx11::SetBumpEnvMatrix() called!\n" );
|
|
}
|
|
|
|
void CShaderAPIDx11::SetAmbientLight( float r, float g, float b )
|
|
{
|
|
//Warning( "Unsupported CShaderAPIDx11::SetAmbientLight() called!\n" );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Methods related to state objects
|
|
//-----------------------------------------------------------------------------
|
|
void CShaderAPIDx11::SetRasterState( const ShaderRasterState_t &state )
|
|
{
|
|
//Warning( "Unsupported CShaderAPIDx11::SetRasterState() called!\n" );
|
|
}
|
|
|
|
// The shade mode
|
|
void CShaderAPIDx11::ShadeMode( ShaderShadeMode_t mode )
|
|
{
|
|
//Warning( "Unsupported CShaderAPIDx11::ShadeMode() called!\n" );
|
|
}
|
|
|
|
void CShaderAPIDx11::TexSetPriority( int priority )
|
|
{
|
|
//Warning( "Unsupported CShaderAPIDx11::SetTexPriority() called!\n" );
|
|
}
|
|
|
|
// Sets the constant register for vertex and pixel shaders
|
|
void CShaderAPIDx11::SetVertexShaderConstant( int var, float const *pVec, int numConst, bool bForce )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::SetPixelShaderConstant( int var, float const *pVec, int numConst, bool bForce )
|
|
{
|
|
}
|
|
|
|
void CShaderAPIDx11::SetPixelShaderFogParams( int psReg )
|
|
{
|
|
}
|
|
|
|
bool CShaderAPIDx11::InFlashlightMode() const
|
|
{
|
|
return ShaderUtil()->InFlashlightMode();
|
|
}
|
|
|
|
bool CShaderAPIDx11::InEditorMode() const
|
|
{
|
|
return ShaderUtil()->InEditorMode();
|
|
}
|
|
|
|
void CShaderAPIDx11::InvalidateDelayedShaderConstants( void )
|
|
{
|
|
//Warning( "Unsupported CShaderAPIDx11::InvalidateDelayedShaderConstants() called!\n" );
|
|
}
|
|
|
|
//Set's the linear->gamma conversion textures to use for this hardware for both srgb writes enabled and disabled(identity)
|
|
void CShaderAPIDx11::SetLinearToGammaConversionTextures( ShaderAPITextureHandle_t hSRGBWriteEnabledTexture, ShaderAPITextureHandle_t hIdentityTexture )
|
|
{
|
|
//Warning( "Unsupported CShaderAPIDx11::SetLinearToGammaConversionTextures() called!\n" );
|
|
}
|
|
|
|
// Special system flat normal map binding.
|
|
void CShaderAPIDx11::BindFlatNormalMap( TextureStage_t stage )
|
|
{
|
|
// Unused
|
|
}
|
|
|
|
void CShaderAPIDx11::BindNormalizationCubeMap( TextureStage_t stage )
|
|
{
|
|
// Unused
|
|
}
|
|
|
|
void CShaderAPIDx11::BindSignedNormalizationCubeMap( TextureStage_t stage )
|
|
{
|
|
// Unused
|
|
}
|
|
|
|
void CShaderAPIDx11::BindFBTexture( TextureStage_t stage, int textureIndex )
|
|
{
|
|
// Unused
|
|
}
|
|
|
|
// Render state for the ambient light cube (vertex shaders)
|
|
void CShaderAPIDx11::SetVertexShaderStateAmbientLightCube()
|
|
{
|
|
//Warning( "Unsupported CShaderAPIDx11::SetVertexShaderStateAmbientLightCube() called!\n" );
|
|
} |