///////////////////////////////////////////////////// // ShaderManagerDX8 ///////////////////////////////////////////////////// #include "stdafx.h" #include "RTView.h" #include "ShaderManagerDX8.h" #include "default_fxDX8.cpp" #include "CKRasterizer.h" #ifndef _XBOX #include "mCppLib.h" #endif #ifdef _XBOX #undef CompileShader #endif // need to Get The symbol D3DXCreateEffect for DX8 // Since we cannot link against D3DX8 and 9 Libs void FourCC2XString(XString& xs,DWORD fcc); DWORD XString2FourCC(XString& xs); IDirect3DDevice8* DeviceFromRC(CKRenderContext* rc){ IDirect3DDevice8*ret = NULL; VxDirectXData* dx = rc->GetDirectXInfo(); #ifdef _XBOX ret = (IDirect3DDevice8*) dx->D3DDevice; ret->AddRef(); #else ((IUnknown*)dx->D3DDevice)->QueryInterface(IID_IDirect3DDevice8,(LPVOID*)&ret); #endif return ret; } //----------------------------------------------------------------------------- ShaderManagerDX8::ShaderManagerDX8(CKContext *Context) : CKShaderManager(Context,ShaderManagerGUID,"Shader Manager DX8"), m_NextCompID(1) { Context->RegisterNewManager(this); #ifndef _XBOX char filename[512]; GetModuleFileName(NULL, filename, 512); int c = strlen(filename); while (c >= 0 && filename[c] != '\\') --c; filename[c] = '\0'; m_FXCCommand = filename; m_FXCCommand += "\\fxc.exe"; m_FXPCommand = filename; m_FXPCommand += "\\fxp.exe"; m_XBECCommand = filename; m_XBECCommand += "\\xbec.exe"; #endif } //----------------------------------------------------------------------------- ShaderManagerDX8::~ShaderManagerDX8() { } CKERROR ShaderManagerDX8::OnCKEnd(){ return CK_OK; } //----------------------------------------------------------------------------- D3DXHANDLE ShaderManagerDX8::_FindAutomaticParameter( CKShader& rfx, ShaderAutomaticParameter index, CKRenderContext* rc ) { RCKShaderDX8& nrfx = (RCKShaderDX8&) rfx; int rcIndex = _GetRenderContextIndex(rc); assert( rcIndex>=0 ); assert( nrfx.m_DXEffect[rcIndex] ); ShaderAutomaticInfoDX8& sai = GetRegAutomaticInfo( index ); D3DXPARAMETER_DESC desc; #ifdef _XBOX // No search By Name on XBOX need // Try With dName ? // Otherwise Iterate on all parameters to find the good one int count = rfx.GetParameterCount(rc); HRESULT res = E_FAIL; for(int i=0;iGetParameterDesc(i,&desc); if(res == S_OK){ if(desc.Name == sai.m_dName){ break; } } res = E_FAIL; } #else HRESULT res = nrfx.m_DXEffect[rcIndex]->GetParameterDesc(sai.m_name.CStr(),&desc); #endif if(res == S_OK){ if (desc.Type != sai.m_d3dType){ m_Context->OutputToConsoleEx("Error : The parameter with %4s " "semantic has an incorrect type.", &sai.m_name); }else{ #ifdef _XBOX return desc.Name; #else return sai.m_name.CStr(); #endif } } return NULL; } //----------------------------------------------------------------------------- void ShaderManagerDX8::BeginShaders(CKRenderContext* rc) { assert(IsSupported()); // Tell the rasterizer context we're in shader mode rc->GetRasterizerContext()->m_ShaderInUse = TRUE; m_DefaultShader = GetDefaultShaderI(); m_DefaultShader->Begin(rc); m_DefaultShader->BeginPass(0,rc); m_DefaultShader->EndPass(rc); IDirect3DDevice8* dev = DeviceFromRC(rc); if(dev){ dev->SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL|D3DFVF_TEX0); dev->SetPixelShader(NULL); dev->Release(); } } //----------------------------------------------------------------------------- void ShaderManagerDX8::EndShaders(CKRenderContext* rc) { m_DefaultShader->End(rc); // Tell the rasterizer context we're in not shader mode rc->GetRasterizerContext()->m_ShaderInUse = FALSE; rc->GetRasterizerContext()->FlushCaches(); rc->GetRasterizerContext()->DisableAllTextureStages(); IDirect3DDevice8* dev = DeviceFromRC(rc); if(dev){ dev->SetVertexShaderInputDirect(NULL,0,NULL); dev->SetVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL|D3DFVF_TEX0); dev->SetPixelShader(NULL); dev->Release(); } } //----------------------------------------------------------------------------- void ShaderManagerDX8::_RegisterAutomatics(){ //--- Add here the information of the new register automatics ///// Automatics standard _SetRegAutomaticInfo( FXAP_WVP, "mWVP", D3DXPT_MATRIX, sizeof(VxMatrix), "World View Projection" ); _SetRegAutomaticInfo( FXAP_WORLD, "mWOR", D3DXPT_MATRIX, sizeof(VxMatrix), "World Matrix" ); _SetRegAutomaticInfo( FXAP_VIEW, "mVIE", D3DXPT_MATRIX, sizeof(VxMatrix), "View Matrix" ); _SetRegAutomaticInfo( FXAP_WORLDVIEW, "mWVI", D3DXPT_MATRIX, sizeof(VxMatrix), "WorldView Matrix" ); _SetRegAutomaticInfo( FXAP_VIEWPROJ, "mVPR", D3DXPT_MATRIX, sizeof(VxMatrix), "ViewProj Matrix" ); _SetRegAutomaticInfo( FXAP_PROJECTION,"mPRO", D3DXPT_MATRIX, sizeof(VxMatrix), "Projection Matrix" ); _SetRegAutomaticInfo( FXAP_EYEPOS, "vEPO", D3DXPT_VECTOR, sizeof(VxVector), "Virtools camera position" ); ///// Automatics for 3dentity _SetRegAutomaticInfo( FXAP_OBJECTPOS, "vPOS", D3DXPT_VECTOR, sizeof(VxVector), "Virtools object's position" ); ///// Automatics for materials _SetRegAutomaticInfo( FXAP_DIFFUSE, "vDIF", D3DXPT_VECTOR, sizeof(VxColor), "- as a Virtools semantic: Virtools material's diffuse color\n" "- as render state: renderstate enum standing for diffuse stage\n" "- as a Vertex Shader Input semantic: the input vertex diffuse color" ); _SetRegAutomaticInfo( FXAP_EMISSIVE, "vEMI", D3DXPT_VECTOR, sizeof(VxColor), "Virtools material's emissive color" ); _SetRegAutomaticInfo( FXAP_SPECULAR, "vSPE", D3DXPT_VECTOR, sizeof(VxColor), "- as a Virtools semantic: Virtools material's specular color\n" "- as a VS input semantic: the input vertex specular color" ); _SetRegAutomaticInfo( FXAP_AMBIENT, "vAMB", D3DXPT_VECTOR, sizeof(VxColor), "Virtools material's ambient color" ); _SetRegAutomaticInfo( FXAP_POWER, "fPOW", D3DXPT_FLOAT, sizeof(float), "Virtools material's power\n" ); _SetRegAutomaticInfo( FXAP_TEXTURE, "tTEX", D3DXPT_TEXTURE, 0, "- as a Virtools semantic: Virtools material's texture\n" "- as render state: renderstate enum standing for texture stage" ); ///// Automatics for global stuff _SetRegAutomaticInfo( FXAP_TIME, "fTIM", D3DXPT_VECTOR, 4*sizeof(float), "x = Seconds elapsed since Virtools play event occured ( in seconds)\n" "y = sin(x)\n" "z = cos(x)\n" "w = 1" ); //--- Channel's Automatic char SemanticName[16]; char SemanticDesc[128]; for( int a=0 ; a<4 ; ++a ){ sprintf( SemanticName, "TEX%d", a ); sprintf( SemanticDesc, "Virtools texture of channel %d of current mesh", a); _SetRegAutomaticInfo( (ShaderAutomaticParameter)(FXAP_TEXTURE0+a), SemanticName, D3DXPT_TEXTURE, 0, SemanticDesc ); } _SetRegAutomaticInfo( FXAP_PASSCOUNT, "PASC", D3DXPT_FLOAT, sizeof(float), "shader's pass count." ); _SetRegAutomaticInfo( FXAP_PASSINDEX, "PASI", D3DXPT_FLOAT, sizeof(float), "Current rendering pass index." ); _SetRegAutomaticInfo( FXAP_BONES, "mBON", D3DXPT_DWORD, sizeof(int), "First Register index that can be used to store bones matrices." ); _SetRegAutomaticInfo( FXAP_TBONES, "mTBO", D3DXPT_DWORD, sizeof(int), "First Register index that can be used to store transformed bones matrices." ); _SetRegAutomaticInfo( FXAP_BONESINDEXCONSTANT, "vBIC", D3DXPT_DWORD, sizeof(int), "Constant needed to convert D3DColor packed bones index to index." ); /* _SetRegAutomaticInfo( FXAP_VIEWPORTOFFSET, "vVOF", D3DXPT_VECTOR, sizeof(VxVector4), "Viewport Offset." ); _SetRegAutomaticInfo( FXAP_VIEWPORTSCALE, "vVSC", D3DXPT_VECTOR, sizeof(VxVector4), "Viewport Scale." ); */ } void ShaderManagerDX8::SetRegAutomaticName( ShaderAutomaticParameter index, const XString& iName ) { m_RegisteredAutomatics[index].m_name = iName; } XString& ShaderManagerDX8::GetRegAutomaticName( ShaderAutomaticParameter index, int NameIndex ) { static XString unregistred(""); if(0 ==NameIndex) return m_RegisteredAutomatics[index].m_name; else return unregistred; } XString& ShaderManagerDX8::GetRegAutomaticDesc( ShaderAutomaticParameter index ) { static XString empty(""); #ifdef _XBOX return empty; #else return m_RegisteredAutomatics[index].m_desc; #endif } void ShaderManagerDX8::_SetRegAutomaticInfo( ShaderAutomaticParameter index, const XString& iName, D3DXPARAMETERTYPE iD3DType, int iTypeSize, const char* iDesc ) { //--- Init all relevant members m_RegisteredAutomatics[index].m_name = iName; m_RegisteredAutomatics[index].m_d3dType = iD3DType; #ifdef _XBOX m_RegisteredAutomatics[index].m_dName = XString2FourCC(m_RegisteredAutomatics[index].m_name); #else m_RegisteredAutomatics[index].m_typeSize = iTypeSize; m_RegisteredAutomatics[index].m_desc = iDesc; #endif } void ShaderManagerDX8::_SetRegAutomaticInfo( ShaderAutomaticParameter index, const ShaderAutomaticInfoDX8& iSai ) { m_RegisteredAutomatics[index] = iSai; } ShaderAutomaticInfoDX8& ShaderManagerDX8::GetRegAutomaticInfo( ShaderAutomaticParameter index ) { return m_RegisteredAutomatics[index]; } BOOL ShaderManagerDX8::IsAutomatic( const D3DXPARAMETER_DESC& desc ) const { for( int a=0 ; a=0 ); for (int i = 0; i < m_AllShaders.Size(); ++i) { CompileShader(m_AllShaders[i], m_Output); } } //----------------------------------------------------------------------------- void ShaderManagerDX8::OnDestroyDevice(CKRenderContext* rc) { int rcIndex = _GetRenderContextIndex(rc); if ( rcIndex>=0 ) { for (int i = 0; i < m_AllShaders.Size(); ++i) { ((RCKShaderDX8*)m_AllShaders[i])->ReleaseDxEffect(rcIndex); } } } //----------------------------------------------------------------------------- void ShaderManagerDX8::OnLostDevice(CKRenderContext* rc) { // No device lost on Xbox #ifndef _XBOX int rcIndex = _GetRenderContextIndex(rc); for (int i = 0; i < m_AllShaders.Size(); ++i) if (((RCKShaderDX8*)m_AllShaders[i])->m_DXEffect[rcIndex]) { HRESULT hr = ((RCKShaderDX8*)m_AllShaders[i])->m_DXEffect[rcIndex]->OnLostDevice(); assert(SUCCEEDED(hr)); } #endif } //----------------------------------------------------------------------------- void ShaderManagerDX8::OnResetDevice(CKRenderContext* rc) { // No Reset Device On Xbox #ifndef _XBOX int rcIndex = _GetRenderContextIndex(rc); for (int i = 0; i < m_AllShaders.Size(); ++i) if (((RCKShaderDX8*)m_AllShaders[i])->m_DXEffect[rcIndex]) { HRESULT hr = ((RCKShaderDX8*)m_AllShaders[i])->m_DXEffect[rcIndex]->OnResetDevice(); assert(SUCCEEDED(hr)); } #endif } //----------------------------------------------------------------------------- CKERROR ShaderManagerDX8::PreClearAll() { CKShaderManager::PreClearAll(); for (int i = 0; i < m_AllShaders.Size(); ++i) delete m_AllShaders[i]; m_AllShaders.Clear(); m_DefaultShader = NULL; return CK_OK; } //----------------------------------------------------------------------------- CKERROR ShaderManagerDX8::PostClearAll() { return CK_OK; } //----------------------------------------------------------------------------- CKShader* ShaderManagerDX8::CreateShader( const XString* name, const XString* text, BOOL uniqueName ) { RCKShaderDX8* fx = new RCKShaderDX8(this); //--- Make Shader Fx name unique. This is needed because for example, ///// the material combo box gets the shader fx by its name. XString wantedName = name? *name:"New Shader"; if( uniqueName ){ XString extName = ""; BOOL nameIsUnique = FALSE; for( int a=1 ; ; ++a ){ CKShader* sameNameFx = GetShaderByName( wantedName+extName ); if( !sameNameFx ) break; extName.Format( "%d", a ); } wantedName += extName; } fx->SetName( wantedName ); //--- Set default text fx->SetText(text ? *text : "technique tech\r\n{\r\n\tpass p\r\n\t{\r\n\t}\r\n}\r\n"); m_AllShaders.PushBack(fx); return fx; } //----------------------------------------------------------------------------- CKShader* ShaderManagerDX8::CreateShaderFromFile(const CKSTRING filename) { VxFile f; if (f.Open(filename, VxFile::TEXTREADONLY)) { int size = f.Size(); XString s; s.Resize(size); int sread = 0; while (sread < size) { f.Read(&s[sread], 1024); sread += 1024; } // Extract Shader name int end = strlen(filename); while (end > 0 && filename[end] != '.') --end; int start = strlen(filename); while (start > 0 && filename[start] != '\\') --start; XString name; if (start < end && end != 0) { if (start) start++; name.Resize(end - start); strncpy(name.Str(), &filename[start], end - start); } else name = filename; // Creates the Shader. CKShader* fx = CreateShader(&name, &s); return fx; } return NULL; } //----------------------------------------------------------------------------- bool ShaderManagerDX8::SaveShaderToFile(const XString& filename, CKShader* fx) { _WriteStringToFile(filename, fx->GetText()); return true; } //----------------------------------------------------------------------------- CKBOOL ShaderManagerDX8::IsSupported() const { CKRenderManager* rm = m_Context->GetRenderManager(); CKRenderContext* rc = rm->GetRenderContext(0); VxDirectXData* dx = rc->GetDirectXInfo(); // Check Direct X Version if (dx && dx->DxVersion >= 0x0800 && dx->DxVersion < 0x0900) return TRUE; return FALSE; } CKBOOL ShaderManagerDX8::IsSupportedAndWarnIfNot() { const CKBOOL isSupported = IsSupported(); if( !isSupported ){ m_Output.PushBack("Rasterizer does not support Shader FXs (use DirectX 8 or better)"); } return isSupported; } //----------------------------------------------------------------------------- void ShaderManagerDX8::GetVSPSVersion(float& vs, float& ps) const { #ifdef _XBOX vs = 1.1f; ps = 1.1f; #else CKRenderManager* rm = m_Context->GetRenderManager(); CKRenderContext* rc = rm->GetRenderContext(0); VxDirectXData* dx = rc->GetDirectXInfo(); // Check Direct X Version if (dx && dx->DxVersion >= 0x0800 && dx->DxVersion < 0x0900) { D3DCAPS8 caps; memset(&caps,0,sizeof(caps)); IDirect3DDevice8* dev8 = NULL; ((IUnknown*)dx->D3DDevice)->QueryInterface(IID_IDirect3DDevice8,(LPVOID*)&dev8); XASSERT(dev8); dev8->GetDeviceCaps(&caps); dev8->Release(); DWORD Major = (caps.VertexShaderVersion & 0xFF00) >> 8; DWORD Minor = (caps.VertexShaderVersion & 0xFF); if (Minor <= 10) Minor *= 10; if (Minor <= 10) Minor *= 10; vs = (float)Major + (float)Minor * 0.01f; Major = (caps.PixelShaderVersion & 0xFF00) >> 8; Minor = (caps.PixelShaderVersion & 0xFF); if (Minor <= 10) Minor *= 10; if (Minor <= 10) Minor *= 10; ps = (float)Major + (float)Minor * 0.01f; } #endif } //----------------------------------------------------------------------------- CKShader* ShaderManagerDX8::GetShaderByName(const XBaseString& name) { for (int i = 0; i < m_AllShaders.Size(); ++i) if (m_AllShaders[i]->GetName() == name) return m_AllShaders[i]; return NULL; } //----------------------------------------------------------------------------- int ShaderManagerDX8::GetNumShaders() const { return m_AllShaders.Size(); } //----------------------------------------------------------------------------- CKShader* ShaderManagerDX8::GetShader(int pos) { return m_AllShaders[pos]; } //----------------------------------------------------------------------------- void ShaderManagerDX8::DeleteShader(CKShader* fx) { m_AllShaders.Remove(fx); if (fx == m_DefaultShader) m_DefaultShader = NULL; delete fx; } //----------------------------------------------------------------------------- bool ShaderManagerDX8::CompileShader(CKShader* fx, XClassArray &output) { RCKShaderDX8& rfx = *(RCKShaderDX8*)fx; CKRenderManager* rm = m_Context->GetRenderManager(); const int rcCount = m_rcList.Size(); for( int rcIndex=0 ; rcIndexGetDirectXInfo(); if (dx && dx->DxVersion >= 0x0800 && dx->DxVersion < 0x0900) { ID3DXBuffer* Error = NULL; const XString& Text = rfx.GetText(); ID3DXEffect* oldfx = rfx.m_DXEffect[rcIndex]; // Creates a simple Shader #ifdef _XBOX ID3DXBuffer* compiledEffect = NULL; HRESULT hr = E_FAIL; try{ hr = D3DXCompileEffect(Text.CStr(), Text.Length(),&compiledEffect,&Error); } catch(...){ } if(hr == D3D_OK){ hr = D3DXCreateEffect((IDirect3DDevice8*)dx->D3DDevice, compiledEffect->GetBufferPointer(),compiledEffect->GetBufferSize(),0, &rfx.m_DXEffect[rcIndex]); } if(compiledEffect) compiledEffect->Release(); if (Error != NULL && Error->GetBufferSize()){ XStringTokenizer tokizer((char*)Error->GetBufferPointer(), "\n"); const char *tok = NULL; while ((tok = tokizer.NextToken(tok)) != NULL){ if(strlen(tok) < 12) continue; output.PushBack(rfx.GetName() + XString(tok)); } } if(Error) Error->Release(); #else IDirect3DDevice8* dev8 = NULL; ((IUnknown*)dx->D3DDevice)->QueryInterface(IID_IDirect3DDevice8,(LPVOID*)&dev8); XASSERT(dev8); // Do Preprocesing Stuff. //mCppLib_Define("D3DX_VERSION","0x0801"); //mCppLib_Define("DIRECT3D_VERSION","0x0801"); XString PreProcessed; XString PreProcErr; HRESULT hr = mCppLib_PreProcess(Text,"-D D3DX_VERSION=0x0801 -D DIRECT3D_VERSION=0x0801" ,PreProcessed,PreProcErr); if(hr && PreProcErr.Length()){ // an error occurred during preprocessing XStringTokenizer tokizer(PreProcErr.CStr(), "\n"); const char *tok = NULL; while ((tok = tokizer.NextToken(tok)) != NULL) output.PushBack(rfx.GetName() + XString(" ") + XString(tok)); }else{ hr = D3DXCreateEffect(dev8,PreProcessed.CStr(), PreProcessed.Length(),&rfx.m_DXEffect[rcIndex], &Error); } dev8->Release(); if (Error != NULL && Error->GetBufferSize()){ XStringTokenizer tokizer((char*)Error->GetBufferPointer(), "\n"); const char *tok = NULL; while ((tok = tokizer.NextToken(tok)) != NULL) output.PushBack(rfx.GetName() + XString(tok)); } if(Error) Error->Release(); #endif //--- Replace the old Shader with the new one if (FAILED(hr)){ rfx.m_DXEffect[rcIndex] = oldfx; output.PushBack(rfx.GetName() + ": Shader Fx compilation failed."); return FALSE; } else { output.PushBack(rfx.GetName() + ": Shader Fx compilation successfull."); if (oldfx) oldfx->Release(); rfx.m_CompID = m_NextCompID++; rfx._RetrieveTechniques(rc); //--- We don't consider automatics for the default shader. ///// In fact the default shader contain automatics just to show the ///// user how to use them if( fx != m_DefaultShader ){ for( int a=0 ; a &output, XArray& text) { CKRenderManager* rm = m_Context->GetRenderManager(); CKRenderContext* rc = rm->GetRenderContext(0); VxDirectXData* dx = rc->GetDirectXInfo(); assert(fx != NULL); #ifndef _XBOX if (!(VxFile::GetFileMode(m_FXCCommand.CStr()) & VxFile::REGULAR_FILE)) { output.PushBack("No path to fxc.exe HLSL Compiler."); return FALSE; } // Check Direct X Version if (dx && dx->DxVersion >= 0x0800 && dx->DxVersion < 0x0900) { char tmp[1024]; GetTempPath(1024, tmp); // Create an input file. XString infile; infile.Format("%sfxcin.fx", tmp); // Write XString to file. if (!_WriteStringToFile(infile, fx->GetText())) { output.PushBack("Cannot write temporary Shader Fx file."); return FALSE; } XString outfile; outfile.Format("%sfxcout.txt", tmp); XString cmd; cmd.Format("\"%s\" /T%s /E%s /Fc%s %s", m_FXCCommand.CStr(), target, funcname, outfile.CStr(), infile.CStr()); if (!_WinExec(cmd.CStr())) { output.PushBack(XString("Command execution has failed : ") + cmd); return FALSE; } if (!_ReadStringFromFile(outfile, text)) { output.PushBack("Cannot read compiled output file."); return FALSE; } } #endif return TRUE; } //----------------------------------------------------------------------------- CKShader* ShaderManagerDX8::GetDefaultShader() { return GetDefaultShaderI(); } //----------------------------------------------------------------------------- CKShader* ShaderManagerDX8::GetDefaultShaderI() { if( !m_DefaultShader ) { #if 0 //#ifdef _XBOX VxFile f; f.Open("d:\\media\\default.fx"); XASSERT(f.IsValid()); VxScratch tmp(f.Size()+1); char *txt = (char*) tmp.Mem(); f.Read(txt,f.Size()); txt[f.Size()] = '\0'; m_DefaultShader = ShaderManagerDX8::CreateShader(&XString("- default -"), &XString(txt)); #else m_DefaultShader = ShaderManagerDX8::CreateShader(&XString("- default -"), &XString(g_default)); #endif CompileShader(m_DefaultShader, m_Output); } return m_DefaultShader; } //----------------------------------------------------------------------------- CKERROR ShaderManagerDX8::LoadData(CKStateChunk *chunk,CKFile* LoadedFile) { assert(LoadedFile != 0); if (!chunk) return CKERR_INVALIDPARAMETER; chunk->StartRead(); if (chunk->SeekIdentifier(SHADERMANAGER_CHUNKID)) { // Check the version int version = chunk->ReadInt(); /* ?... I don't get the point of this... if (version != ShaderManagerDX8_SAVE_VERSION) { m_Context->OutputToConsole("Shader manager load data error : bad version"); return CK_OK; } */ // Check the flags int flags = chunk->ReadInt(); // Read Shaders int num_Shaders = chunk->ReadInt(); int chunkid = FIRSTSHADER_CHUNKID; for (int i = 0; i < num_Shaders; ++i) { chunk->SeekIdentifier(chunkid); ++chunkid; //--- If Version < 1 there's a BOOL "isDefaultFx" if( version < 2 ){ //--- Is it the default effect then don't read content CKBOOL isDefaultFx = chunk->ReadInt(); if( isDefaultFx ) continue; } //--- Read Shader Name and Text XString fxName = chunk->ReadString(); XString fxText = chunk->ReadString(); CKShader* sameNameEffect; BOOL shaderMustBeCreated = TRUE; while( sameNameEffect = GetShaderByName( fxName ) ){ //--- Skip this effect if text is the same if( !fxText.Compare( sameNameEffect->GetText()) ){ shaderMustBeCreated = FALSE; break; } //--- Otherwise rename the new effect int extCount = 1; XString originalFxName = fxName; fxName.Format( "%s %.3d", originalFxName.CStr(), extCount ); ++extCount; } if( !shaderMustBeCreated ) continue; RCKShaderDX8* fx = new RCKShaderDX8(this); fx->SetName( fxName ); fx->SetText( fxText ); m_AllShaders.PushBack(fx); m_Context->OutputToConsoleEx("Loaded Shader Fx %s.", fx->GetName().CStr()); } } //--- If the Default Shader doesn't exist GetDefaultShader will create it m_DefaultShader = GetDefaultShaderI(); if( IsSupportedAndWarnIfNot() ){ //--- Compile every loaded Shader except the default Shader ///// as it has already been compiled (cf: just above) for (int i = 0; i < m_AllShaders.Size(); ++i){ CKShader* const fx = m_AllShaders[i]; if( fx == m_DefaultShader ) continue; CompileShader( fx, m_Output ); } } chunk->CloseChunk(); return CK_OK; } //----------------------------------------------------------------------------- CKStateChunk* ShaderManagerDX8::SaveData(CKFile* SavedFile) { assert(SavedFile != 0); //--- If there's only one shader it's certainly the default shader Shader ///// and so it's not even needed to save any ShaderManagerDX8 Chunk const int toSaveCount = m_AllShaders.Size()-1; if( toSaveCount<1 ) return NULL; // Writes chunk information CKStateChunk *chunk = CreateCKStateChunk(SHADERMANAGER_CHUNKID, SavedFile); if (!chunk) return NULL; chunk->StartWrite(); chunk->WriteIdentifier(SHADERMANAGER_CHUNKID); chunk->WriteInt(SHADERMANAGER_SAVE_VERSION); chunk->WriteInt(SHADERMANAGER_FLAGS); // Writes all Shaders we want to save. chunk->WriteInt( toSaveCount ); //--- Minus the default Shader int chunkid = FIRSTSHADER_CHUNKID; for (int i = 0; i < m_AllShaders.Size(); ++i) { CKShader* const fx = m_AllShaders[i]; //--- Is it the default effect then don't write it if( fx == m_DefaultShader ) continue; chunk->WriteIdentifier(chunkid); ++chunkid; /* --- old Version ( < 2 ) // store if it's the default Shader (this becomes obsolete...) chunk->WriteInt(m_AllShaders[i] == m_DefaultShader ? TRUE : FALSE); */ // store name chunk->WriteString(m_AllShaders[i]->GetName().CStr()); // store text #ifndef _XBOX if(m_SavePreProcessed){ XString PreProcessed; XString PreProcErr; HRESULT hr = mCppLib_PreProcess(m_AllShaders[i]->GetText(),m_SavePreprocessedOptions.CStr(),PreProcessed,PreProcErr); if(S_OK == hr) chunk->WriteString(PreProcessed.CStr()); else chunk->WriteString(m_AllShaders[i]->GetText().CStr()); }else #endif { // Need to do some pre-processing to match the target chunk->WriteString(m_AllShaders[i]->GetText().CStr()); } } chunk->CloseChunk(); return chunk; } //----------------------------------------------------------------------------- BOOL ShaderManagerDX8::_ReadStringFromFile(const XString& filename, XString &s) const { //--- Read XString from file. VxFile f; if( !f.Open(filename.CStr()) ) return FALSE; int size = f.Size(); s.Resize( size ); f.Read( s.Str(), size ); f.Close(); return TRUE; } //----------------------------------------------------------------------------- BOOL ShaderManagerDX8::_WriteStringToFile(const XString& filename, const XString &s) const { VxFile f; if (!f.Open(filename.CStr(), VxFile::WRITEONLY)) return FALSE; f.Write(s.CStr(), s.Length()); f.Close(); return TRUE; } //----------------------------------------------------------------------------- BOOL _WinExec(const XString& command) { #ifdef _XBOX return FALSE; #else STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); // Start the child process. if( !CreateProcess( NULL, // No module name (use command line). const_cast(command.CStr()), // Command line. NULL, // Process handle not inheritable. NULL, // Thread handle not inheritable. FALSE, // Set handle inheritance to FALSE. CREATE_NO_WINDOW, // No creation flags. NULL, // Use parent's environment block. NULL, // Use parent's starting directory. &si, // Pointer to STARTUPINFO structure. &pi ) // Pointer to PROCESS_INFORMATION structure. ) return FALSE; // Wait until child process exits. WaitForSingleObject( pi.hProcess, INFINITE ); DWORD code = 0; GetExitCodeProcess( pi.hProcess, &code ); // Close process and thread handles. CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); return code == 0; #endif } int ShaderManagerDX8::_GetRenderContextIndex( CKRenderContext* rc ) { const int rcCount = m_rcList.Size(); for( int a=0 ; am_DXEffect.PushBack(NULL); } } void ShaderManagerDX8::OnRenderContextDestroyed( CKRenderContext* rc ) { int rcIndex = _GetRenderContextIndex(rc); assert( rcIndex>=0 ); //--- UnRegister the Render Context _RemoveRCForExposedParameters( rcIndex ); //--- Release d3deffects for this device for(int a=0; a& dxEffectArray = ((RCKShaderDX8*)m_AllShaders[a])->m_DXEffect; if( dxEffectArray[rcIndex] ){ dxEffectArray[rcIndex]->Release(); } dxEffectArray.RemoveAt(rcIndex); } //--- Remove the RC from our managed list (hash) of RCs m_rcList.Remove( rc ); } void ShaderManagerDX8::_AddRCForExposedParameters() { const int endIndex = m_paramLinker.Size(); //--- Add one rc m_paramLinker.Expand(1); //--- Set as many params for this rc as there's params defined in the hash table const int registeredParamCount = m_hashParamIndex.Size(); m_paramLinker[endIndex].Resize( registeredParamCount ); m_paramLinker[endIndex].Fill( (D3DXHANDLE)0 ); } void ShaderManagerDX8::_RemoveRCForExposedParameters( int rcIndex ) { //--- Remove the rc ///// Note: as it's a class array, it will remove also all d3dhandles fo the rc m_paramLinker.RemoveAt( rcIndex ); }