static void cg_error_handler(CGcontext ctx, CGerror error, void *data) { (void)ctx; (void)data; switch (error) { case CG_INVALID_PARAM_HANDLE_ERROR: RARCH_ERR("CG: Invalid param handle.\n"); break; case CG_INVALID_PARAMETER_ERROR: RARCH_ERR("CG: Invalid parameter.\n"); break; default: break; } RARCH_ERR("CG error: \"%s\"\n", cgGetErrorString(error)); }
void cEffect::SetParam(const std::string &lacName, const float * lfParam, int liCount ) { static const unsigned kuiAuxiliarBuffer = 256 * 4; static float gFullArray[kuiAuxiliarBuffer]; CGparameter lParam = cgGetNamedEffectParameter(mEffect, lacName.c_str()); if (lParam) { int liNRows = cgGetParameterRows(lParam); int liNCols = cgGetParameterColumns(lParam); int liASize = cgGetArrayTotalSize(lParam); int liNTotal = liNRows*liNCols; if (liASize > 0) { liNTotal *= liASize; if ( liCount < liNTotal ) { assert(kuiAuxiliarBuffer > liNTotal); assert(kuiAuxiliarBuffer > liCount); memcpy(gFullArray, lfParam, sizeof(float) * liCount); cgSetParameterValuefr(lParam, liNTotal, gFullArray); } else { cgSetParameterValuefr(lParam, liCount, lfParam); } CGerror err = cgGetError(); if (err != CG_NO_ERROR) { OutputDebugStr(cgGetErrorString( err )); OutputDebugStr("\n"); } } } }
static void print_errors() { std::cerr << "Printing all possible error strings:" << std::endl; std::cerr << "SDL : " << (strlen(SDL_GetError() ) ? SDL_GetError() : "no error") << std::endl; std::cerr << "SDL_image : " << (strlen(IMG_GetError () ) ? IMG_GetError () : "no error") << std::endl; std::cerr << "SDL_net : " << (strlen(SDLNet_GetError()) ? SDLNet_GetError() : "no error") << std::endl; std::cerr << "SDL_ttf : " << (strlen(TTF_GetError() ) ? TTF_GetError() : "no error") << std::endl; #ifndef DISABLE_DX9 //DXGetErrorString? #endif #ifndef DISABLE_GL std::cerr << "OpenGL : " << gluErrorString(glGetError()) << std::endl; #endif #ifndef DISABLE_AL std::cerr << "OpenAL : " << Zeni::alErrorString(alGetError()) << std::endl; #endif #ifndef DISABLE_CG std::cerr << "Cg : " << cgGetErrorString(cgGetError()) << std::endl; #endif }
static bool gl_cg_compile_program( void *data, unsigned idx, void *program_data, struct shader_program_info *program_info) { const char *list = NULL; const char *argv[2 + GFX_MAX_SHADERS]; bool ret = true; char *listing_f = NULL; char *listing_v = NULL; unsigned i, argc = 0; struct shader_program_cg *program = (struct shader_program_cg*)program_data; cg_shader_data_t *cg = (cg_shader_data_t*)data; if (!program) program = &cg->prg[idx]; argv[argc++] = "-DPARAMETER_UNIFORM"; for (i = 0; i < GFX_MAX_SHADERS; i++) { if (*(cg->alias_define[i])) argv[argc++] = cg->alias_define[i]; } argv[argc] = NULL; if (program_info->is_file) program->fprg = cgCreateProgramFromFile( cg->cgCtx, CG_SOURCE, program_info->combined, cg->cgFProf, "main_fragment", argv); else program->fprg = cgCreateProgram(cg->cgCtx, CG_SOURCE, program_info->combined, cg->cgFProf, "main_fragment", argv); list = cgGetLastListing(cg->cgCtx); if (list) listing_f = strdup(list); list = NULL; if (program_info->is_file) program->vprg = cgCreateProgramFromFile( cg->cgCtx, CG_SOURCE, program_info->combined, cg->cgVProf, "main_vertex", argv); else program->vprg = cgCreateProgram(cg->cgCtx, CG_SOURCE, program_info->combined, cg->cgVProf, "main_vertex", argv); list = cgGetLastListing(cg->cgCtx); if (list) listing_v = strdup(list); if (!program->fprg || !program->vprg) { RARCH_ERR("CG error: %s\n", cgGetErrorString(cgGetError())); if (listing_f) RARCH_ERR("Fragment:\n%s\n", listing_f); else if (listing_v) RARCH_ERR("Vertex:\n%s\n", listing_v); ret = false; goto end; } cgGLLoadProgram(program->fprg); cgGLLoadProgram(program->vprg); end: free(listing_f); free(listing_v); return ret; }
static void cg_error_callback( void ) { CGerror i = cgGetError(); common->Printf( "Cg error (%d): %s\n", i, cgGetErrorString(i) ); }
static void handleCgError() { fprintf(stderr, "Cg error: %s\n", cgGetErrorString(cgGetError())); // exit(1); }
static bool d3d9_cg_load_program(void *data, struct shader_pass *pass, const char *prog, bool path_is_file) { const char *list = NULL; char *listing_f = NULL; char *listing_v = NULL; CGprofile vertex_profile = cgD3D9GetLatestVertexProfile(); CGprofile fragment_profile = cgD3D9GetLatestPixelProfile(); const char **fragment_opts = cgD3D9GetOptimalOptions(fragment_profile); const char **vertex_opts = cgD3D9GetOptimalOptions(vertex_profile); cg_renderchain_t *chain = (cg_renderchain_t*)data; CGcontext cgCtx = chain->cgCtx; if ( fragment_profile == CG_PROFILE_UNKNOWN || vertex_profile == CG_PROFILE_UNKNOWN) { RARCH_ERR("Invalid profile type\n"); goto error; } RARCH_LOG("[D3D9 Cg]: Vertex profile: %s\n", cgGetProfileString(vertex_profile)); RARCH_LOG("[D3D9 Cg]: Fragment profile: %s\n", cgGetProfileString(fragment_profile)); if (path_is_file && !string_is_empty(prog)) pass->fprg = cgCreateProgramFromFile(cgCtx, CG_SOURCE, prog, fragment_profile, "main_fragment", fragment_opts); else pass->fprg = cgCreateProgram(cgCtx, CG_SOURCE, stock_cg_d3d9_program, fragment_profile, "main_fragment", fragment_opts); list = cgGetLastListing(cgCtx); if (list) listing_f = strdup(list); if (path_is_file && !string_is_empty(prog)) pass->vprg = cgCreateProgramFromFile(cgCtx, CG_SOURCE, prog, vertex_profile, "main_vertex", vertex_opts); else pass->vprg = cgCreateProgram(cgCtx, CG_SOURCE, stock_cg_d3d9_program, vertex_profile, "main_vertex", vertex_opts); list = cgGetLastListing(cgCtx); if (list) listing_v = strdup(list); if (!pass->fprg || !pass->vprg) goto error; cgD3D9LoadProgram(pass->fprg, true, 0); cgD3D9LoadProgram(pass->vprg, true, 0); free(listing_f); free(listing_v); return true; error: RARCH_ERR("CG error: %s\n", cgGetErrorString(cgGetError())); if (listing_f) RARCH_ERR("Fragment:\n%s\n", listing_f); else if (listing_v) RARCH_ERR("Vertex:\n%s\n", listing_v); free(listing_f); free(listing_v); return false; }
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; }
Shader::Shader(std::string shader_name) { // Be carefull: Cg needs a valid OpenGL context (be sure no shader is created before we have an OpenGL window) if (!cg_context) { cg_context = cgCreateContext(); vertex_profile = cgGLGetLatestProfile(CG_GL_VERTEX); // auto-detect best vertex profile cgGLSetOptimalOptions(vertex_profile); fragment_profile = cgGLGetLatestProfile(CG_GL_FRAGMENT); // auto-detect best fragment profile cgGLSetOptimalOptions(fragment_profile); } if (shader_name.length()) { vertex_program = cgCreateProgramFromFile(cg_context, CG_SOURCE, shader_name.c_str(), vertex_profile, "VertexProgram", 0); CGerror vertex_error = cgGetError(); if (vertex_error != CG_NO_ERROR) { printf("Warning: No valid vertex program found in %s: %s\n", shader_name.c_str(), cgGetErrorString(vertex_error)); vertex_program = 0; } else { cgGLLoadProgram(vertex_program); } fragment_program = cgCreateProgramFromFile(cg_context, CG_SOURCE, shader_name.c_str(), fragment_profile, "FragmentProgram", 0); CGerror fragment_error = cgGetError(); if (fragment_error != CG_NO_ERROR) { printf("Warning: No valid fragment program found in %s: %s\n", shader_name.c_str(), cgGetErrorString(fragment_error)); fragment_program = 0; } else { cgGLLoadProgram(fragment_program); } } }
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; }
static bool d3d9_cg_load_program(void *data, void *fragment_data, void *vertex_data, const char *prog, bool path_is_file) { const char *list = NULL; char *listing_f = NULL; char *listing_v = NULL; CGprogram *fPrg = (CGprogram*)fragment_data; CGprogram *vPrg = (CGprogram*)vertex_data; CGprofile vertex_profile = cgD3D9GetLatestVertexProfile(); CGprofile fragment_profile = cgD3D9GetLatestPixelProfile(); const char **fragment_opts = cgD3D9GetOptimalOptions(fragment_profile); const char **vertex_opts = cgD3D9GetOptimalOptions(vertex_profile); cg_renderchain_t *cg_data = (cg_renderchain_t*)data; RARCH_LOG("[D3D Cg]: Vertex profile: %s\n", cgGetProfileString(vertex_profile)); RARCH_LOG("[D3D Cg]: Fragment profile: %s\n", cgGetProfileString(fragment_profile)); if (path_is_file && !string_is_empty(prog)) *fPrg = cgCreateProgramFromFile(cg_data->cgCtx, CG_SOURCE, prog, fragment_profile, "main_fragment", fragment_opts); else *fPrg = cgCreateProgram(cg_data->cgCtx, CG_SOURCE, stock_cg_d3d9_program, fragment_profile, "main_fragment", fragment_opts); list = cgGetLastListing(cg_data->cgCtx); if (list) listing_f = strdup(list); if (path_is_file && !string_is_empty(prog)) *vPrg = cgCreateProgramFromFile(cg_data->cgCtx, CG_SOURCE, prog, vertex_profile, "main_vertex", vertex_opts); else *vPrg = cgCreateProgram(cg_data->cgCtx, CG_SOURCE, stock_cg_d3d9_program, vertex_profile, "main_vertex", vertex_opts); list = cgGetLastListing(cg_data->cgCtx); if (list) listing_v = strdup(list); if (!fPrg || !vPrg) goto error; cgD3D9LoadProgram(*fPrg, true, 0); cgD3D9LoadProgram(*vPrg, true, 0); free(listing_f); free(listing_v); return true; error: RARCH_ERR("CG error: %s\n", cgGetErrorString(cgGetError())); if (listing_f) RARCH_ERR("Fragment:\n%s\n", listing_f); else if (listing_v) RARCH_ERR("Vertex:\n%s\n", listing_v); free(listing_f); free(listing_v); return false; }