1109 lines
30 KiB
C++
1109 lines
30 KiB
C++
#include "stdafx.h"
|
|
|
|
#ifdef _XBOX
|
|
#include <XGraphics.h>
|
|
#include <XGMath.h>
|
|
BOOL gRestoreConstantMode = FALSE;
|
|
|
|
template <class T>
|
|
int GetRefCount(T* t){
|
|
t->AddRef();
|
|
return t->Release();
|
|
}
|
|
|
|
#endif
|
|
|
|
#include "RCKShaderDX8.h"
|
|
#include "ShaderManagerDX8.h"
|
|
|
|
#include "..\..\..\Render Engines\CKDX8Rasterizer\CKDX8Rasterizer.h"
|
|
|
|
#include <d3dx8.h>
|
|
#include <d3dx8effect.h>
|
|
|
|
|
|
typedef D3DXHANDLE *LPD3DXHANDLE;
|
|
typedef IUnknown ID3DXEffectPool;
|
|
|
|
typedef DWORD D3DXPARAMETER_CLASS;
|
|
typedef D3DXPARAMETERTYPE D3DXPARAMETER_TYPE;
|
|
#define DX8_EFFECT
|
|
|
|
IDirect3DDevice8* DeviceFromRC(CKRenderContext* rc);
|
|
|
|
void FourCC2XString(XString& xs,DWORD fcc){
|
|
char *tmp = (char*)&fcc;
|
|
xs = "";
|
|
tmp[0] ? xs << tmp[0] : 0;
|
|
tmp[1] ? xs << tmp[1] : 0;
|
|
tmp[2] ? xs << tmp[2] : 0;
|
|
tmp[3] ? xs << tmp[3] : 0;
|
|
};
|
|
|
|
DWORD XString2FourCC(XString& xs){
|
|
DWORD d = 0;
|
|
char*temp = (char*)&d;
|
|
int count = XMin((const int)xs.Length(),4);
|
|
for(int i=0;i<count;i++){
|
|
temp[i] = xs[i];
|
|
}
|
|
return d;
|
|
}
|
|
|
|
|
|
inline D3DXHANDLE GetD3DXHandle(CKParameterLocal* param)
|
|
{
|
|
return (D3DXHANDLE)param->GetAppData();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
RCKShaderDX8::RCKShaderDX8(ShaderManagerDX8 *man) :
|
|
m_ShaderManager(man),
|
|
m_CurrTechnique(NULL),
|
|
m_TechGuid()
|
|
{
|
|
//--- Initialize the DXEffect for all render context
|
|
const int rcCount = man->m_rcList.Size();
|
|
m_DXEffect.Resize(rcCount);
|
|
// m_DXTechnique.Resize(rcCount);
|
|
|
|
m_DXEffect.Fill(NULL);
|
|
// m_DXTechnique.Fill(NULL);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
RCKShaderDX8::~RCKShaderDX8()
|
|
{
|
|
//--- Release all DXEffects for allrender context
|
|
const int rcCount = m_DXEffect.Size();
|
|
for( int rcIndex=0 ; rcIndex<rcCount ; ++rcIndex ){
|
|
|
|
#ifdef _XBOX
|
|
// Release Techniques
|
|
for(int i=0;i<m_Techniques.Size();i++){
|
|
((ID3DXTechnique*)m_Techniques[i].handle[rcIndex])->Release();
|
|
m_Techniques[i].handle[rcIndex] = NULL;
|
|
}
|
|
#endif
|
|
|
|
ReleaseDxEffect(rcIndex);
|
|
}
|
|
m_DXEffect.Clear();
|
|
// m_DXTechnique.Clear();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
CKBOOL RCKShaderDX8::IsSupported() const
|
|
{
|
|
const int rcCount = m_DXEffect.Size();
|
|
for( int rcIndex=0 ; rcIndex<rcCount ; ++rcIndex ){
|
|
if( !m_DXEffect[rcIndex] ) return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
int RCKShaderDX8::Begin(CKRenderContext* rc)
|
|
{
|
|
UINT NumPasses;
|
|
const int rcIndex = m_ShaderManager->_GetRenderContextIndex(rc);
|
|
#ifdef _XBOX
|
|
ID3DXTechnique* tec = (ID3DXTechnique*) m_CurrTechnique->handle[rcIndex];
|
|
XASSERT(tec);
|
|
HRESULT hr = tec->Begin(&NumPasses);
|
|
#else
|
|
HRESULT hr = m_DXEffect[rcIndex]->Begin( &NumPasses, 0 );
|
|
#endif
|
|
|
|
assert(SUCCEEDED(hr));
|
|
assert(NumPasses >= (UINT)m_CurrTechnique->pubpasses.Size());
|
|
return m_CurrTechnique->pubpasses.Size();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void RCKShaderDX8::EndPass(CKRenderContext* rc)
|
|
{
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void RCKShaderDX8::CommitChanges(CKRenderContext* rc)
|
|
{
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void RCKShaderDX8::BeginPass(CKDWORD Num,CKRenderContext* rc)
|
|
{
|
|
const int rcIndex = m_ShaderManager->_GetRenderContextIndex(rc);
|
|
XArray<DWORD>& passes = m_CurrTechnique->pubpasses;
|
|
#ifdef _XBOX
|
|
ID3DXTechnique* tec = (ID3DXTechnique*) m_CurrTechnique->handle[rcIndex];
|
|
XASSERT(tec);
|
|
HRESULT hr = tec->Pass(passes[Num]);
|
|
IDirect3DDevice8* dev = DeviceFromRC(rc);
|
|
D3DSURFACE_DESC desc;
|
|
for(int i=0;i<4;i++){
|
|
LPDIRECT3DTEXTURE8 tex = NULL;
|
|
dev->GetTexture(i,(D3DBaseTexture**)&tex);
|
|
if(tex){
|
|
tex->GetLevelDesc(0,&desc);
|
|
if(VxIsSignedFormat(desc.Format)){
|
|
dev->SetTextureStageState(i,D3DTSS_COLORSIGN,D3DTSIGN_RSIGNED | D3DTSIGN_GSIGNED | D3DTSIGN_BSIGNED);
|
|
}else{
|
|
dev->SetTextureStageState(i,D3DTSS_COLORSIGN,0);
|
|
}
|
|
|
|
if(!VxIsSwizzledFormat(desc.Format)){
|
|
DWORD valU,valV;
|
|
D3DDevice::GetTextureStageState(i,D3DTSS_ADDRESSU,&valU);
|
|
D3DDevice::GetTextureStageState(i,D3DTSS_ADDRESSU,&valV);
|
|
|
|
if(valU < D3DTADDRESS_CLAMP || valV < D3DTADDRESS_CLAMP ){
|
|
rc->SetTextureStageState(CKRST_TSS_ADDRESS,VXTEXTURE_ADDRESSCLAMP,i);
|
|
}
|
|
}
|
|
tex->Release();
|
|
}
|
|
}
|
|
|
|
dev->Release();
|
|
|
|
#else
|
|
HRESULT hr = m_DXEffect[rcIndex]->Pass(passes[Num]);
|
|
#endif
|
|
assert(SUCCEEDED(hr));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void RCKShaderDX8::End(CKRenderContext* rc)
|
|
{
|
|
const int rcIndex = m_ShaderManager->_GetRenderContextIndex(rc);
|
|
#ifdef _XBOX
|
|
ID3DXTechnique* tec = (ID3DXTechnique*) m_CurrTechnique->handle[rcIndex];
|
|
XASSERT(tec);
|
|
|
|
if(gRestoreConstantMode){
|
|
D3DDevice::SetVertexShaderInputDirect(NULL,0,NULL);
|
|
D3DDevice::SetShaderConstantMode(D3DSCM_96CONSTANTS);
|
|
}
|
|
|
|
HRESULT hr = tec->End();
|
|
IDirect3DDevice8* dev = DeviceFromRC(rc);
|
|
for(int i=0;i<4;i++){
|
|
dev->SetTextureStageState(i,D3DTSS_COLORSIGN,0);
|
|
// dev->SetTexture(i,NULL);
|
|
}
|
|
dev->Release();
|
|
|
|
#else
|
|
HRESULT hr = m_DXEffect[rcIndex]->End();
|
|
#endif
|
|
assert(SUCCEEDED(hr));
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool RCKShaderDX8::IsTechniqueOf(const XString& str) const
|
|
{
|
|
for (int i = 0; i < m_Techniques.Size(); ++i)
|
|
if (m_Techniques[i].name == str)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void RCKShaderDX8::SetTechnique(const XString& tech)
|
|
{
|
|
|
|
const int rcCount = m_DXEffect.Size();
|
|
|
|
for (int i = 0; i < m_Techniques.Size(); ++i)
|
|
if (m_Techniques[i].name == tech){
|
|
for( int rcIndex=0 ; rcIndex<rcCount ; ++rcIndex ){
|
|
SetTechnique(( CKShader::Technique *)&m_Techniques[i]);
|
|
m_CurrTechnique = &m_Techniques[i];
|
|
}
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void RCKShaderDX8::SetTechnique(const CKShader::Technique *tech)
|
|
{
|
|
const int rcCount = m_DXEffect.Size();
|
|
|
|
if(m_CurrTechnique != (Technique*)tech){
|
|
m_CurrTechnique = (Technique*)tech;
|
|
_UpdateInternalTechnique();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool RCKShaderDX8::FindNextValidTechnique(XString& tech) const
|
|
{
|
|
D3DXHANDLE next = NULL;
|
|
CKBOOL reserved = TRUE;
|
|
|
|
// Finds the first technique
|
|
int t = 0;
|
|
for (int i = 0; i < m_Techniques.Size(); ++i)
|
|
if (m_Techniques[i].name == tech)
|
|
{
|
|
t = i;
|
|
break;
|
|
}
|
|
|
|
for (int fi = t; fi < m_Techniques.Size(); ++fi)
|
|
if (!(m_Techniques[fi].options & FXOPT_RESERVED)
|
|
&& (m_Techniques[fi].options & FXOPT_VALID))
|
|
{
|
|
tech = m_Techniques[fi].name;
|
|
return true;
|
|
}
|
|
|
|
// returns false if no technique is found.
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool RCKShaderDX8::GetPass(const CKShader::Technique* tech, const char* name, int& pos) const
|
|
{
|
|
if (!tech)
|
|
return false;
|
|
|
|
Technique* t = (Technique*)tech;
|
|
for (int i = 0; i < t->passes.Size(); ++i)
|
|
if (strcmp(t->passes[i].name.CStr(), name) == 0)
|
|
{
|
|
pos = i;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Effect parameters feature
|
|
//-----------------------------------------------------------------------------
|
|
void RCKShaderDX8::SetParameter(CKParameterLocal* param)
|
|
{
|
|
XASSERT(0);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void RCKShaderDX8::SetParameters(const XArray<CKParameterLocal*>& params)
|
|
{
|
|
|
|
CKRenderManager* rm = m_ShaderManager->m_Context->GetRenderManager();
|
|
|
|
const int rcCount = m_DXEffect.Size();
|
|
for( int rcIndex=0 ; rcIndex<rcCount ; ++rcIndex ){
|
|
|
|
CKRenderContext* rc = m_ShaderManager->m_rcList[rcIndex];
|
|
|
|
for (int i = 0; i < params.Size(); ++i)
|
|
{
|
|
CKParameterLocal* param = params[i];
|
|
D3DXHANDLE h = GetD3DXHandle(param);
|
|
// there is handle is not = 0 if the parameter has been linked
|
|
if (!h)
|
|
return;
|
|
|
|
|
|
#ifdef _XBOX
|
|
// In DX8.0 the app data is the parameter index
|
|
#else
|
|
// In DX8.1 the app data is fourCC of the name
|
|
// Get the Real Name from the Parameter
|
|
h = param->GetName();
|
|
#endif
|
|
|
|
DWORD hr;
|
|
// Special case for Texture
|
|
if (param->GetGUID() == CKPGUID_TEXTURE)
|
|
{
|
|
CKTexture* tex = (CKTexture*)param->GetValueObject();
|
|
_SetParamWithTexture(h, tex, rc);
|
|
}
|
|
// Special case for 3dEntity {TM and position}
|
|
else if (param->GetGUID() == CKPGUID_3DENTITY)
|
|
{
|
|
CK3dEntity* en = (CK3dEntity*)param->GetValueObject();
|
|
if (en)
|
|
{
|
|
D3DXPARAMETER_DESC desc;
|
|
hr = m_DXEffect[rcIndex]->GetParameterDesc(h, &desc);
|
|
XASSERT(SUCCEEDED(hr));
|
|
switch(desc.Type ){
|
|
case D3DXPT_VECTOR:
|
|
{
|
|
VxVector position;
|
|
en->GetPosition(&position);
|
|
hr = m_DXEffect[rcIndex]->SetVector(h, (D3DXVECTOR4*)&position);
|
|
XASSERT(SUCCEEDED(hr));
|
|
}
|
|
break;
|
|
case D3DXPT_MATRIX:
|
|
{
|
|
#ifdef _XBOX
|
|
D3DXMATRIX tmp;
|
|
D3DXMatrixTranspose(&tmp,(D3DXMATRIX*) &en->GetWorldMatrix());
|
|
hr = m_DXEffect[rcIndex]->SetMatrix(h,&tmp);
|
|
#else
|
|
hr = m_DXEffect[rcIndex]->SetMatrix(h, (D3DXMATRIX*)&en->GetWorldMatrix());
|
|
#endif
|
|
XASSERT(SUCCEEDED(hr));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
// Other cases
|
|
else if (param->GetGUID() == CKPGUID_FLOAT)
|
|
{
|
|
|
|
if(h == 'PASC' || h == 'PASI'){
|
|
float f = (float) *(DWORD*) param->GetReadDataPtr();
|
|
hr = m_DXEffect[rcIndex]->SetFloat(h,f);
|
|
}else{
|
|
hr = m_DXEffect[rcIndex]->SetFloat(h, *(float*)param->GetReadDataPtr());
|
|
}
|
|
XASSERT(SUCCEEDED(hr));
|
|
}
|
|
else if (param->GetGUID() == CKPGUID_INT)
|
|
{
|
|
hr = m_DXEffect[rcIndex]->SetDword(h, *(int*)param->GetReadDataPtr());
|
|
XASSERT(SUCCEEDED(hr));
|
|
}
|
|
else if (param->GetGUID() == CKPGUID_VECTOR4)
|
|
{
|
|
D3DXVECTOR4 tmp;
|
|
param->GetValue(&tmp,TRUE);
|
|
hr = m_DXEffect[rcIndex]->SetVector(h, &tmp);
|
|
XASSERT(SUCCEEDED(hr));
|
|
}
|
|
else if (param->GetGUID() == CKPGUID_MATRIX)
|
|
{
|
|
hr = m_DXEffect[rcIndex]->SetMatrix(h,(D3DXMATRIX*) param->GetReadDataPtr());
|
|
XASSERT(SUCCEEDED(hr));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
BOOL RCKShaderDX8::IsAutomaticUsed( ShaderAutomaticParameter index )
|
|
{
|
|
return m_AutomaticHandle[index]!=NULL;
|
|
}
|
|
|
|
void RCKShaderDX8::SetAutomaticValue(
|
|
ShaderAutomaticParameter index,
|
|
const void* valueBuffer,
|
|
CKRenderContext* rc,CKDWORD iSize)
|
|
{
|
|
if( m_AutomaticHandle[index] == NULL ) return;
|
|
|
|
ShaderAutomaticInfoDX8& info = m_ShaderManager->GetRegAutomaticInfo(index);
|
|
HRESULT hr = S_OK;
|
|
|
|
const int rcIndex = m_ShaderManager->_GetRenderContextIndex(rc);
|
|
|
|
#ifdef _XBOX
|
|
#define PARAM info.m_dName
|
|
#else
|
|
#define PARAM info.m_name.CStr()
|
|
#endif
|
|
|
|
switch(info.m_d3dType){
|
|
case D3DXPT_DWORD:
|
|
if(index == FXAP_BONES){
|
|
|
|
DWORD idx = 0;
|
|
hr = m_DXEffect[rcIndex]->GetDword(PARAM,&idx);
|
|
gRestoreConstantMode = TRUE;
|
|
|
|
D3DDevice::SetShaderConstantMode(D3DSCM_192CONSTANTS/* | D3DSCM_NORESERVEDCONSTANTS*/);
|
|
for(DWORD i = 0;i<iSize/sizeof(VxMatrix);i++){
|
|
D3DDevice::SetVertexShaderConstantFast(idx+3*i,
|
|
((BYTE*)valueBuffer)+i*sizeof(VxMatrix),3);
|
|
}
|
|
}else
|
|
if(index == FXAP_TBONES){
|
|
|
|
DWORD idx = 0;
|
|
hr = m_DXEffect[rcIndex]->GetDword(PARAM,&idx);
|
|
gRestoreConstantMode = TRUE;
|
|
D3DDevice::SetShaderConstantMode(D3DSCM_192CONSTANTS/* | D3DSCM_NORESERVEDCONSTANTS*/);
|
|
XGMATRIX mat;
|
|
|
|
for(DWORD i = 0;i<iSize/sizeof(VxMatrix);i++){
|
|
XGMatrixTranspose(&mat,(const XGMATRIX*)((BYTE*)valueBuffer)+i*sizeof(VxMatrix));
|
|
D3DDevice::SetVertexShaderConstantFast(idx+3*i,mat,3);
|
|
}
|
|
}else
|
|
if(index == FXAP_BONESINDEXCONSTANT){
|
|
DWORD idx = 0;
|
|
hr = m_DXEffect[rcIndex]->GetDword(PARAM,&idx);
|
|
XGVECTOR4 v(255.002f,0.0f,0.0f,0.0f);
|
|
D3DDevice::SetVertexShaderConstantFast(idx,&v,1);
|
|
}else
|
|
{
|
|
hr = m_DXEffect[rcIndex]->SetDword(PARAM,*(DWORD*) valueBuffer);
|
|
}
|
|
break;
|
|
|
|
case D3DXPT_FLOAT:
|
|
if(index == FXAP_PASSCOUNT || index == FXAP_PASSINDEX){
|
|
float f = (float) *(DWORD*) valueBuffer;
|
|
hr = m_DXEffect[rcIndex]->SetFloat(PARAM,f);
|
|
}else{
|
|
hr = m_DXEffect[rcIndex]->SetFloat(PARAM,*(float*) valueBuffer);
|
|
}
|
|
break;
|
|
|
|
case D3DXPT_VECTOR:
|
|
switch(index){
|
|
case FXAP_TIME:
|
|
{
|
|
D3DXVECTOR4 v;
|
|
v.x = *(float*) valueBuffer;
|
|
v.y = sinf(v.x);
|
|
v.z = cosf(v.x);
|
|
v.w = 1.0f;
|
|
hr = m_DXEffect[rcIndex]->SetVector(PARAM,(D3DXVECTOR4*) &v);
|
|
}
|
|
break;
|
|
|
|
case FXAP_OBJECTPOS:
|
|
case FXAP_EYEPOS:
|
|
{
|
|
D3DXVECTOR4 v;
|
|
v.x = ((VxVector*) valueBuffer)->x;
|
|
v.y = ((VxVector*) valueBuffer)->y;
|
|
v.z = ((VxVector*) valueBuffer)->z;
|
|
v.w = 1.0f;
|
|
hr = m_DXEffect[rcIndex]->SetVector(PARAM,(D3DXVECTOR4*) &v);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
hr = m_DXEffect[rcIndex]->SetVector(PARAM,(D3DXVECTOR4*) valueBuffer);
|
|
}
|
|
break;
|
|
|
|
case D3DXPT_MATRIX:
|
|
#ifdef _XBOX
|
|
D3DXMATRIX tmp;
|
|
D3DXMatrixTranspose(&tmp,(D3DXMATRIX*) valueBuffer);
|
|
hr = m_DXEffect[rcIndex]->SetMatrix(PARAM,&tmp);
|
|
#else
|
|
hr = m_DXEffect[rcIndex]->SetMatrix(PARAM,(D3DXMATRIX*) valueBuffer);
|
|
#endif
|
|
break;
|
|
|
|
}
|
|
XASSERT(SUCCEEDED(hr));
|
|
}
|
|
|
|
|
|
void RCKShaderDX8::SetAutomaticValueTexture(
|
|
ShaderAutomaticParameter index,
|
|
CKTexture* iTex ,CKRenderContext* rc)
|
|
{
|
|
if( m_AutomaticHandle[index] == NULL ) return;
|
|
|
|
_SetParamWithTexture( m_AutomaticHandle[index], iTex, rc);
|
|
}
|
|
|
|
|
|
void RCKShaderDX8::_SetParamWithTexture( D3DXHANDLE handle, CKTexture* iTex, CKRenderContext* rc )
|
|
{
|
|
|
|
const int rcIndex = m_ShaderManager->_GetRenderContextIndex(rc);
|
|
|
|
LPDIRECT3DBASETEXTURE8 d3dTex = NULL;
|
|
if( iTex ){
|
|
CKRenderContext* rc = m_ShaderManager->m_Context->GetRenderManager()->GetRenderContext(0);
|
|
iTex->EnsureVideoMemory(rc);
|
|
CKDX8TextureDesc* texdesc = (CKDX8TextureDesc*)
|
|
rc->GetRasterizerContext()->GetTextureData( iTex->GetRstTextureIndex() );
|
|
if (texdesc)
|
|
{
|
|
d3dTex = texdesc->DxCubeTexture;
|
|
XASSERT(d3dTex != NULL);
|
|
}
|
|
}
|
|
|
|
LPDIRECT3DBASETEXTURE8 tex;
|
|
m_DXEffect[rcIndex]->GetTexture( handle, &tex);
|
|
if(tex)
|
|
tex->Release();
|
|
|
|
if(tex != d3dTex){
|
|
DWORD hr = m_DXEffect[rcIndex]->SetTexture(handle, d3dTex);
|
|
XASSERT(SUCCEEDED(hr));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void RCKShaderDX8::ComputeTexelSizes(CKRenderContext* rc)
|
|
{
|
|
HRESULT hr;
|
|
|
|
const int rcIndex = m_ShaderManager->_GetRenderContextIndex(rc);
|
|
|
|
const int texelSizeCount = m_TexelArray.Size();
|
|
for( int a=0 ; a<texelSizeCount ; ++a ){
|
|
|
|
//--- Check that texture param exists
|
|
if( !m_TexelArray[a].tex ) continue;
|
|
|
|
//--- Get interface to d3d base texture From D3DXHANDLE
|
|
LPDIRECT3DBASETEXTURE8 d3dTexture=NULL;
|
|
hr = m_DXEffect[rcIndex]->GetTexture( m_TexelArray[a].tex, &d3dTexture );
|
|
if( !d3dTexture ) continue;
|
|
|
|
//--- Get interface to d3d texture
|
|
IDirect3DTexture8* texture = NULL;
|
|
#ifdef _XBOX
|
|
if(D3DRTYPE_TEXTURE == d3dTexture->GetType()){
|
|
texture = (IDirect3DTexture8*) d3dTexture;
|
|
texture->AddRef();
|
|
}
|
|
#else
|
|
hr = d3dTexture->QueryInterface( IID_IDirect3DTexture8, (void**)&texture);
|
|
#endif
|
|
if( !texture ){
|
|
d3dTexture->Release();
|
|
continue;
|
|
}
|
|
|
|
//--- Get texture desc
|
|
D3DSURFACE_DESC desc;
|
|
hr = texture->GetLevelDesc( 0, &desc );
|
|
|
|
//--- Compute Texel Size from Texture Width and Height
|
|
Vx2DVector texelSize( 1.0f/desc.Width, 1.0f/desc.Height );
|
|
|
|
|
|
// Vx2DVector texelSize( 1.0f/512.0f, 1.0f/512.0f );
|
|
|
|
//--- Put Texel Size inside given parameter (the one with teh annotation)
|
|
D3DXVECTOR4 v;
|
|
|
|
v.x = texelSize.x;
|
|
v.y = texelSize.y;
|
|
v.z = 0.0f;
|
|
v.w = 0.0f;
|
|
|
|
hr = m_DXEffect[rcIndex]->SetVector(m_TexelArray[a].param, &v);
|
|
|
|
//--- Release D3D Interfaces
|
|
d3dTexture->Release();
|
|
texture->Release();
|
|
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------------
|
|
int RCKShaderDX8::GetParameterCount(CKRenderContext* rc)
|
|
{
|
|
const rcIndex = m_ShaderManager->_GetRenderContextIndex(rc);
|
|
|
|
if( !m_DXEffect[rcIndex] ) return 0;
|
|
|
|
D3DXEFFECT_DESC desc;
|
|
m_DXEffect[rcIndex]->GetDesc(&desc);
|
|
|
|
return desc.Parameters;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void RCKShaderDX8::_GetParameterInfo(D3DXPARAMETER_DESC& pdesc, ParamInfo& paramInfo )
|
|
{
|
|
|
|
static CKGUID typemap[] =
|
|
{
|
|
CKPGUID_INT, //D3DXPT_DWORD
|
|
CKPGUID_FLOAT, //D3DXPT_FLOAT
|
|
CKPGUID_VECTOR4,//D3DXPT_VECTOR
|
|
CKPGUID_MATRIX, //D3DXPT_MATRIX
|
|
CKPGUID_TEXTURE,//D3DXPT_TEXTURE
|
|
CKGUID(), //D3DXPT_VERTEXSHADER
|
|
CKGUID(), //D3DXPT_PIXELSHADER
|
|
CKPGUID_FLOAT, //D3DXPT_CONSTANT
|
|
};
|
|
|
|
#ifdef _XBOX
|
|
FourCC2XString(paramInfo.name,pdesc.Name);
|
|
#else
|
|
paramInfo.name = pdesc.Name;
|
|
#endif
|
|
if(pdesc.Type<=D3DXPT_TEXTURE){
|
|
paramInfo.guid = typemap[pdesc.Type];
|
|
//--- Automatics
|
|
if ( m_ShaderManager->IsAutomatic( pdesc))
|
|
paramInfo.type = CKShader::AUTOMATIC;
|
|
else{
|
|
if(pdesc.Name == '0ZIS' ||
|
|
pdesc.Name == '1ZIS' ||
|
|
pdesc.Name == '2ZIS' ||
|
|
pdesc.Name == '3ZIS' ){
|
|
paramInfo.type = CKShader::TEXELSIZE;
|
|
}else{
|
|
paramInfo.type = CKShader::NORMAL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void RCKShaderDX8::GetParameterInfo( int paramIndex, ParamInfo& paramInfo,CKRenderContext* rc)
|
|
{
|
|
paramInfo.type = CKShader::INVALID;
|
|
|
|
const int rcIndex = m_ShaderManager->_GetRenderContextIndex(rc);
|
|
if( !m_DXEffect[rcIndex] )
|
|
return;
|
|
|
|
D3DXPARAMETER_DESC pdesc;
|
|
#ifdef _XBOX
|
|
m_DXEffect[rcIndex]->GetParameterDesc(paramIndex, &pdesc);
|
|
#else
|
|
m_DXEffect[rcIndex]->GetParameterDesc((LPCSTR)paramIndex, &pdesc);
|
|
#endif
|
|
|
|
_GetParameterInfo( pdesc, paramInfo );
|
|
|
|
return;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool RCKShaderDX8::LinkParameters(int& CompID, XArray<CKParameterLocal*>& params, CKBOOL cleanup)
|
|
{
|
|
|
|
//--- If comes from the same compilation, nothing to do.
|
|
if (CompID == m_CompID)
|
|
return false;
|
|
|
|
CKRenderManager* rm = m_ShaderManager->m_Context->GetRenderManager();
|
|
|
|
const int rcCount = m_DXEffect.Size();
|
|
for( int rcIndex=0 ; rcIndex<rcCount ; ++rcIndex ){
|
|
|
|
if( !m_DXEffect[rcIndex] )
|
|
continue;
|
|
|
|
CKRenderContext* rc = m_ShaderManager->m_rcList[rcIndex];
|
|
|
|
|
|
//--- Set AppData of each params to point to the corresponding D3DXHANDLE,
|
|
///// and remove params that doesn't appear anymore in the shader code.
|
|
cleanup = TRUE; // force cleaning
|
|
ParamInfo pInfo;
|
|
BOOL bRemove = FALSE;
|
|
for (int ip = 0; ip < params.Size(); ++ip)
|
|
{
|
|
if( !params[ip] ) continue;
|
|
|
|
D3DXPARAMETER_DESC pdesc;
|
|
#ifdef _XBOX
|
|
// On Xbox the Parameter Desc is accessed by handle, We need to iterate until we find the correct one.
|
|
D3DXHANDLE h = NULL;
|
|
int count = this->GetParameterCount(rc);
|
|
DWORD fcc = XString2FourCC(XString(params[ip]->GetName()));
|
|
HRESULT hr = E_FAIL;
|
|
for(int i=0;i<count;i++){
|
|
hr = m_DXEffect[rcIndex] ->GetParameterDesc(i, &pdesc);
|
|
if(SUCCEEDED(hr) && pdesc.Name == fcc){
|
|
h = pdesc.Name;
|
|
break;
|
|
}
|
|
}
|
|
#else
|
|
D3DXHANDLE h = params[ip]->GetName();
|
|
HRESULT hr = m_DXEffect[rcIndex] ->GetParameterDesc(h, &pdesc);
|
|
#endif
|
|
|
|
if(hr == S_OK){
|
|
|
|
//--- If it's an automatic
|
|
///// then remove it from the list by setting handle to NULL
|
|
if( m_ShaderManager->IsAutomatic( pdesc ) )
|
|
bRemove = TRUE;
|
|
else
|
|
bRemove = FALSE;
|
|
|
|
//--- If its guid has changed (for example because its annotation has changed)
|
|
///// then change its type
|
|
_GetParameterInfo(pdesc, pInfo );
|
|
if( !pInfo.guid.IsValid() || params[ip]->GetGUID() != pInfo.guid ){
|
|
params[ip]->SetGUID( pInfo.guid );
|
|
}
|
|
}else{
|
|
bRemove = TRUE;
|
|
}
|
|
|
|
//--- If cleaning is asked, then destroy params which name does not match
|
|
///// any D3DX Parameter, and remove them from input list
|
|
///// Note: now we should decide not to take anymore the clean parameter
|
|
///// into account anymore, and to clean always unused parameters.
|
|
if( cleanup && bRemove)
|
|
{
|
|
CKParameterLocal* p = params[ip];
|
|
m_ShaderManager->m_Context->DestroyObject(p, CK_DESTROY_NONOTIFY);
|
|
params.RemoveAt(ip);
|
|
--ip;
|
|
//--- Otherwise set AppData to the corresponding D3DXHANDLE
|
|
} else {
|
|
#ifdef _XBOX
|
|
// On DX8 set the App data to a DWORD the fourCC name of the param
|
|
// Used when linking parameter ( LinkParameters )
|
|
params[ip]->SetAppData((void*) h);
|
|
#else
|
|
// On DX8.1 set the App data to a fourCC
|
|
// Used when linking parameter ( LinkParameters )
|
|
params[ip]->SetAppData((void*) XString2FourCC(XString(pdesc.Name)));
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//--- Now parse all parameters described in the D3DXEFFECT_DESC
|
|
///// To find some new parameters that need to be exposed.
|
|
ParamInfo paramInfo;
|
|
D3DXEFFECT_DESC desc;
|
|
m_DXEffect[rcIndex] ->GetDesc(&desc);
|
|
D3DXHANDLE previousTextureParam = NULL;
|
|
D3DXHANDLE h = NULL;
|
|
|
|
for (DWORD i = 0; i < desc.Parameters; ++i)
|
|
{
|
|
//--- Get some parameter infos
|
|
D3DXPARAMETER_DESC pdesc;
|
|
m_DXEffect[rcIndex] ->GetParameterDesc((D3DXHANDLE)i, &pdesc);
|
|
|
|
//--- If it's a sampler or something else, then don't expose it
|
|
if( pdesc.Type > D3DXPT_TEXTURE )
|
|
continue;
|
|
|
|
//--- Get Parameter Info
|
|
GetParameterInfo( i, paramInfo, rc );
|
|
if( !paramInfo.guid.IsValid() ) continue;
|
|
|
|
//--- If it's a texture param then remember it as the last parsed
|
|
///// texture param, just in case there's a TEXELSIZE param further.
|
|
if( paramInfo.guid == CKPGUID_TEXTURE ){
|
|
previousTextureParam = pdesc.Name;
|
|
}
|
|
//--- If it's a TEXELSIZE param, then don't create CKParameter,
|
|
///// but add the param handle and texture handle to the TexelArray[] instead.
|
|
if( paramInfo.type == CKShader::TEXELSIZE ){
|
|
ParamAndTextureHandle paramAndTex = { pdesc.Name, previousTextureParam };
|
|
m_TexelArray.PushBack( paramAndTex );
|
|
continue;
|
|
}
|
|
|
|
#ifdef _XBOX
|
|
h = pdesc.Name;
|
|
#else
|
|
h = (LPCSTR) XString2FourCC(XString(pdesc.Name));
|
|
#endif
|
|
|
|
//--- Find one of our params that points to this handle
|
|
bool found = false;
|
|
for (int par = 0; !found && par < params.Size(); ++par){
|
|
if (GetD3DXHandle(params[par]) == h)
|
|
found = true;
|
|
}
|
|
//--- If not found it means it has never been created...
|
|
if (!found)
|
|
{
|
|
//--- ...beware it is not an automatic parameter
|
|
if (!m_ShaderManager->IsAutomatic( pdesc ))
|
|
{
|
|
GetParameterInfo( i, paramInfo,rc);
|
|
|
|
//--- So let's create a new CKParameter for this D3DXPARAMETER
|
|
CKParameterLocal* p =
|
|
m_ShaderManager->m_Context->CreateCKParameterLocal(
|
|
paramInfo.name.Str(), paramInfo.guid );
|
|
if (p)
|
|
{
|
|
|
|
///--- While we are at it, tries to give the brand new parameter
|
|
///// the same value as the one in the shader.
|
|
if (!(p->GetGUID() == CKPGUID_3DENTITY
|
|
|| p->GetGUID() == CKPGUID_TEXTURE))
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CKGUID g(p->GetGUID());
|
|
if(g == CKPGUID_INT){
|
|
hr = m_DXEffect[rcIndex] ->GetDword(pdesc.Name, (DWORD*)p->GetWriteDataPtr());
|
|
}else
|
|
if(g == CKPGUID_FLOAT){
|
|
hr = m_DXEffect[rcIndex] ->GetFloat(pdesc.Name, (FLOAT*)p->GetWriteDataPtr());
|
|
}else
|
|
if(g == CKPGUID_VECTOR4){
|
|
hr = m_DXEffect[rcIndex] ->GetVector(pdesc.Name, (D3DXVECTOR4*)p->GetWriteDataPtr());
|
|
}else
|
|
if(g == CKPGUID_MATRIX){
|
|
hr = m_DXEffect[rcIndex] ->GetMatrix(pdesc.Name, (D3DXMATRIX*)p->GetWriteDataPtr());
|
|
}
|
|
assert(SUCCEEDED(hr));
|
|
|
|
}
|
|
|
|
#ifdef _XBOX
|
|
p->SetAppData((void*)pdesc.Name);
|
|
#else
|
|
p->SetAppData(const_cast<char*>(h));
|
|
#endif
|
|
params.PushBack(p);
|
|
|
|
} else {
|
|
//m_ShaderManager->m_Context->OutputToConsoleEx("Cannot get parameter '%s'.", pdesc.Name);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//--- Updates the compilation id.
|
|
|
|
CompID = m_CompID;
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
bool RCKShaderDX8::LinkTechnique(int& CompID, const XString& tech, BOOL fnvt, CKShader::Technique*& outtech)
|
|
{
|
|
// If comes from the same compilation, nothing to do.
|
|
if (CompID == m_CompID)
|
|
return false;
|
|
|
|
// Fix the technique reference.
|
|
outtech = NULL;
|
|
if (!m_Techniques.Size())
|
|
return false;
|
|
|
|
int t = 0;
|
|
bool found = false;
|
|
for (int i = 0; !found && i < m_Techniques.Size(); ++i)
|
|
if (m_Techniques[i].name == tech)
|
|
{
|
|
found = true;
|
|
t = i;
|
|
}
|
|
|
|
if (!found)
|
|
return false;
|
|
|
|
// Finds the next valid technique.
|
|
if (fnvt)
|
|
for (; t < m_Techniques.Size(); ++t)
|
|
if (m_Techniques[t].options & FXOPT_VALID
|
|
&& !(m_Techniques[t].options & FXOPT_RESERVED))
|
|
break;
|
|
|
|
if (t < m_Techniques.Size() && m_Techniques[t].options & FXOPT_VALID)
|
|
outtech = (CKShader::Technique*)&m_Techniques[t];
|
|
|
|
// Updates the compilation id.
|
|
CompID = m_CompID;
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Compiling
|
|
//-----------------------------------------------------------------------------
|
|
void RCKShaderDX8::Compile(CKContext* Context)
|
|
{
|
|
XClassArray<XString> output;
|
|
m_ShaderManager->CompileShader(this, output);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
XString RCKShaderDX8::_GetTechFlagString(DWORD options) const
|
|
{
|
|
XString desc;
|
|
|
|
if (options & FXOPT_RESERVED)
|
|
{
|
|
if (desc.Length()) desc += ", ";
|
|
desc += "reserved";
|
|
}
|
|
if (options & FXOPT_SKIPOCCLUSION)
|
|
{
|
|
if (desc.Length()) desc += ", ";
|
|
desc += "skip occlusion";
|
|
}
|
|
if (options & FXOPT_USAGE2D)
|
|
{
|
|
if (desc.Length()) desc += ", ";
|
|
desc += "usage 2d";
|
|
}
|
|
if (!(options & FXOPT_VALID))
|
|
{
|
|
if (desc.Length()) desc += ", ";
|
|
desc += "*";
|
|
}
|
|
return desc;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void RCKShaderDX8::_RetrieveTechniques( CKRenderContext* rc )
|
|
{
|
|
const int rcIndex = m_ShaderManager->_GetRenderContextIndex(rc);
|
|
const int rcCount = m_ShaderManager->m_rcList.Size();
|
|
|
|
m_Techniques.Clear();
|
|
|
|
D3DXEFFECT_DESC fxdesc;
|
|
m_DXEffect[rcIndex]->GetDesc(&fxdesc);
|
|
for (DWORD it = 0; it < fxdesc.Techniques; ++it)
|
|
{
|
|
// Get Technique info.
|
|
Technique tech(rcCount);
|
|
D3DXTECHNIQUE_DESC techdesc;
|
|
m_DXEffect[rcIndex]->GetTechniqueDesc((D3DXHANDLE)it, &techdesc);
|
|
|
|
#ifdef _XBOX
|
|
FourCC2XString(tech.name,techdesc.Name);
|
|
#else
|
|
tech.name = techdesc.Name;
|
|
#endif
|
|
|
|
#ifdef _XBOX
|
|
// Validate or not the techinque
|
|
ID3DXTechnique* tec = NULL;
|
|
m_DXEffect[rcIndex]->GetTechnique(it,&tec);
|
|
XASSERT(tec);
|
|
//tech.options = SUCCEEDED(tec->Validate()) ? FXOPT_VALID : 0;
|
|
tech.options = FXOPT_VALID;
|
|
tech.desc = _GetTechFlagString(tech.options);
|
|
tech.handle[rcIndex] = tec; // We keep the technique in the handle
|
|
#else
|
|
// Validate or not the techinque
|
|
m_DXEffect[rcIndex]->SetTechnique(techdesc.Name);
|
|
tech.options = SUCCEEDED(m_DXEffect[rcIndex]->Validate()) ? FXOPT_VALID : 0;
|
|
tech.desc = _GetTechFlagString(tech.options);
|
|
tech.handle[rcIndex] = (void*)techdesc.Name;
|
|
#endif
|
|
// Retrieve passes.
|
|
for (DWORD ip = 0; ip < techdesc.Passes; ++ip)
|
|
{
|
|
// Get Pass info.
|
|
Pass pass(rcCount);
|
|
D3DXPASS_DESC passdesc;
|
|
|
|
#ifdef _XBOX
|
|
tec->GetPassDesc(ip,&passdesc);
|
|
FourCC2XString(pass.name,passdesc.Name);
|
|
pass.handle[rcIndex] = (void*)passdesc.Name;
|
|
#else
|
|
m_DXEffect[rcIndex]->GetPassDesc(tech.name.CStr(),(LPCSTR) ip,&passdesc);
|
|
pass.name = passdesc.Name;
|
|
pass.handle[rcIndex] = &pass.name;
|
|
#endif
|
|
pass.options = 0;
|
|
|
|
if (!(pass.options & FXOPT_RESERVED))
|
|
tech.pubpasses.PushBack(ip);
|
|
|
|
// Adds the pass to the technique.
|
|
tech.passes.PushBack(pass);
|
|
}
|
|
|
|
|
|
// Adds the technique to the effect.
|
|
m_Techniques.PushBack(tech);
|
|
|
|
}
|
|
SetTechnique((CKShader::Technique *) m_Techniques.Begin());
|
|
|
|
_RebuildTechniqueEnum();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void RCKShaderDX8::_RebuildTechniqueEnum()
|
|
{
|
|
XString init;
|
|
// Creates the init string
|
|
for (int i = 0; i < m_Techniques.Size(); ++i)
|
|
if (!(m_Techniques[i].options & FXOPT_RESERVED))
|
|
{
|
|
XString s;
|
|
s.Format("%s=%d", m_Techniques[i].name.CStr(), i);
|
|
if (i != 0)
|
|
init += ",";
|
|
init += s;
|
|
}
|
|
|
|
CKContext* m_CKContext = m_ShaderManager->m_Context;
|
|
CKParameterManager* pman = m_CKContext->GetParameterManager();
|
|
if (!m_TechGuid.IsValid())
|
|
{
|
|
m_TechGuid = m_CKContext->GetSecureGuid();
|
|
pman->RegisterNewEnum(m_TechGuid, "Technique", init.Str());
|
|
}
|
|
else
|
|
pman->ChangeEnumDeclaration(m_TechGuid, init.Str());
|
|
}
|
|
|
|
void RCKShaderDX8::ReleaseDxEffect(int rcIndex){
|
|
if(m_DXEffect[rcIndex]){
|
|
|
|
// Clean Texture parameters
|
|
D3DXEFFECT_DESC desc;
|
|
m_DXEffect[rcIndex]->GetDesc(&desc);
|
|
for (DWORD i = 0; i < desc.Parameters; ++i)
|
|
{
|
|
//--- Get parameter infos
|
|
D3DXPARAMETER_DESC pdesc;
|
|
m_DXEffect[rcIndex]->GetParameterDesc((D3DXHANDLE)i, &pdesc);
|
|
|
|
if( pdesc.Type == D3DXPT_TEXTURE ) {
|
|
LPDIRECT3DBASETEXTURE8 tex;
|
|
m_DXEffect[rcIndex]->GetTexture(pdesc.Name,&tex);
|
|
if(tex){
|
|
m_DXEffect[rcIndex]->SetTexture(pdesc.Name,NULL);
|
|
int rf = tex->Release();
|
|
}
|
|
}
|
|
}
|
|
m_DXEffect[rcIndex]->Release();
|
|
m_DXEffect[rcIndex] = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Registering
|
|
//-----------------------------------------------------------------------------
|
|
//-----------------------------------------------------------------------------
|
|
CKSTRING RCKShaderDX8::GetClassName()
|
|
{
|
|
return "Shader";
|
|
}
|
|
|
|
void RCKShaderDX8::_UpdateInternalTechnique(){
|
|
|
|
#ifndef _XBOX
|
|
const int rcCount = m_DXEffect.Size();
|
|
for( int rcIndex=0 ; rcIndex<rcCount ; ++rcIndex ){
|
|
if(m_DXEffect[rcIndex]){
|
|
HRESULT res = m_DXEffect[rcIndex]->SetTechnique((D3DXHANDLE)m_CurrTechnique->handle[rcIndex]);
|
|
XASSERT(res == D3D_OK);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
|