CD3D9CgMaterialRenderer::~CD3D9CgMaterialRenderer() { if (VertexProgram) { cgD3D9UnloadProgram(VertexProgram); cgDestroyProgram(VertexProgram); } if (FragmentProgram) { cgD3D9UnloadProgram(FragmentProgram); cgDestroyProgram(FragmentProgram); } /*if (GeometryProgram) { cgD3D9UnloadProgram(GeometryProgram); cgDestroyProgram(GeometryProgram); }*/ }
COpenGLCgMaterialRenderer::~COpenGLCgMaterialRenderer() { if (VertexProgram) { cgGLUnloadProgram(VertexProgram); cgDestroyProgram(VertexProgram); } if (FragmentProgram) { cgGLUnloadProgram(FragmentProgram); cgDestroyProgram(FragmentProgram); } if (GeometryProgram) { cgGLUnloadProgram(GeometryProgram); cgDestroyProgram(GeometryProgram); } }
void CCGShaderSystem::DestroyPixelShader(Resources::IPixelShader* pPS) { xst_assert( pPS, "(CCGShaderSystem::DestroyPixelShader)" ); Resources::CCGPixelShader* pShader = (Resources::CCGPixelShader*)pPS; if( pShader->m_CGShader != xst_null ) { cgDestroyProgram( pShader->m_CGShader ); } }
void csShaderGLCGCommon::PrecacheClear() { if (program != 0) { cgDestroyProgram (program); program = 0; } /*objectCode.Empty(); objectCodeCachePathArc.Empty(); objectCodeCachePathItem.Empty();*/ }
//--------------------------------------------------------------------------------- // ~FFxProgram //--------------------------------------------------------------------------------- FFxProgram::~FFxProgram() { if (mProgram /*&& !mProgramFlags.flags(FFX_PROGRAM_ERROR)*/) { cgDestroyProgram(mProgram); /* if (mSourceBuffer) delete [] mSourceBuffer; */ } }
IOGLBaseShader::~IOGLBaseShader(){ this->UnbindParameters(); this->UnbindSamplers(); if(this->m_bBinded){ this->Unbind(); } if(this->m_uProgram != 0 && cgIsProgram(this->m_uProgram)){ cgDestroyProgram(this->m_uProgram); this->m_uProgram = 0; } }
static void keyboard(unsigned char c, int x, int y) { switch (c) { case 27: /* Esc key */ /* Demonstrate proper deallocation of Cg runtime data structures. Not strictly necessary if we are simply going to exit. */ cgDestroyProgram(myCgVertexProgram); cgDestroyContext(myCgContext); exit(0); break; } }
//----------------------------------------------------------------------- void CgProgram::unloadHighLevelImpl(void) { // Unload Cg Program // Lowlevel program will get unloaded elsewhere if (mCgProgram) { cgDestroyProgram(mCgProgram); checkForCgError("CgProgram::unloadImpl", "Error while unloading Cg program " + mName + ": ", mCgContext); mCgProgram = 0; } }
static void gl_cg_deinit_progs(void) { RARCH_LOG("CG: Destroying programs.\n"); cgGLUnbindProgram(cgFProf); cgGLUnbindProgram(cgVProf); // Programs may alias [0]. for (unsigned i = 1; i < GFX_MAX_SHADERS; i++) { if (prg[i].fprg && prg[i].fprg != prg[0].fprg) cgDestroyProgram(prg[i].fprg); if (prg[i].vprg && prg[i].vprg != prg[0].vprg) cgDestroyProgram(prg[i].vprg); } if (prg[0].fprg) cgDestroyProgram(prg[0].fprg); if (prg[0].vprg) cgDestroyProgram(prg[0].vprg); memset(prg, 0, sizeof(prg)); }
//[-------------------------------------------------------] //[ Private virtual PLRenderer::Resource functions ] //[-------------------------------------------------------] void FragmentShaderCg::BackupDeviceData(uint8 **ppBackup) { // Backup data const char *pszProgram = m_pCgFragmentProgram ? cgGetProgramString(m_pCgFragmentProgram, CG_PROGRAM_SOURCE) : nullptr; if (pszProgram) { const uint32 nNumOfBytes = Wrapper::GetStringLength(pszProgram) + 1; *ppBackup = new uint8[nNumOfBytes]; MemoryManager::Copy(*ppBackup, pszProgram, nNumOfBytes); cgDestroyProgram(m_pCgFragmentProgram); m_pCgFragmentProgram = nullptr; } else { *ppBackup = nullptr; } }
void sCompileResult::Reset() { #if sCOMP_DX9_ENABLE sRelease(D3D9.CTable); sRelease(D3D9.Errors); #endif // sCOMP_DX9_ENABLE #if sCOMP_CG_ENABLE if(Cg.Program) cgDestroyProgram(Cg.Program); #endif // sCOMP_CG_ENABLE ShaderBlobs.Reset(); Valid = sFALSE; Errors = L""; }
void ObjMeshGPUDeformer::DeleteCGShaders() { if (VertexPass2Program) cgDestroyProgram(VertexPass2Program); if (VertexPass2ProgramShadow) cgDestroyProgram(VertexPass2ProgramShadow); //if (VertexPass2ProgramDeformedNormals) //cgDestroyProgram(VertexPass2ProgramDeformedNormals); if (VertexPass2ProgramPoints) cgDestroyProgram(VertexPass2ProgramPoints); if (VertexPass2ProgramEdges) cgDestroyProgram(VertexPass2ProgramEdges); if (FragmentPass2Program) cgDestroyProgram(FragmentPass2Program); if (Context) cgDestroyContext(Context); }
cgShader::~cgShader(){ SAFE_FREE(code); SAFE_FREE(vpmain); SAFE_FREE(gpmain); SAFE_FREE(fpmain); for(int k = 0; k < 3; k++){ if(cgProgram[k]){ cgDestroyProgram(cgProgram[k]); } } }
CGprogram CCGShaderSystem::CreateProgram(lpcastr lpszShaderCode, CGprofile Profile, lpcastr lpszEntryPoint, lpcastr lpszShaderName) { XST_LOG_ERR( lpszShaderCode ); CGprogram Program = cgCreateProgram( m_CGContext, CG_SOURCE, lpszShaderCode, Profile, lpszEntryPoint, xst_null ); if( XST_FAILED( this->CheckForErrors( "Program creation", lpszShaderName ) ) ) { if( Program ) { cgDestroyProgram( Program ); } return xst_null; } return Program; }
void CD3DCG::ClearPasses() { /* clean up cg programs, vertex buffers/declarations and textures from all regular passes. pass 0 is the orignal texture, so ignore that */ if(shaderPasses.size()>1) { for(std::vector<shaderPass>::iterator it=(shaderPasses.begin()+1);it!=shaderPasses.end();it++) { if(it->cgFragmentProgram) cgDestroyProgram(it->cgFragmentProgram); if(it->cgVertexProgram) cgDestroyProgram(it->cgVertexProgram); if(it->tex) it->tex->Release(); if(it->vertexBuffer) it->vertexBuffer->Release(); if(it->vertexDeclaration) it->vertexDeclaration->Release(); } } for(std::vector<lookupTexture>::iterator it=lookupTextures.begin();it!=lookupTextures.end();it++) { if(it->tex) it->tex->Release(); } for(std::deque<prevPass>::iterator it=prevPasses.begin();it!=prevPasses.end();it++) { if(it->tex) it->tex->Release(); if(it->vertexBuffer) it->vertexBuffer->Release(); } prevPasses.clear(); shaderPasses.clear(); lookupTextures.clear(); // prevPasses deque is always filled with PREV + PREV1-6 elements prevPasses.resize(7); shaderLoaded = false; }
void DestroyCg() { cgDestroyProgram(VP_DrawSites); cgDestroyProgram(FP_DrawSites); cgDestroyProgram(VP_Flood); cgDestroyProgram(FP_Flood); cgDestroyProgram(VP_FinalRender); cgDestroyProgram(FP_FinalRender); cgDestroyContext(Context); }
// keyboard callback void keyboard(unsigned char key, int x, int y) { static bool animation = false; switch (key) { case 27: // Escape case 'q': cgDestroyProgram(cg_vertex_program); cgDestroyContext(cg_context); exit(0); break; case ' ': animation = !animation; if(animation) glutIdleFunc(idle); else glutIdleFunc(NULL); break; } }
/* THE MAIN */ int main( int argc, char** argv ) { if( argc == 2 ){ char *a = argv[1]; readfile( a ); }else{ printf( "Usage: shader <filename>\n" ); exit(0); } init(argc, argv); CgInit(); glutMainLoop(); cgDestroyProgram( CgProg ); cgDestroyContext( CgCtxt ); return 0; }
bool FragmentShaderCg::SetSourceCode(const String &sSourceCode, const String &sProfile, const String &sArguments, const String &sEntry) { // Destroy the previous Cg fragment program, if there's one if (m_pCgFragmentProgram) { cgDestroyProgram(m_pCgFragmentProgram); m_pCgFragmentProgram = nullptr; } // Get the profile from a user given string m_pCgProfile = cgGetProfile(sProfile.GetLength() ? sProfile : "glslf"); // We're using a GLSL profile as default so ATI users have reasonable shader support when using Cg // On unknown or invalid profile, choose a fallback profile if (m_pCgProfile == CG_PROFILE_UNKNOWN || (!cgGetProfileProperty(m_pCgProfile, CG_IS_FRAGMENT_PROFILE) && m_pCgProfile != CG_PROFILE_GLSLF)) { m_pCgProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT); if (m_pCgProfile == CG_PROFILE_UNKNOWN && cgGLIsProfileSupported(CG_PROFILE_GLSLF)) m_pCgProfile = CG_PROFILE_GLSLF; } // Create the Cg fragment program if (m_pCgProfile != CG_PROFILE_UNKNOWN) m_pCgFragmentProgram = CgContext::CreateCgProgram(m_pCgProfile, sSourceCode, sArguments, sEntry); // Was the Cg program created successfully? if (m_pCgFragmentProgram) { // Backup the optional shader compiler arguments and the user defined entry point m_sArguments = sArguments; m_sEntry = sEntry; // Done return true; } else { m_pCgProfile = CG_PROFILE_UNKNOWN; m_sArguments = ""; m_sEntry = ""; // Error! return false; } }
static sBool sCompileCg(sCompileResult &result, sInt stype, sInt dtype, sInt flags, const sChar8 *src, sInt len, const sChar8 *name) { #if sCOMP_CG_ENABLE if(result.Cg.Program) cgDestroyProgram(result.Cg.Program); sChar8 *src8 = new sChar8[len]; sCopyString(src8,src,len); CGprofile prof = cgGetProfile(GetProfile(dtype)); CGprogram program = cgCreateProgram(CGC,CG_SOURCE,src8,prof,name,0); if(GetCgError(result.Errors)) goto error; cgCompileProgram(program); if(GetCgError(result.Errors)) goto error; const sChar8 *out8 = cgGetProgramString(program,CG_COMPILED_PROGRAM); if(GetCgError(result.Errors)) goto error; sInt size = 0; while(out8[size]) size++; sAddShaderBlob(result.ShaderBlobs,dtype,size,(const sU8*)out8); result.Valid = sTRUE; sDeleteArray(src8); return sTRUE; error: result.Valid = sFALSE; sDeleteArray(src8); return sFALSE; #else sLogF(L"asc",L"sCOMP_CG_ENABLE == 0 no cg compiler available\n"); return sFALSE; #endif // sCOMP_CG_ENABLE }
static void keyboard(unsigned char c, int x, int y) { switch (c) { case ' ': animating = !animating; /* Toggle */ if (animating) { enablestick=0; moving=0; w.xspeed=power*cos(2*angle*myPi/360); w.zspeed=power*sin(2*angle*myPi/360); glutIdleFunc(idle); } else { reset(); glutIdleFunc(NULL); } break; case '1': camera[0]=0; camera[1]=200; camera[2]=400; angle = -90; stickangle = 0; glutPostRedisplay(); break; case '2': camera[0]=500; camera[1]=200; camera[2]=0; angle = 180; stickangle = 270; glutPostRedisplay(); break; case '3': camera[0]=-500; camera[1]=200; camera[2]=0; angle = 0; stickangle = 90; glutPostRedisplay(); break; case '4': camera[0]=0; camera[1]=200; camera[2]=-400; angle = 90; stickangle=180; glutPostRedisplay(); break; case 'z': angle = angle + 2; stickangle=90+angle; glutPostRedisplay(); break; case 'x': angle = angle - 2; stickangle=90+angle; glutPostRedisplay(); break; case 'n': if (camera[0]==0 && camera[1]<=200 && camera[1]>=50 && camera[2]<=400 && camera[2]>100) { camera[1]-=25; camera[2]-=50; glutPostRedisplay(); } if (camera[0]==0 && camera[1]<=200 && camera[1]>=50 && camera[2]>=-400 && camera[2]<100) { camera[1]-=25; camera[2]+=50; glutPostRedisplay(); } if (camera[0]<=500 && camera[0]>100 && camera[1]<=200 && camera[1]>50 && camera[2]==0) { camera[0]-=50; camera[1]-=25; glutPostRedisplay(); } if (camera[0]>=-500 && camera[0]<=-100 && camera[1]<=200 && camera[1]>50 && camera[2]==0) { camera[0]+=50; camera[1]-=25; glutPostRedisplay(); } break; case 'm': if (camera[0]==0 && camera[1]<=175 && camera[1]>=25 && camera[2]<=350 && camera[2]>75) { camera[1]+=25; camera[2]+=50; glutPostRedisplay(); } if (camera[0]==0 && camera[1]<=175 && camera[1]>=25 && camera[2]>=-350 && camera[2]<50) { camera[1]+=25; camera[2]-=50; glutPostRedisplay(); } if (camera[0]<=450 && camera[0]>=50 && camera[1]<=175 && camera[1]>25 && camera[2]==0) { camera[0]+=50; camera[1]+=25; glutPostRedisplay(); } if (camera[0]>=-450 && camera[0]<=-50 && camera[1]<=175 && camera[1]>25 && camera[2]==0) { camera[0]-=50; camera[1]+=25; glutPostRedisplay(); } break; case 27: /* Esc key */ /* Demonstrate proper deallocation of Cg runtime data structures. Not strictly necessary if we are simply going to exit. */ cgDestroyProgram(myCgVertexProgram); cgDestroyContext(myCgContext); exit(0); break; } }
bool cgShader::Reload(){ for(int k = 0; k < 3; k++){ if(cgProgram[k]){ cgDestroyProgram(cgProgram[k]); } } cgProfile[0] = cgProfile[1] = cgProfile[2] = CG_PROFILE_UNKNOWN; cgProgram[0] = cgProgram[1] = cgProgram[2] = NULL; bool ret = true; if(cgGetContext()){ for(int i = 0; i < 3; i++){ if(i == 0 && vpmain == 0){ continue; } if(i == 1 && gpmain == 0){ continue; } if(i == 2 && fpmain == 0){ continue; } switch(i){ case 0: cgProfile[i] = cgGLGetLatestProfile(CG_GL_VERTEX); break; case 1: cgProfile[i] = cgGLGetLatestProfile(CG_GL_GEOMETRY); break; case 2: cgProfile[i] = cgGLGetLatestProfile(CG_GL_FRAGMENT); break; } if (cgProfile[i] == CG_PROFILE_UNKNOWN){ printf("Invalid profile type ("); switch(i){ case 0: printf("CG_GL_VERTEX)\n"); break; case 1: printf("CG_GL_GEOMETRY)\n"); break; case 2: printf("CG_GL_FRAGMENT)\n"); break; } ret = false; continue; } cgGLSetOptimalOptions(cgProfile[i]); if(code){ switch(i){ case 0: cgProgram[i] = cgCreateProgram(cgGetContext(), CG_SOURCE, code, cgProfile[i], vpmain, 0); break; case 1: cgProgram[i] = cgCreateProgram(cgGetContext(), CG_SOURCE, code, cgProfile[i], gpmain, 0); break; case 2: cgProgram[i] = cgCreateProgram(cgGetContext(), CG_SOURCE, code, cgProfile[i], fpmain, 0); break; } } else{ switch(i){ case 0: cgProgram[i] = cgCreateProgramFromFile(cgGetContext(), CG_SOURCE, fname, cgProfile[i], vpmain, 0); break; case 1: cgProgram[i] = cgCreateProgramFromFile(cgGetContext(), CG_SOURCE, fname, cgProfile[i], gpmain, 0); break; case 2: cgProgram[i] = cgCreateProgramFromFile(cgGetContext(), CG_SOURCE, fname, cgProfile[i], fpmain, 0); break; } } if (cgProgram[i] == NULL){ switch(i){ case 0: printf("CG ERROR (VERTEX) : %s\n", cgGetErrorString(cgGetError())); break; case 1: printf("CG ERROR (GEOMETRY) : %s\n",cgGetErrorString(cgGetError())); break; case 2: printf("CG ERROR (FRAGMENT) : %s\n",cgGetErrorString(cgGetError())); break; } ret = false; continue; } cgGLLoadProgram(cgProgram[i]); } } if(loaded){ if(ret){ printf("INFO (cgShader): Reloaded %s successfully\n",fname); } else{ printf("INFO (cgShader): Reloading %s failed\n",fname); } } else{ if(ret){ printf("INFO (cgShader): Loaded %s successfully\n",fname); } else{ printf("INFO (cgShader): Loading %s failed\n",fname); } } loaded = true; return ret; }
bool cgShader_3::Reload(){ for(int k = 0; k < 5; k++){ if(cgProgram[k]){ cgDestroyProgram(cgProgram[k]); } cgProfile[k] = CG_PROFILE_UNKNOWN; cgProgram[k] = NULL; } bool ret = true; if(cgGetContext()){ for(int i = 0; i < 5; i++){ if( main[i] == 0 ){ continue; } switch(i){ case 0: cgProfile[i] = cgGLGetLatestProfile(CG_GL_VERTEX); break; case 1: cgProfile[i] = cgGLGetLatestProfile(CG_GL_TESSELLATION_CONTROL); break; case 2: cgProfile[i] = cgGLGetLatestProfile(CG_GL_TESSELLATION_EVALUATION); break; case 3: cgProfile[i] = cgGLGetLatestProfile(CG_GL_GEOMETRY); break; case 4: cgProfile[i] = cgGLGetLatestProfile(CG_GL_FRAGMENT); break; } if (cgProfile[i] == CG_PROFILE_UNKNOWN){ printf("Invalid profile type ("); switch(i){ case 0: printf("CG_GL_VERTEX)\n"); break; case 1: printf("CG_GL_TESSELLATION_CONTROL)\n"); break; case 2: printf("CG_GL_TESSELLATION_EVALUATION)\n"); break; case 3: printf("CG_GL_GEOMETRY)\n"); break; case 4: printf("CG_GL_FRAGMENT)\n"); break; } ret = false; continue; } cgGLSetOptimalOptions(cgProfile[i]); if(code){ cgProgram[i] = cgCreateProgram(cgGetContext(), CG_SOURCE, code, cgProfile[i], main[i], 0); } else{ cgProgram[i] = cgCreateProgramFromFile(cgGetContext(), CG_SOURCE, fname, cgProfile[i], main[i], 0); } if (cgProgram[i] == NULL){ switch(i){ case 0: printf("CG ERROR (VERTEX) : %s\n", cgGetErrorString(cgGetError())); break; case 1: printf("CG ERROR (TESS_CTRL) : %s\n",cgGetErrorString(cgGetError())); break; case 2: printf("CG ERROR (TESS_EVAL) : %s\n",cgGetErrorString(cgGetError())); break; case 3: printf("CG ERROR (GEOMETRY) : %s\n", cgGetErrorString(cgGetError())); break; case 4: printf("CG ERROR (FRAGMENT) : %s\n", cgGetErrorString(cgGetError())); break; } ret = false; continue; } cgGLLoadProgram(cgProgram[i]); } } if(loaded){ if(ret){ printf("INFO (cgShader): Reloaded %s successfully\n",fname); } else{ printf("INFO (cgShader): Reloading %s failed\n",fname); } } else{ if(ret){ printf("INFO (cgShader): Loaded %s successfully\n",fname); } else{ printf("INFO (cgShader): Loading %s failed\n",fname); } } loaded = true; return ret; }
CGShader::~CGShader(void) { cgDestroyProgram(m_program); }
bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram) { GLenum err = GL_REPORT_ERROR(); if (err != GL_NO_ERROR) { ERROR_LOG(VIDEO, "glError %08x before PS!", err); } #if defined HAVE_CG && HAVE_CG char stropt[128]; sprintf(stropt, "MaxLocalParams=224,NumInstructionSlots=%d", s_nMaxPixelInstructions); const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL}; CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgfProf, "main", opts); // handle errors if (!cgIsProgram(tempprog)) { cgDestroyProgram(tempprog); static int num_failures = 0; char szTemp[MAX_PATH]; sprintf(szTemp, "%sbad_ps_%04i.txt", File::GetUserPath(D_DUMP_IDX).c_str(), num_failures++); std::ofstream file(szTemp); file << pstrprogram; file.close(); PanicAlert("Failed to compile pixel shader!\nThis usually happens when trying to use Dolphin with an outdated GPU or integrated GPU like the Intel GMA series.\n\nIf you're sure this is Dolphin's error anyway, post the contents of %s along with this error message at the forums.\n\nDebug info (%d):\n%s", szTemp, g_cgfProf, cgGetLastListing(g_cgcontext)); return false; } // handle warnings if (cgGetError() != CG_NO_ERROR) { WARN_LOG(VIDEO, "Warnings on compile ps %s:", cgGetLastListing(g_cgcontext)); WARN_LOG(VIDEO, "%s", pstrprogram); } // This looks evil - we modify the program through the const char * we got from cgGetProgramString! // It SHOULD not have any nasty side effects though - but you never know... char *pcompiledprog = (char*)cgGetProgramString(tempprog, CG_COMPILED_PROGRAM); char *plocal = strstr(pcompiledprog, "program.local"); while (plocal != NULL) { const char *penv = " program.env"; memcpy(plocal, penv, 13); plocal = strstr(plocal+13, "program.local"); } glGenProgramsARB(1, &ps.glprogid); SetCurrentShader(ps.glprogid); glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog); err = GL_REPORT_ERROR(); if (err != GL_NO_ERROR) { GLint error_pos, native_limit; glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos); glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native_limit); // Error occur if (error_pos != -1) { const char *program_error = (const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB); char line[256]; strncpy(line, (const char *)pcompiledprog + error_pos, 255); line[255] = 0; ERROR_LOG(VIDEO, "Error at %i: %s", error_pos, program_error); ERROR_LOG(VIDEO, "Line dump: \n%s", line); } else if (native_limit != -1) { ERROR_LOG(VIDEO, "Hit limit? %i", native_limit); // TODO } ERROR_LOG(VIDEO, "%s", pstrprogram); ERROR_LOG(VIDEO, "%s", pcompiledprog); } cgDestroyProgram(tempprog); #endif return true; }
// // Constructor // CCgShader::CCgShader( CGenum SourceType, const string& SourceStr, CGprofile Profile, CGGLenum ProfileClass, const string& Entry, const string& Arguments ): m_Program( NULL ) { if (SourceType != CG_SOURCE && SourceType != CG_OBJECT) throw Sys::CDeveloperException( "GL::CCgShader", "::CCgShader() : Invalid <SourceType> parameter." ); if (SourceStr.length() == 0) throw Sys::CDeveloperException( "GL::CCgShader", "::CCgShader() : Invalid <SourceStr> parameter." ); CCgContext::AddRef(); if (Profile == CG_PROFILE_UNKNOWN) Profile = cgGLGetLatestProfile( ProfileClass ); else { CheckDomain( Profile, ProfileClass ); if (cgGLIsProfileSupported( Profile ) == CG_FALSE) { const char *ProfileName = GetProfileName( Profile ); if (!ProfileName) throw Sys::CException( 0, "GL::CCgShader", "::CCgShader() : Unknown shader profile." ); else { throw Sys::CException( 0, "GL::CCgShader", "::CCgShader() : Profile %s unsupported.\n" "A profile may not be supported if required OpenGL extension is not available.", ProfileName ); } } } try { const char *TypeName = NULL; switch (ProfileClass) { case CG_GL_VERTEX: TypeName = "vertex"; break; case CG_GL_GEOMETRY: TypeName = "geometry"; break; case CG_GL_FRAGMENT: TypeName = "fragment"; break; } const char *Args[ 2 ] = { Arguments.c_str(), NULL }; m_Program = cgCreateProgram( CCgContext::GetContext(), SourceType, SourceStr.c_str(), Profile, (Entry.length() == 0) ? NULL : Entry.c_str(), (Arguments.length() == 0) ? NULL : Args ); if (!m_Program) { m_LastListing = CCgContext::GetLastListing(); #ifdef _DEBUG OutputDebugLog(); #endif throw CCgException( "GL::CCgShader", cgGetError(), "::CCgShader() : Failed to create Cg %s shader.\nSee program log for more details.", TypeName ); } cgCompileProgram( m_Program ); CGerror Error = cgGetError(); if (Error != CG_NO_ERROR) { m_LastListing = CCgContext::GetLastListing(); #ifdef _DEBUG OutputDebugLog(); #endif throw CCgException( "GL::CCgShader", Error, "::CCgShader() : Failed to compile Cg %s shader.\nSee program log for more details.", TypeName ); } } catch (const Sys::CException& Ex) { if (cgIsProgram( m_Program )) cgDestroyProgram( m_Program ); CCgContext::Release(); throw Ex; } }
//--------------------------------------------------------------------------------- // init // this function load and compile a vertex/fragment program on the specified context // if the source file is not found, it assigns a default GREEN color shader // if the compile failed, it assigns a default RED color shader //--------------------------------------------------------------------------------- bool FFxProgram::init(CGcontext aContext) { CGenum fileType; // remove existing program (in case a program is already loaded) if (mProgram) { cgDestroyProgram(mProgram); mProgram = 0; } fileType = CG_SOURCE; #ifdef WIN32 HRESULT hr; if (GDD->GetClassID() == ClassIDZDisplayDeviceDX9) { const char** profileOpts; profileOpts = cgD3D9GetOptimalOptions(mProfile); const char *nOpts[16]; nOpts[0] = COMPILE_ARGS[0]; int idx =1; while ( (idx<15) && profileOpts[idx-1]) { nOpts[idx] = profileOpts[idx-1]; idx++; } nOpts[idx] = 0; const char *szDXprofile = NULL; if (mProfile == CG_PROFILE_VS_2_0) { szDXprofile = D3DXGetVertexShaderProfile(GDD->GetD3D9Device()); } else { szDXprofile = D3DXGetPixelShaderProfile(GDD->GetD3D9Device()); } /* //LPD3DXBUFFER mDXShader; D3DXCompileShader( mSourceBuffer, strlen(mSourceBuffer), NULL, NULL, mEntry.c_str(), szDXprofile, 0, &mDXShader, NULL, NULL ); */ mProgram = cgCreateProgram(aContext, fileType, mSourceBuffer, mProfile, mEntry.c_str(), nOpts); hr = cgD3D9LoadProgram(mProgram, true, 0); } else #endif { // opengl //mProgram = cgCreateProgram(aContext, fileType, mSourceBuffer, mProfile, mEntry.c_str(), COMPILE_ARGS); mProfile = (mProfileDomain == CG_VERTEX_DOMAIN) ?cgGLGetLatestProfile(CG_GL_VERTEX):cgGLGetLatestProfile(CG_GL_FRAGMENT ); assert(cgGLIsProfileSupported(mProfile)); mProgram = cgCreateProgramFromFile(aContext, fileType, mFileName, mProfile, mEntry.c_str(), COMPILE_ARGS); if (mProgram == NULL) { CGerror error; const char* errTxt = cgGetLastErrorString(&error); LOG ("ERROR %x: can't compile %s : %s\n", error, mFileName.c_str(), errTxt); useDefaultProgram(aContext); assert(false); return false; } cgGLLoadProgram(mProgram); checkForCgError("loadprog"); } if (mProgram == 0) { CGerror error = cgGetError(); LOG ("ERROR %x: can't load or compile %s : %s\n", error, mFileName.c_str(), cgGetLastErrorString(&error)); useDefaultProgram(aContext); assert(false); return false; } return true; }
iShaderProgram::CacheLoadResult csShaderGLCGCommon::LoadFromCache ( iHierarchicalCache* cache, iBase* previous, iDocumentNode* node, csRef<iString>* failReason, csRef<iString>* tag, ProfileLimitsPair* cacheLimits) { if (!cache) return iShaderProgram::loadFail; csRef<iShaderProgramCG> prevCG (scfQueryInterfaceSafe<iShaderProgramCG> ( previous)); csRef<iStringArray> allCachedPrograms; if ((programType == progVP) && prevCG.IsValid()) { csShaderGLCGFP* prevFP = static_cast<csShaderGLCGFP*> ( (iShaderProgramCG*)prevCG); csString tagStr ("CG"); tagStr += prevFP->cacheLimits.ToString(); if (failReason) failReason->AttachNew ( new scfString ("paired cached programs not found")); allCachedPrograms.AttachNew (new scfStringArray); allCachedPrograms->Push (tagStr); } else allCachedPrograms = cache->GetSubItems ("/"); if (!allCachedPrograms.IsValid() || (allCachedPrograms->GetSize() == 0)) { if (failReason) failReason->AttachNew ( new scfString ("no cached programs found")); return iShaderProgram::loadFail; } if (!GetProgramNode (node)) return iShaderProgram::loadFail; csRef<iDataBuffer> programBuffer = GetProgramData(); CS::Utility::Checksum::MD5::Digest progHash = CS::Utility::Checksum::MD5::Encode ( programBuffer->GetData(), programBuffer->GetSize()); csArray<CachedShaderWrapper> cachedProgWrappers; for (size_t i = 0; i < allCachedPrograms->GetSize(); i++) { const char* tag = allCachedPrograms->Get (i); if ((tag[0] != 'C') || (tag[1] != 'G')) continue; CachedShaderWrapper wrapper; if (!wrapper.limits.FromString (tag+2)) continue; wrapper.name = tag; csString cachePath ("/"); cachePath.Append (tag); csRef<iDataBuffer> cacheBuf = cache->ReadCache (cachePath); if (!cacheBuf.IsValid()) continue; csRef<iFile> cacheFile; cacheFile.AttachNew (new csMemFile (cacheBuf, true)); wrapper.cacheFile = cacheFile; uint32 diskMagic; if (cacheFile->Read ((char*)&diskMagic, sizeof (diskMagic)) != sizeof (diskMagic)) continue; if (csLittleEndian::UInt32 (diskMagic) != cacheFileMagic) continue; CS::Utility::Checksum::MD5::Digest diskHash; if (cacheFile->Read ((char*)&diskHash, sizeof (diskHash)) != sizeof (diskHash)) continue; if (diskHash != progHash) continue; cachedProgWrappers.Push (wrapper); } if (cachedProgWrappers.GetSize() == 0) { if (failReason && !*failReason) failReason->AttachNew ( new scfString ("all cached programs failed to read")); return iShaderProgram::loadFail; } cachedProgWrappers.Sort (); ProfileLimits currentLimits ( (programType == progVP) ? shaderPlug->currentLimits.vp : shaderPlug->currentLimits.fp); bool strictMatch = (programType == progVP) ? shaderPlug->strictMatchVP : shaderPlug->strictMatchFP; const char* progTypeNode = 0; switch (programType) { case progVP: progTypeNode = "cgvp"; break; case progFP: progTypeNode = "cgfp"; break; } csString allReasons; bool oneReadCorrectly = false; ProfileLimits bestLimits ( CS::PluginCommon::ShaderProgramPluginGL::Other, CG_PROFILE_UNKNOWN); bool bestLimitsSet = false; for (size_t i = cachedProgWrappers.GetSize(); i-- > 0;) { const CachedShaderWrapper& wrapper = cachedProgWrappers[i]; const ProfileLimits& limits = (programType == progVP) ? wrapper.limits.vp : wrapper.limits.fp; if (!bestLimitsSet) { bestLimits = limits; bestLimitsSet = true; } if (strictMatch && (limits != currentLimits)) { allReasons += wrapper.name; allReasons += ": strict mismatch; "; continue; } bool profileSupported = (shaderPlug->ProfileNeedsRouting (limits.profile) && shaderPlug->IsRoutedProfileSupported (limits.profile)) || cgGLIsProfileSupported (limits.profile); if (!profileSupported) { allReasons += wrapper.name; allReasons += ": Profile unsupported; "; continue; } if ((limits.vendor != currentLimits.vendor) && (limits.vendor != CS::PluginCommon::ShaderProgramPluginGL::Other)) { allReasons += wrapper.name; allReasons += ": vendor mismatch; "; continue; } bool limitsSupported = currentLimits >= limits; if (!limitsSupported) { allReasons += wrapper.name; allReasons += ": Limits exceeded; "; continue; } iFile* cacheFile = wrapper.cacheFile; { uint32 diskState; if (cacheFile->Read ((char*)&diskState, sizeof (diskState)) != sizeof (diskState)) continue; if (csLittleEndian::UInt32 (diskState) != cpsValid) { oneReadCorrectly = true; continue; } } description = CS::PluginCommon::ShaderCacheHelper::ReadString (cacheFile); bool breakFail = false; csRef<iDocumentNode> cgNode = node->GetNode (progTypeNode); if (!cgNode.IsValid()) continue; csRef<iDocumentNodeIterator> nodes = cgNode->GetNodes(); while(nodes->HasNext() && !breakFail) { csRef<iDocumentNode> child = nodes->Next(); if(child->GetType() != CS_NODE_ELEMENT) continue; const char* value = child->GetValue (); csStringID id = xmltokens.Request (value); switch(id) { case XMLTOKEN_VARIABLEMAP: if (!ParseVmap (child)) breakFail = true; break; case XMLTOKEN_CLIP: if (!ParseClip (child)) breakFail = true; break; default: /* Ignore unknown nodes. Invalid nodes would have been caught by the first (not from cache) parsing */ break; } } if (breakFail) continue; csString objectCodeCachePathArc = CS::PluginCommon::ShaderCacheHelper::ReadString (cacheFile); if (objectCodeCachePathArc.IsEmpty()) continue; csString objectCodeCachePathItem = CS::PluginCommon::ShaderCacheHelper::ReadString (cacheFile); if (objectCodeCachePathItem.IsEmpty()) continue; ProgramObjectID progId (objectCodeCachePathArc, objectCodeCachePathItem); ProgramObject programObj; //if (!LoadObjectCodeFromCompileCache (limits, cache)) if (!shaderPlug->progCache.LoadObject (progId, programObj)) continue; oneReadCorrectly = true; if (program) { cgDestroyProgram (program); program = 0; } if (!programObj.IsValid()) continue; cgGetError(); // Clear error program = cgCreateProgram (shaderPlug->context, CG_OBJECT, programObj.GetObjectCode(), limits.profile, 0, 0); if (!program) continue; CGerror err = cgGetError(); if (err != CG_NO_ERROR) { const char* errStr = cgGetErrorString (err); shaderPlug->Report (CS_REPORTER_SEVERITY_WARNING, "Cg error %s", errStr); continue; } programProfile = limits.profile; programPositionInvariant = programObj.GetFlags() & ProgramObject::flagPositionInvariant; unusedParams = programObj.GetUnusedParams(); ClipsToVmap(); GetParamsFromVmap(); bool doLoadToGL = !shaderPlug->ProfileNeedsRouting (programProfile); cgGetError(); // Clear error if (doLoadToGL) { cgGLLoadProgram (program); } else { cgCompileProgram (program); } shaderPlug->PrintAnyListing(); err = cgGetError(); if ((err != CG_NO_ERROR) || (doLoadToGL && !cgGLIsProgramLoaded (program))) { //if (shaderPlug->debugDump) //DoDebugDump(); const char* errStr = cgGetErrorString (err); shaderPlug->Report (CS_REPORTER_SEVERITY_WARNING, "Cg error %s", errStr); if (shaderPlug->doVerbose && (((programType == progVP) && (programProfile >= CG_PROFILE_ARBVP1)) || ((programType == progFP) && (programProfile >= CG_PROFILE_ARBFP1)))) { const char* err = (char*)glGetString (GL_PROGRAM_ERROR_STRING_ARB); shaderPlug->Report (CS_REPORTER_SEVERITY_WARNING, "OpenGL error string: %s", err); } shaderPlug->SetCompiledSource (0); continue; } GetPostCompileParamProps (); if (shaderPlug->debugDump) DoDebugDump(); tag->AttachNew (new scfString (wrapper.name)); if (cacheLimits != 0) *cacheLimits = wrapper.limits; bool loaded = !shaderPlug->ProfileNeedsRouting (programProfile) || LoadProgramWithPS1 (); if (loaded && (bestLimits < currentLimits)) { /* The best found program is worse than the current limits, so pretend that the shader program failed (instead just being 'invalid') - that will make xmlshader try to load the program from scratch, ie with current limits, which may just work. */ if (failReason) failReason->AttachNew (new scfString ("Provoking clean load with current limits")); return iShaderProgram::loadFail; } return loaded ? iShaderProgram::loadSuccessShaderValid : iShaderProgram::loadSuccessShaderInvalid; } if (oneReadCorrectly) { if (bestLimits < currentLimits) { /* The 'invalid' programs may compile with the current limits - so again, provoke clean load */ if (failReason) failReason->AttachNew (new scfString ("Provoking clean load with current limits")); return iShaderProgram::loadFail; } else return iShaderProgram::loadSuccessShaderInvalid; } else return iShaderProgram::loadFail; }
//----------------------------------------------------------------------- void CgProgram::compileMicrocode(void) { // Create Cg Program /// Program handle CGprogram cgProgram; if (mSelectedCgProfile == CG_PROFILE_UNKNOWN) { LogManager::getSingleton().logMessage( "Attempted to load Cg program '" + mName + "', but no supported " "profile was found. "); return; } buildArgs(); // deal with includes String sourceToUse = resolveCgIncludes(mSource, this, mFilename); cgProgram = cgCreateProgram(mCgContext, CG_SOURCE, sourceToUse.c_str(), mSelectedCgProfile, mEntryPoint.c_str(), const_cast<const char**>(mCgArguments)); // Test //LogManager::getSingleton().logMessage(cgGetProgramString(mCgProgram, CG_COMPILED_PROGRAM)); // Check for errors checkForCgError("CgProgram::compileMicrocode", "Unable to compile Cg program " + mName + ": ", mCgContext); CGerror error = cgGetError(); if (error == CG_NO_ERROR) { // get program string (result of cg compile) mProgramString = cgGetProgramString(cgProgram, CG_COMPILED_PROGRAM); checkForCgError("CgProgram::compileMicrocode", "Unable to retrieve program code for Cg program " + mName + ": ", mCgContext); // get params mParametersMap.clear(); mParametersMapSizeAsBuffer = 0; mSamplerRegisterMap.clear(); recurseParams(cgGetFirstParameter(cgProgram, CG_PROGRAM)); recurseParams(cgGetFirstParameter(cgProgram, CG_GLOBAL)); if (mDelegate) { // Delegating to HLSL or GLSL, need to clean up Cg's output fixHighLevelOutput(mProgramString); if (mSelectedCgProfile == CG_PROFILE_GLSLG) { // need to determine input and output operations mInputOp = cgGetProgramInput(cgProgram); mOutputOp = cgGetProgramOutput(cgProgram); } } // Unload Cg Program - we don't need it anymore cgDestroyProgram(cgProgram); //checkForCgError("CgProgram::unloadImpl", // "Error while unloading Cg program " + mName + ": ", // mCgContext); cgProgram = 0; if ( GpuProgramManager::getSingleton().getSaveMicrocodesToCache()) { addMicrocodeToCache(); } } }
bool csShaderGLCGCommon::DefaultLoadProgram (iShaderProgramCG* cgResolve, const char* programStr, ProgramType _type, const ProfileLimitsPair& customLimitsPair, uint flags) { if (!programStr || !*programStr) return false; const ProfileLimits& customLimits = (_type == progVP) ? customLimitsPair.vp : customLimitsPair.fp; CGGLenum type = (_type == progVP) ? CG_GL_VERTEX : CG_GL_FRAGMENT; size_t i; csString augmentedProgramStr = GetAugmentedProgram (programStr, (flags & loadFlagUnusedV2FForInit) != 0); programStr = augmentedProgramStr; CGprofile profile = customLimits.profile; CS::PluginCommon::ShaderProgramPluginGL::HardwareVendor vendor = customLimits.vendor; if (shaderPlug->doVerbose || shaderPlug->doVerbosePrecache) { shaderPlug->Report (CS_REPORTER_SEVERITY_NOTIFY, "Cg %s program %s: using profile %s[%d]", GetProgramType(), CS::Quote::Single (description.GetData ()), cgGetProfileString (profile), profile); } ArgumentArray args; shaderPlug->GetProfileCompilerArgs (GetProgramType(), profile, customLimitsPair, vendor, (flags & loadIgnoreConfigProgramOpts) ? csGLShader_CG::argsNoConfig : csGLShader_CG::argsAll, args); for (i = 0; i < compilerArgs.GetSize(); i++) args.Push (compilerArgs[i]); programPositionInvariant = false; for (i = 0; i < args.GetSize(); ) { if (strcmp (args[i], "-posinv") == 0) { if (profile >= CG_PROFILE_GPU_VP) { /* Work around Cg 2.0 and above (including 3.0) bug: it emits "OPTION ARB_position_invariant;" AND computes result.position in the VP - doing both is verboten. Affected are the GP4VP and higher profiles. Remedy: remove -posinv argument */ args.DeleteIndex (i); continue; } programPositionInvariant = true; } i++; } customLimits.ToCgOptions (args); args.Push (0); if (program) { cgDestroyProgram (program); } shaderPlug->SetCompiledSource (programStr); shaderPlug->SetIgnoreErrors (true); program = cgCreateProgram (shaderPlug->context, CG_SOURCE, programStr, profile, !entrypoint.IsEmpty() ? entrypoint : "main", args.GetArray()); shaderPlug->SetIgnoreErrors (false); if (!(flags & loadIgnoreErrors)) shaderPlug->PrintAnyListing(); if (!program) { shaderPlug->SetCompiledSource (0); /*if (shaderPlug->debugDump) { EnsureDumpFile(); WriteAdditionalDumpInfo ("Failed program source", programStr); }*/ return false; } programProfile = cgGetProgramProfile (program); GetParamsFromVmapConstants(); if (flags & loadApplyVmap) GetParamsFromVmap(); if (flags & loadIgnoreErrors) shaderPlug->SetIgnoreErrors (true); cgCompileProgram (program); if (flags & loadIgnoreErrors) shaderPlug->SetIgnoreErrors (false); else shaderPlug->PrintAnyListing(); if (flags & loadApplyVmap) GetPostCompileParamProps (); if (flags & loadLoadToGL) { cgGetError(); // Clear error cgGLLoadProgram (program); if (!(flags & loadIgnoreErrors)) shaderPlug->PrintAnyListing(); if ((cgGetError() != CG_NO_ERROR) || !cgGLIsProgramLoaded (program)) { if (shaderPlug->debugDump) DoDebugDump(); if (shaderPlug->doVerbose && (((type == CG_GL_VERTEX) && (profile >= CG_PROFILE_ARBVP1)) || ((type == CG_GL_FRAGMENT) && (profile >= CG_PROFILE_ARBFP1)))) { csString err = (char*)glGetString (GL_PROGRAM_ERROR_STRING_ARB); if (!err.IsEmpty()) shaderPlug->Report (CS_REPORTER_SEVERITY_WARNING, "OpenGL error string: %s", err.GetData()); } shaderPlug->SetCompiledSource (0); return false; } } if (shaderPlug->debugDump) DoDebugDump(); shaderPlug->SetCompiledSource (0); bool result = true; if (programType == progFP) { int numVaryings = 0; CGparameter param = cgGetFirstLeafParameter (program, CG_PROGRAM); while (param) { if (cgIsParameterUsed (param, program) && cgIsParameterReferenced (param)) { const CGenum var = cgGetParameterVariability (param); if (var == CG_VARYING) numVaryings++; } param = cgGetNextLeafParameter (param); } /* WORKAROUND: Even NVs G80 doesn't support passing more than 16 attribs into an FP, yet Cg happily generates code that uses more (and GL falls back to SW). So manually check the number of varying inputs and reject more than 16. @@@ This should be at least configurable */ const int maxNumVaryings = 16; if (numVaryings > maxNumVaryings) { if (shaderPlug->doVerbose || shaderPlug->doVerbosePrecache) { shaderPlug->Report (CS_REPORTER_SEVERITY_NOTIFY, "Discarding compiled program for having too much varyings " "(%d, limit is %d)", numVaryings, maxNumVaryings); } cgDestroyProgram (program); program = 0; result = false; } } if (!result && !debugFN.IsEmpty()) { csRef<iVFS> vfs = csQueryRegistry<iVFS> (objectReg); vfs->DeleteFile (debugFN); } return result; }