#include "stdafx.h" #include "RCKShader.h" #include "ShaderManager.h" #if defined(_XBOX) && (_XBOX_VER<200) #include #include #include "CKDX8Rasterizer.h" char* FourCC2String(DWORD fcc); BOOL gRestoreConstantMode = FALSE; #else #include "CKDX9Rasterizer.h" #define FourCC2String(a) (a) #endif //----------------------------------------------------------------------------- RCKShader::RCKShader(ShaderManager *man) : m_ShaderManager(man), m_CurrTechniqueIndex(-1), m_ShaderText("// Shader") #if defined(MULTIPLESHADERMANAGER) ,m_ShaderName(NULL) #endif #if DIRECT3D_VERSION<0x0900 ,m_CurrentTechnique(0) #endif { //--- Initialize the DXEffect for all render context const int rcCount = man->m_rcList.Size(); m_DXEffect.Resize(rcCount); m_DXEffect.Fill(NULL); //--- Allocate a ShaderDescriptor for each RenderContext m_ShaderDescriptor.Resize(rcCount); for( int rcIndex=0 ; rcIndexGetProtectable(), pass)) { if(m_Hide) { const XString& clearSrc = GetTextInternal(); m_Hide = FALSE; SetText(clearSrc); delete &clearSrc; } } } const XString& RCKShader::GetTextInternal() const{ CKBOOL isTagged = m_ShaderText.Contains(CKHideContentManager::GetTag()); if(isTagged||m_Hide) { return CKHideContentManager::Clarify((CKProtectable*)this, m_ShaderText); } else return m_ShaderText; } const XString& RCKShader::GetTextInternal(CK_SHADER_MANAGER_TYPE type){ CKBOOL isTagged = m_ShaderText.Contains(CKHideContentManager::GetTag()); if(isTagged||m_Hide) { return CKHideContentManager::Clarify(GetProtectable(), m_ShaderText); } else return m_ShaderText; } //----------------------------------------------------------------------------- int RCKShader::Begin( CKRenderContext* rc ) { PIXE_RENDER_L3("RCKShader::Begin"); const int rcIndex = m_ShaderManager->_GetRenderContextIndex(rc); UINT NumPasses; #if DIRECT3D_VERSION<0x0900 if(!m_CurrentTechnique){ HRESULT hr = m_DXEffect[rcIndex]->GetTechnique(0,&m_CurrentTechnique); } XASSERT(m_CurrentTechnique); D3DXTECHNIQUE_DESC tdesc; HRESULT hr = m_CurrentTechnique->GetDesc(&tdesc); NumPasses = tdesc.Passes; #else #ifdef _XBOX HRESULT hr = m_DXEffect[rcIndex]->Begin( &NumPasses, D3DXFX_DONOTSAVESTATE |D3DXFX_DONOTSAVESHADERSTATE); #else HRESULT hr = m_DXEffect[rcIndex]->Begin( &NumPasses, 0); #endif #endif // _XBOX XASSERT( SUCCEEDED(hr) ); return NumPasses; } //----------------------------------------------------------------------------- void RCKShader::BeginPass( CKDWORD Num, CKRenderContext* rc ) { PIXE_RENDER_L4("RCKShader::BeginPass"); const int rcIndex = m_ShaderManager->_GetRenderContextIndex(rc); #if DIRECT3D_VERSION<0x0900 XASSERT(m_CurrentTechnique); if(Num == 0){ UINT NumPasses; HRESULT hr = m_CurrentTechnique->Begin(&NumPasses); } HRESULT hr = m_CurrentTechnique->Pass(Num); D3DSURFACE_DESC desc; for(int i=0;i<4;i++){ LPDIRECT3DTEXTURE8 tex = NULL; D3DDevice::GetTexture(i,(D3DBaseTexture**)&tex); if(tex){ tex->GetLevelDesc(0,&desc); if(VxIsSignedFormat(desc.Format)){ D3DDevice::SetTextureStageState(i,D3DTSS_COLORSIGN,D3DTSIGN_RSIGNED | D3DTSIGN_GSIGNED | D3DTSIGN_BSIGNED); }else{ D3DDevice::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(); } } #else HRESULT hr = m_DXEffect[rcIndex]->BeginPass(Num); XASSERT(SUCCEEDED(hr)); #endif } //----------------------------------------------------------------------------- void RCKShader::EndPass( CKRenderContext* rc ) { PIXE_RENDER_L4("RCKShader::EndPass"); #if DIRECT3D_VERSION>=0x0900 const INT rcIndex = m_ShaderManager->_GetRenderContextIndex(rc); HRESULT hr = m_DXEffect[rcIndex]->EndPass(); XASSERT(SUCCEEDED(hr)); #else HRESULT hr = S_OK; if((m_ShaderManager->m_CurrentPassCount-1) == m_ShaderManager->m_CurrentPassIndex){ XASSERT(m_CurrentTechnique); if(gRestoreConstantMode){ D3DDevice::SetVertexShaderInputDirect(NULL,0,NULL); D3DDevice::SetShaderConstantMode(D3DSCM_96CONSTANTS); } m_CurrentTechnique->End(); for(int i=0;i<4;i++){ D3DDevice::SetTextureStageState(i,D3DTSS_COLORSIGN,0); D3DDevice::SetTexture(i,NULL); } } #endif // _XBOX } //----------------------------------------------------------------------------- void RCKShader::CommitChanges( CKRenderContext* rc ) { PIXE_RENDER_L4("RCKShader::CommitChanges"); #if DIRECT3D_VERSION>=0x0900 const int rcIndex = m_ShaderManager->_GetRenderContextIndex(rc); HRESULT hr = m_DXEffect[rcIndex]->CommitChanges(); XASSERT(SUCCEEDED(hr)); #endif // _XBOX } //----------------------------------------------------------------------------- void RCKShader::End( CKRenderContext* rc ) { PIXE_RENDER_L3("RCKShader::End"); #if DIRECT3D_VERSION<0x0900 HRESULT hr = S_OK; #else const int rcIndex = m_ShaderManager->_GetRenderContextIndex(rc); HRESULT hr = m_DXEffect[rcIndex]->End(); #endif // _XBOX XASSERT(SUCCEEDED(hr)); } //----------------------------------------------------------------------------- void RCKShader::SetTechnique( const XString& iTechName ) { PIXE_RENDER_L4("RCKShader::SetTechnique"); int techIndex = -1; if( !GetTechIndexByName( iTechName, techIndex ) ) return; SetTechnique( techIndex ); } //----------------------------------------------------------------------------- void RCKShader::SetTechnique( int iTechIndex ) { PIXE_RENDER_L4("RCKShader::SetTechnique"); // if(m_CurrTechniqueIndex == iTechIndex) // return; m_CurrTechniqueIndex = iTechIndex; const int rcCount = m_DXEffect.Size(); for( int rcIndex=0 ; rcIndex& meanings = m_ShaderDescriptor[rcIndex]->GetTechMeanings(); ShaderDescriptor::TechMeaning* techMeaning = meanings[ m_CurrTechniqueIndex ]; XASSERT( techMeaning!=NULL ); #if DIRECT3D_VERSION<0x0900 SAFERELEASE(m_CurrentTechnique); HRESULT hr = m_DXEffect[rcIndex]->GetTechnique(techMeaning->m_D3DHandle,&m_CurrentTechnique); #else HRESULT hr = m_DXEffect[rcIndex]->SetTechnique( techMeaning->m_D3DHandle ); #endif // _XBOX XASSERT(SUCCEEDED(hr)); } } //----------------------------------------------------------------------------- int RCKShader::GetTechniquesCount() const { //--- Same count for all render context if( !m_ShaderDescriptor.Size() ) return 0; return m_ShaderDescriptor[0]->GetTechMeanings().Size(); } //----------------------------------------------------------------------------- bool RCKShader::GetTechIndexByName( const XString& iTechName, int& oPos ) const { //--- Tech Name Should be the same for all Render Contexts if( !m_ShaderDescriptor.Size() ) return false; oPos = m_ShaderDescriptor[0]->GetTechIndexByName( iTechName ); if( oPos == -1 ) return false; return true; } //----------------------------------------------------------------------------- void RCKShader::GetTechniqueInfo( int iTechIndex, TechniqueInfo& oTechInfo ) const { if( !m_ShaderDescriptor.Size() ) return; XArray& techMeanings = m_ShaderDescriptor[0]->GetTechMeanings(); ShaderDescriptor::TechMeaning& techMeaning = *techMeanings[ iTechIndex ]; oTechInfo.name = FourCC2String(techMeaning.m_TechDesc.Name); oTechInfo.desc = techMeaning.m_DescStr; oTechInfo.isValid = techMeaning.m_Validated; } //----------------------------------------------------------------------------- bool RCKShader::FindNextValidTechnique( int& ioTechIndex, XString* oTechName ) const { if( !m_ShaderDescriptor.Size() ) return false; //--- Use Shader Descriptor of Render Context 0 (validation should be the same for all RC) ShaderDescriptor::Shader& shaderDescriptor = *m_ShaderDescriptor[0]; //--- Parse all technique from the given one TechniqueInfo techInfo; int techIndex = ioTechIndex; if( techIndex == -1 ) techIndex = 0; const int techCount = GetTechniquesCount(); for( ; techIndexGetDefaultShader() ) return 1; if( !m_ShaderDescriptor.Size() ) return 0; XArray& techMeanings = m_ShaderDescriptor[0]->GetTechMeanings(); ShaderDescriptor::TechMeaning& techMeaning = *techMeanings[ iTechIndex ]; return techMeaning.m_Passes.Size(); } //----------------------------------------------------------------------------- void RCKShader::GetPassInfo( int iTechIndex, int iPassIndex, PassInfo& oPassInfo ) const { if( !m_ShaderDescriptor.Size() ) return; //--- Should be the same for RC0 than for other RC XArray& techMeanings = m_ShaderDescriptor[0]->GetTechMeanings(); ShaderDescriptor::TechMeaning& techMeaning = *techMeanings[ iTechIndex ]; ShaderDescriptor::PassMeaning& passMeaning = *techMeaning.m_Passes[ iPassIndex ]; oPassInfo.name = FourCC2String(passMeaning.m_PassDesc.Name); oPassInfo.desc = passMeaning.m_DescStr; } //----------------------------------------------------------------------------- bool RCKShader::GetPassIndexByName( int iTechIndex, const char* iPassName, int& oPos ) const { if( !m_ShaderDescriptor.Size() ) return false; //--- Should be the same for RC0 than for other RC XArray& techMeanings = m_ShaderDescriptor[0]->GetTechMeanings(); ShaderDescriptor::TechMeaning& techMeaning = *techMeanings[ iTechIndex ]; //--- Find index of given technique int passIndex = techMeaning.GetPassIndexByName( iPassName ); //--- Cannot find the given pass if( passIndex == -1 ) return false; oPos = passIndex; return true; } //----------------------------------------------------------------------------- // Effect parameters feature //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Execute Exposed Params Meanings void RCKShader::SetParameters(const XArray& params) { PIXE_RENDER_L4("RCKShader::SetParameters"); CKRenderManager* rm = m_ShaderManager->m_Context->GetRenderManager(); const int rcCount = m_DXEffect.Size(); for( int rcIndex=0 ; rcIndexm_rcList[rcIndex]; ShaderDescriptor::MeaningProcessingInfo MPI( NULL, NULL, m_DXEffect[rcIndex], rc, NULL, m_ShaderDescriptor[rcIndex], NULL ); for (int i = 0; i < params.Size(); ++i) { CKParameterLocal* param = params[i]; ShaderDescriptor::ExposedParamMeaning* exposedParamMeaning = m_ShaderManager->_GetRegisteredParamMeaning( param, rcIndex ); if( !exposedParamMeaning ) continue; MPI.param = param; exposedParamMeaning->ProcessCallBack( MPI ); } } } //----------------------------------------------------------------------------- // Execute Params Meanings (non-exposed) // called by SetValuesOfUsedAutomatics() // void RCKShader::ExecuteMeanings( CK3dEntity* iEnt, CKMaterial* iMat, CKMaterialShader* iMatShader, CKRenderContext* iRC ) { PIXE_RENDER_L4("RCKShader::ExecuteMeanings"); const int rcIndex = m_ShaderManager->_GetRenderContextIndex( iRC ); ShaderDescriptor::MeaningProcessingInfo mpi( iEnt, iMat, m_DXEffect[rcIndex], iRC, iMatShader, m_ShaderDescriptor[rcIndex], NULL ); m_ShaderDescriptor[rcIndex]->ExecuteMeanings( mpi ); } //----------------------------------------------------------------------------- void RCKShader::ExecutePerPassMeanings( CK3dEntity* iEnt, CKMaterial* iMat, CKMaterialShader* iMatShader, CKRenderContext* iRC ) { PIXE_RENDER_L4("RCKShader::ExecutePerPassMeanings"); const int rcIndex = m_ShaderManager->_GetRenderContextIndex( iRC ); ShaderDescriptor::MeaningProcessingInfo mpi( iEnt, iMat, m_DXEffect[rcIndex], iRC, iMatShader, m_ShaderDescriptor[rcIndex], NULL ); m_ShaderDescriptor[rcIndex]->ExecutePerPassMeanings( mpi ); } //----------------------------------------------------------------------------- int RCKShader::GetAutoParameterCount( CKRenderContext* rc ) { const int rcIndex = m_ShaderManager->_GetRenderContextIndex(rc); if( !m_ShaderDescriptor[rcIndex] ) return 0; return m_ShaderDescriptor[rcIndex]->GetParamMeanings().Size(); } //----------------------------------------------------------------------------- int RCKShader::GetExposedParameterCount( CKRenderContext* rc ) { const int rcIndex = m_ShaderManager->_GetRenderContextIndex(rc); if( !m_ShaderDescriptor[rcIndex] ) return 0; return m_ShaderDescriptor[rcIndex]->GetExposedParamMeanings().Size(); } //----------------------------------------------------------------------------- void RCKShader::GetAutoParameterInfo( int paramIndex, ParamInfo& paramInfo, CKRenderContext* rc ) { const int rcIndex = m_ShaderManager->_GetRenderContextIndex(rc); if( !m_ShaderDescriptor[rcIndex] ) return; XArray& paramMeanings = m_ShaderDescriptor[rcIndex]->GetParamMeanings(); paramInfo.name = FourCC2String(paramMeanings[paramIndex]->m_ParamDesc.Name); } //----------------------------------------------------------------------------- void RCKShader::GetExposedParameterInfo( int paramIndex, ParamInfo& paramInfo, CKRenderContext* rc ) { const int rcIndex = m_ShaderManager->_GetRenderContextIndex(rc); if( !m_ShaderDescriptor[rcIndex] ) return; XArray& exposedParamMeanings = m_ShaderDescriptor[rcIndex]->GetExposedParamMeanings(); paramInfo.name = FourCC2String(exposedParamMeanings[paramIndex]->m_ParamDesc.Name); paramInfo.guid = exposedParamMeanings[paramIndex]->m_Guid; } //----------------------------------------------------------------------------- bool RCKShader::LinkParameters(int& CompID, XArray& params, CKBOOL cleanup) { //--- If comes from the same compilation, nothing to do. if( CompID == m_CompID ) return false; //--- Updates the compilation id. CompID = m_CompID; CKRenderManager* rm = m_ShaderManager->m_Context->GetRenderManager(); const int rcCount = m_DXEffect.Size(); for( int rcIndex=0 ; rcIndexm_rcList[rcIndex]; VxDirectXData *dat = rc->GetDirectXInfo(); //--- Set index of the CKParam* to the corresponding ExposedParamMeaning*, ///// and remove CKParam* that doesn't appear anymore in the shader code. ParamInfo pInfo; int ckParamCount = params.Size(); for( int ip=0; ipGetName(); ShaderDescriptor::ExposedParamMeaning* paramMeaning = m_ShaderDescriptor[rcIndex]->GetParamMeaningByName( name ); //--- If parameter is found... if( paramMeaning ){ CKGUID prevGUID = p->GetGUID(); //--- If its guid has changed (for example because its annotation has changed) ///// then change its type if( !paramMeaning->m_Guid.IsValid() || prevGUID != paramMeaning->m_Guid ) { p->SetGUID( paramMeaning->m_Guid ); } //--- Kindly update UI for FLOATSLIDER because update UIMin and UIMax ///// may have changed in the shader code if( paramMeaning->m_Guid == CKPGUID_FLOATSLIDER ){ float valueToKeep = *(float*)p->GetWriteDataPtr(); ShaderDescriptor::MeaningProcessingInfo mpi( NULL, NULL, m_DXEffect[rcIndex], NULL, NULL, NULL, p ); paramMeaning->CopyDefaultValueFromShaderToParamCB( mpi ); //--- UIMin and UIMax have been change, but we don't want the Value ///// to change so restore the previous one *(float*)p->GetWriteDataPtr() = valueToKeep; } //--- Link the ExposedMeaning* this name-matching CKParam* m_ShaderManager->_RegisterExposedParameterMeaning( params[ip], paramMeaning, rcIndex ); } else { //--- Destroy params which name does not match ///// any Exposed Meaning, and remove them from input list m_ShaderManager->m_Context->DestroyObject( p, CK_DESTROY_NONOTIFY ); m_ShaderManager->_UnregisterExposedParameter( p ); params.RemoveAt(ip); --ip; --ckParamCount; } } //--- Now parse all ExposedMeaning* and create new CKParam* ///// if there wasn't any CKParam* associated with the ExposedMeaning* XArray& exposedMeanings = m_ShaderDescriptor[rcIndex]->GetExposedParamMeanings(); const int exposedMeaningCount = exposedMeanings.Size(); for( int exposedMeaningIndex=0 ; exposedMeaningIndex_GetRegisteredParamMeaning( p, rcIndex ) == exposedMeaning ) { found=true; //--- Ensure parameter is located at the natural position if( paramIndex != exposedMeaningIndex ){ //--- And if not, then move it to the desired position params.Move( ¶ms[exposedMeaningIndex], ¶ms[paramIndex] ); } break; } } //--- No CKParam* linked to the ExposedMeaning*, so create one if( !found ){ //--- So let's create a new CKParameter CKParameterLocal* p = m_ShaderManager->m_Context->CreateCKParameterLocal( (char*)FourCC2String(exposedMeaning->m_ParamDesc.Name), exposedMeaning->m_Guid ); //--- Insert it in the CKParameter array at the natural position if possible if( params.Size() > exposedMeaningIndex ){ params.Insert( exposedMeaningIndex, p ); } else { params.PushBack(p); } m_ShaderManager->_RegisterExposedParameterMeaning( p, exposedMeaning, rcIndex ); //--- We must register the parameter for the others handles ///// of all other render context, to make sure no other local param ///// will be created (as we must have only 1 ckparam for all RCs) for( int otherRCIndex=0 ; otherRCIndex& exposedMeaningsOfOtherRC = m_ShaderDescriptor[otherRCIndex]->GetExposedParamMeanings(); ShaderDescriptor::ExposedParamMeaning* meaningOfOtherRC = exposedMeaningsOfOtherRC[ exposedMeaningIndex ]; m_ShaderManager->_RegisterExposedParameterMeaning( p, meaningOfOtherRC, otherRCIndex ); } //--- While we are at it, tries to give the brand new parameter ///// the same value as the one in the shader. ///// Note: In principle, for the CopyDefaultValue callback we only need ///// to provide the FX and the CKParam ShaderDescriptor::MeaningProcessingInfo mpi( NULL, NULL, m_DXEffect[rcIndex], NULL, NULL, NULL, p ); exposedMeaning->CopyDefaultValueFromShaderToParamCB( mpi ); } } } return true; } //----------------------------------------------------------------------------- bool RCKShader::LinkTechnique( int& CompID, const XString& iTechName, BOOL iFNVT, int& oTechIndex ) { //--- If comes from the same compilation, nothing to do. if( CompID == m_CompID ) return false; //--- Updates the compilation id. CompID = m_CompID; //--- Retrieves Technique index From Name if( !GetTechIndexByName( iTechName, oTechIndex ) ) return false; //--- Finds the next valid technique. if( iFNVT ){ return FindNextValidTechnique( oTechIndex ); } return true; } //----------------------------------------------------------------------------- // Compiling //----------------------------------------------------------------------------- void RCKShader::Compile(CKContext* Context) { XClassArray output; m_ShaderManager->CompileShader(this, output); } //----------------------------------------------------------------------------- void RCKShader::_AddRenderContextSlot() { //--- Add a D3DXEffect slot m_DXEffect.PushBack( NULL ); ///// Also add a ShaderDescriptor slot ShaderDescriptor::Shader* shaderDescriptorForThisRenderContext = new ShaderDescriptor::Shader; m_ShaderDescriptor.PushBack( shaderDescriptorForThisRenderContext ); } //----------------------------------------------------------------------------- void RCKShader::_RemoveRenderContextSlot( int iRCIndex ) { //--- Remove dxEffect for this rcIndex XArray& dxEffectArray = m_DXEffect; dxEffectArray.RemoveAt( iRCIndex ); //--- Remove also the ShaderDescriptor delete m_ShaderDescriptor[iRCIndex]; m_ShaderDescriptor.RemoveAt( iRCIndex ); } //----------------------------------------------------------------------------- // Registering //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- CKSTRING RCKShader::GetClassName() { return "Shader"; } #if DIRECT3D_VERSION<0x0900 char* FourCC2String(DWORD fcc) { static char ret[5]; char *tmp = (char*)&fcc; ret[0] = tmp[0] ? tmp[0] : '\0'; ret[1] = tmp[1] ? tmp[1] : '\0'; ret[2] = tmp[2] ? tmp[2] : '\0'; ret[3] = tmp[3] ? tmp[3] : '\0'; ret[4] = '\0'; return ret; }; #endif