deargui-vpl/ref/virtools/Samples/Behaviors/Shader/Sources/RCKShaderDX8.cpp

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
}