//////////////////////////////////////////////////////////////// // // 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() ); }
int r3dPixelShader :: Load( const char* FName, int Type, const r3dTL::TArray <D3DXMACRO> & defines ) { R3D_ENSURE_MAIN_THREAD(); sprintf(FileName, "%s\\%s", __r3dBaseShaderPath, FName); char defines_string[256]; memset(defines_string, 0, 256); for(unsigned int i=0; i<defines.Count(); ++i) { sprintf(&defines_string[strlen(defines_string)], "%s=%s,", defines[i].Name, defines[i].Definition); } if ( !LoadBinaryCache( FName, FileName, defines_string ) ) { ID3DXBuffer* pCode; HRESULT hr; r3dTL::TArray <D3DXMACRO> definesCpy( defines ); definesCpy.PushBack(D3DXMACRO()); definesCpy[definesCpy.Count() - 1].Name = "VERTEX_SHADER"; definesCpy[definesCpy.Count() - 1].Definition = "0"; definesCpy.PushBack(D3DXMACRO()); definesCpy[definesCpy.Count() - 1].Name = "PIXEL_SHADER"; definesCpy[definesCpy.Count() - 1].Definition = "1"; definesCpy.PushBack(D3DXMACRO()); definesCpy[definesCpy.Count() - 1].Name = 0; definesCpy[definesCpy.Count() - 1].Definition = 0; r3dTL::TArray < r3dString > Includes; if( !r3dCompileShader( FileName, &definesCpy[0], "main", r3dRenderer->PixelShaderProfileName, &pCode, &Includes )) return 0; Unload(); // Create the pixel shader hr = r3dRenderer->pd3ddev->CreatePixelShader( (DWORD*)pCode->GetBufferPointer(), &m_pShader); r3dRenderer->CheckOutOfMemory( hr ) ; if( FAILED(hr) ) { r3dOutToLog("Failed to create Pixel shader '%s' : ", FileName); if(hr == D3DERR_INVALIDCALL) r3dOutToLog ("Invalid Call\n"); if(hr == E_OUTOFMEMORY) r3dOutToLog ("Out of memory\n"); if(hr == D3DERR_OUTOFVIDEOMEMORY) r3dOutToLog ("Out of Video Memory\n"); else r3dOutToLog("error: %d\n", hr); m_pShader = NULL; pCode->Release(); return 0; } #ifdef _DEBUG _r3d_mShaderMap.insert(std::pair<DWORD, std::string>((DWORD)m_pShader, FileName)); //r3dOutToLog("Shader[%x] created : %d, %s\n", m_dwShader, _iNumShaders, FileName); #endif SaveBinaryCache( FName, pCode, defines_string, Includes ); pCode->Release(); } // save macros for reloading possibility ( TODO : make optional & disabled in final build ) Macros.Resize( defines.Count() ); for( uint32_t i = 0, e = defines.Count(); i < e ; i ++ ) { ShaderMacro& macro = Macros[ i ]; const D3DXMACRO& dxmacro = defines[ i ]; macro.Name = dxmacro.Name; macro.Definition = dxmacro.Definition; } return 1; }