#include "stdafx.h" #ifdef _XBOX #include #include BOOL gRestoreConstantMode = FALSE; template int GetRefCount(T* t){ t->AddRef(); return t->Release(); } #endif #include "RCKShaderDX8.h" #include "ShaderManagerDX8.h" #include "..\..\..\Render Engines\CKDX8Rasterizer\CKDX8Rasterizer.h" #include #include 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;iGetAppData(); } //----------------------------------------------------------------------------- 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 ; rcIndexRelease(); 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_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& 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 ; rcIndexpasses.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& params) { CKRenderManager* rm = m_ShaderManager->m_Context->GetRenderManager(); const int rcCount = m_DXEffect.Size(); for( int rcIndex=0 ; rcIndexm_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;iGetDword(PARAM,&idx); gRestoreConstantMode = TRUE; D3DDevice::SetShaderConstantMode(D3DSCM_192CONSTANTS/* | D3DSCM_NORESERVEDCONSTANTS*/); XGMATRIX mat; for(DWORD i = 0;iGetDword(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 ; aGetTexture( 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& 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 ; rcIndexm_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;iGetParameterDesc(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(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 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 ; rcIndexSetTechnique((D3DXHANDLE)m_CurrTechnique->handle[rcIndex]); XASSERT(res == D3D_OK); } } #endif }