//////////////////////////////////////////////////////////////// // // CEffectTemplateImpl::CloneD3DEffect // // Clone the d3d effect // //////////////////////////////////////////////////////////////// ID3DXEffect* CEffectTemplateImpl::CloneD3DEffect ( SString& strOutStatus, bool& bOutUsesVertexShader, bool& bOutUsesDepthBuffer ) { // Clone D3DXEffect ID3DXEffect* pNewD3DEffect = NULL; LPDIRECT3DDEVICE9 pDevice = NULL; m_pD3DEffect->GetDevice ( &pDevice ); m_pD3DEffect->CloneEffect ( pDevice, &pNewD3DEffect ); if ( !pNewD3DEffect ) return NULL; // Set the same technique { D3DXHANDLE hTechnique = m_pD3DEffect->GetCurrentTechnique (); D3DXTECHNIQUE_DESC TechniqueDesc; m_pD3DEffect->GetTechniqueDesc( hTechnique, &TechniqueDesc ); pNewD3DEffect->SetTechnique ( pNewD3DEffect->GetTechniqueByName ( TechniqueDesc.Name ) ); // Output technique name strOutStatus = TechniqueDesc.Name; } // Check if any technique uses a vertex shader bOutUsesVertexShader = false; D3DXEFFECT_DESC EffectDesc; m_pD3DEffect->GetDesc ( &EffectDesc ); for ( uint i = 0 ; i < EffectDesc.Techniques ; i++ ) { D3DXHANDLE hTechnique = m_pD3DEffect->GetTechnique ( i ); D3DXTECHNIQUE_DESC TechniqueDesc; m_pD3DEffect->GetTechniqueDesc( hTechnique, &TechniqueDesc ); for ( uint i = 0 ; i < TechniqueDesc.Passes ; i++ ) { D3DXPASS_DESC PassDesc; m_pD3DEffect->GetPassDesc ( m_pD3DEffect->GetPass ( hTechnique, i ), &PassDesc ); if ( PassDesc.pVertexShaderFunction ) bOutUsesVertexShader = true; } } bOutUsesDepthBuffer = m_bUsesDepthBuffer; // Add to list of clones assert ( !MapContains ( m_CloneList, pNewD3DEffect ) ); MapInsert ( m_CloneList, pNewD3DEffect ); return pNewD3DEffect; }
bool Init(IDirect3DDevice9 *d3dev) { D3DXEFFECT_DESC desc; { D3DCAPS9 hal_caps; ZeroMemory(&hal_caps, sizeof(D3DCAPS9)); if(d3dev->GetDeviceCaps(&hal_caps)!=S_OK) return false; UINT ps_major = D3DSHADER_VERSION_MAJOR(hal_caps.PixelShaderVersion); UINT ps_minor = D3DSHADER_VERSION_MAJOR(hal_caps.PixelShaderVersion); if(ps_major<2) return false; } { LPD3DXBUFFER pErrorMsgs = NULL; if(FAILED(D3DXCreateEffectFromFile(d3dev, filename, NULL, NULL, 0, NULL, &effect, &pErrorMsgs))) { if(pErrorMsgs != NULL) { unsigned char* message = (unsigned char*)pErrorMsgs->GetBufferPointer(); { // save error log char path[ALIB_PATH]; FILE *fic; strcpy(path, root); strcat(path, "\\shaders\\_errors.txt"); fic=fopen(path, "w"); if(fic) { fprintf(fic, (char *)message); fclose(fic); } } } return false; } } if(FAILED(effect->GetDesc(&desc))) return false; { int i; for(i=0; i<(int)desc.Parameters; i++) { D3DXHANDLE hp=effect->GetParameter(NULL, i); D3DXPARAMETER_DESC descp; if(!hp) continue; if(FAILED(effect->GetParameterDesc(hp, &descp))) continue; if((descp.Class==D3DXPC_VECTOR)&&(descp.Type==D3DXPT_FLOAT)) { if(!strcmp(descp.Name, "color")) { hColor=hp; hp=NULL; } } else if((descp.Class==D3DXPC_SCALAR)&&(descp.Type==D3DXPT_FLOAT)) { if(!strcmp(descp.Name, "power")) hPower=hp; } } } if(FAILED(d3dev->CreateVertexBuffer(VBUFSIZE, 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &vb, NULL))) return false; return true; }
//////////////////////////////////////////////////////////////// // // CEffectTemplateImpl::CreateUnderlyingData // // // //////////////////////////////////////////////////////////////// void CEffectTemplateImpl::CreateUnderlyingData ( const SString& strFilename, const SString& strRootPath, SString& strOutStatus, bool bDebug ) { assert ( !m_pD3DEffect ); // Make defines bool bUsesRAWZ = CGraphics::GetSingleton ().GetRenderItemManager ()->GetDepthBufferFormat () == RFORMAT_RAWZ; std::vector < D3DXMACRO > macroList; macroList.push_back ( D3DXMACRO () ); macroList.back ().Name = "IS_DEPTHBUFFER_RAWZ"; macroList.back ().Definition = bUsesRAWZ ? "1" : "0"; macroList.push_back ( D3DXMACRO () ); macroList.back ().Name = NULL; macroList.back ().Definition = NULL; // Compile effect DWORD dwFlags = 0; // D3DXSHADER_PARTIALPRECISION, D3DXSHADER_DEBUG, D3DXFX_NOT_CLONEABLE; if ( bDebug ) dwFlags |= D3DXSHADER_DEBUG; SString strMetaPath = strFilename.Right ( strFilename.length () - strRootPath.length () ); CIncludeManager IncludeManager ( strRootPath, ExtractPath ( strMetaPath ) ); LPD3DXBUFFER pBufferErrors = NULL; HRESULT hr = D3DXCreateEffectFromFile( m_pDevice, ExtractFilename ( strMetaPath ), ¯oList[0], &IncludeManager, dwFlags, NULL, &m_pD3DEffect, &pBufferErrors ); // Handle compile errors strOutStatus = ""; if( pBufferErrors != NULL ) { strOutStatus = SStringX ( (CHAR*)pBufferErrors->GetBufferPointer() ).TrimEnd ( "\n" ); // Error messages sometimes contain the current directory. Remove that here. SString strCurrentDirectory = GetSystemCurrentDirectory(); strOutStatus = strOutStatus.ReplaceI ( strCurrentDirectory + "\\", "" ); strOutStatus = strOutStatus.ReplaceI ( strCurrentDirectory, "" ); } SAFE_RELEASE( pBufferErrors ); if( !m_pD3DEffect ) { if ( strOutStatus.empty () ) strOutStatus = SString ( "[D3DXCreateEffectFromFile failed (%08x)%s]", hr, *IncludeManager.m_strReport ); return; } // Find first valid technique D3DXHANDLE hTechnique = NULL; D3DXEFFECT_DESC EffectDesc; m_pD3DEffect->GetDesc ( &EffectDesc ); for ( uint uiAttempt = 0 ; true ; uiAttempt++ ) { SString strProblemInfo = ""; for ( uint i = 0 ; i < EffectDesc.Techniques ; i++ ) { SString strErrorExtra; D3DXHANDLE hTemp = m_pD3DEffect->GetTechnique ( i ); HRESULT hr = m_pD3DEffect->ValidateTechnique ( hTemp ); if ( SUCCEEDED( hr ) ) { // Check depth buffer rules if ( ValidateDepthBufferUsage ( hTemp, strErrorExtra ) ) { hTechnique = hTemp; break; } } // Update problem string D3DXTECHNIQUE_DESC TechniqueDesc; m_pD3DEffect->GetTechniqueDesc( hTemp, &TechniqueDesc ); strProblemInfo += SString ( "['%s' (%d/%d) failed (%08x)%s]", TechniqueDesc.Name, i, EffectDesc.Techniques, hr, *strErrorExtra ); } // Found valid technique if ( hTechnique ) break; // Error if can't find a valid technique after 2nd attempt if ( uiAttempt > 0 ) { strOutStatus = SString ( "No valid technique; [Techniques:%d %s]%s", EffectDesc.Techniques, *strProblemInfo, *IncludeManager.m_strReport ); SAFE_RELEASE ( m_pD3DEffect ); return; } // Try resetting samplers if 1st attempt failed LPDIRECT3DDEVICE9 pDevice; m_pD3DEffect->GetDevice ( &pDevice ); for ( uint i = 0 ; i < 16 ; i++ ) { pDevice->SetSamplerState ( i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); pDevice->SetSamplerState ( i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); pDevice->SetSamplerState ( i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR ); } } // Set technique m_pD3DEffect->SetTechnique( hTechnique ); // Inform user of technique name D3DXTECHNIQUE_DESC TechniqueDesc; m_pD3DEffect->GetTechniqueDesc( hTechnique, &TechniqueDesc ); strOutStatus = TechniqueDesc.Name; if ( bDebug ) { // Disassemble effect LPD3DXBUFFER pDisassembly = NULL; if ( SUCCEEDED( D3DXDisassembleEffect( m_pD3DEffect, false, &pDisassembly ) ) && pDisassembly ) { LPVOID pData = pDisassembly->GetBufferPointer(); DWORD Size = pDisassembly->GetBufferSize(); if( pData && Size ) { SString strDisassemblyContents; strDisassemblyContents.assign ( (const char*)pData, Size - 1 ); FileSave ( strFilename + ".dis", strDisassemblyContents ); } SAFE_RELEASE( pDisassembly ); } } // Copy MD5s of all loaded files m_FileMD5Map = IncludeManager.m_FileMD5Map; dassert ( !HaveFilesChanged() ); }