//----------------------------------------------------------------------- void CgProgram::createLowLevelImpl(void) { // ignore any previous error if (mSelectedCgProfile != CG_PROFILE_UNKNOWN && !mCompileError) { if ( false // the hlsl 4 profiles are only supported in OGRE from CG 2.2 #if(CG_VERSION_NUM >= 2200) || mSelectedCgProfile == CG_PROFILE_VS_4_0 || mSelectedCgProfile == CG_PROFILE_PS_4_0 #endif ) { // Create a high-level program, give it the same name as us HighLevelGpuProgramPtr vp = HighLevelGpuProgramManager::getSingleton().createProgram( mName, mGroup, "hlsl", mType); String hlslSourceFromCg = cgGetProgramString(mCgProgram, CG_COMPILED_PROGRAM); vp->setSource(hlslSourceFromCg); vp->setParameter("target", mSelectedProfile); vp->setParameter("entry_point", "main"); vp->load(); mAssemblerProgram = vp; } else { String shaderAssemblerCode = cgGetProgramString(mCgProgram, CG_COMPILED_PROGRAM); if (mType == GPT_FRAGMENT_PROGRAM) { //HACK : http://developer.nvidia.com/forums/index.php?showtopic=1063&pid=2378&mode=threaded&start=#entry2378 //Still happens in CG 2.2. Remove hack when fixed. shaderAssemblerCode = StringUtil::replaceAll(shaderAssemblerCode, "oDepth.z", "oDepth"); } // Create a low-level program, give it the same name as us mAssemblerProgram = GpuProgramManager::getSingleton().createProgramFromString( mName, mGroup, shaderAssemblerCode, mType, mSelectedProfile); } // Shader params need to be forwarded to low level implementation mAssemblerProgram->setAdjacencyInfoRequired(isAdjacencyInfoRequired()); } }
bool csShaderGLCGCommon::WriteToCache (iHierarchicalCache* cache, const ProfileLimits& limits, const ProfileLimitsPair& limitsPair, const char* tag) { csString objectCode; if (program != 0) objectCode = cgGetProgramString (program, CG_COMPILED_PROGRAM); ProgramObject programObj (objectCode, programPositionInvariant ? ProgramObject::flagPositionInvariant : 0, unusedParams); const char* preprocSource (cgGetProgramString (program, CG_PROGRAM_SOURCE)); csString failReason; ProgramObjectID progId; if (!shaderPlug->progCache.WriteObject (preprocSource, limits, programObj, progId, failReason)) { if (shaderPlug->doVerbose) { csReport (objectReg, CS_REPORTER_SEVERITY_WARNING, "crystalspace.graphics3d.shader.glcg", "Error writing %s program for %s to compile cache: %s", GetProgramType(), tag, failReason.GetData()); } return false; } programObj.SetID (progId); return WriteToCache (cache, limits, limitsPair, tag, programObj); }
bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram) { // Reset GL error before compiling shaders. Yeah, we need to investigate the causes of these. GLenum err = GL_REPORT_ERROR(); if (err != GL_NO_ERROR) { ERROR_LOG(VIDEO, "glError %08x before VS!", err); } #if defined HAVE_CG && HAVE_CG char stropt[64]; sprintf(stropt, "MaxLocalParams=256,MaxInstructions=%d", s_nMaxVertexInstructions); const char *opts[] = {"-profileopts", stropt, "-O2", "-q", NULL}; CGprogram tempprog = cgCreateProgram(g_cgcontext, CG_SOURCE, pstrprogram, g_cgvProf, "main", opts); if (!cgIsProgram(tempprog)) { if (s_displayCompileAlert) { PanicAlert("Failed to create vertex shader"); s_displayCompileAlert = false; } cgDestroyProgram(tempprog); ERROR_LOG(VIDEO, "Failed to load vs %s:", cgGetLastListing(g_cgcontext)); ERROR_LOG(VIDEO, "%s", pstrprogram); return false; } if (cgGetError() != CG_NO_ERROR) { WARN_LOG(VIDEO, "Failed to load vs %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, &vs.glprogid); SetCurrentShader(vs.glprogid); glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(pcompiledprog), pcompiledprog); err = GL_REPORT_ERROR(); if (err != GL_NO_ERROR) { ERROR_LOG(VIDEO, "%s", pstrprogram); ERROR_LOG(VIDEO, "%s", pcompiledprog); } cgDestroyProgram(tempprog); #endif #if defined(_DEBUG) || defined(DEBUGFAST) vs.strprog = pstrprogram; #endif return true; }
// // GetString // string CCgShader::GetString( CGenum Type ) const { if (Type != CG_PROGRAM_SOURCE && Type != CG_PROGRAM_ENTRY && Type != CG_PROGRAM_PROFILE && Type != CG_COMPILED_PROGRAM) throw Sys::CDeveloperException( this, "::GetString() : Invalid <Type> parameter." ); return cgGetProgramString( m_Program, Type ); }
//[-------------------------------------------------------] //[ 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 CgProgram::createLowLevelImpl(void) { // ignore any previous error if (mSelectedCgProfile != CG_PROFILE_UNKNOWN && !mCompileError) { // Create a low-level program, give it the same name as us mAssemblerProgram = GpuProgramManager::getSingleton().createProgramFromString( mName, mGroup, cgGetProgramString(mCgProgram, CG_COMPILED_PROGRAM), mType, mSelectedProfile); } }
bool csShaderGLCGCommon::LoadProgramWithPS1 () { pswrap = shaderPlug->psplg->CreateProgram ("fp"); if (!pswrap) return false; const char* objectCode = cgGetProgramString (program, CG_COMPILED_PROGRAM); if (!objectCode || !*objectCode) // Program did not actually compile return false; csArray<csShaderVarMapping> mappings; for (size_t i = 0; i < variablemap.GetSize (); i++) { // Get the Cg parameter ShaderParameter* sparam = reinterpret_cast<ShaderParameter*> (variablemap[i].userVal); // Make sure it's a C-register CGresource resource = cgGetParameterResource (sparam->param); if (resource == CG_C) { // Get the register number, and create a mapping csString regnum; regnum.Format ("c%lu", cgGetParameterResourceIndex (sparam->param)); mappings.Push (csShaderVarMapping (variablemap[i].name, regnum)); } } if (pswrap->Load (0, objectCode, mappings)) { bool ret = pswrap->Compile (0); if (shaderPlug->debugDump) DoDebugDump(); return ret; } else { 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 }
//----------------------------------------------------------------------- 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(); } } }
static bool AddPass(CGtechnique technique, JSON &json, CGpass pass, UniformsMap &uniformRemapping) { bool success = true; json.AddObject(NULL); const char * const passName = cgGetPassName(pass); if (NULL != passName) { json.AddString("name", passName); } bool firstParameter = true; #if CG_VERSION_NUM >= 3000 const int CG_NUMBER_OF_DOMAINS = (CG_TESSELLATION_EVALUATION_DOMAIN + 1); #endif for (int domain = CG_FIRST_DOMAIN; domain < CG_NUMBER_OF_DOMAINS; domain++) { const CGprogram program = cgGetPassProgram(pass, (CGdomain)domain); if (NULL != program) { const char * const programString = cgGetProgramString(program, CG_COMPILED_PROGRAM); CGparameter param = cgGetFirstParameter(program, CG_GLOBAL); while (NULL != param) { if (cgIsParameterUsed(param, program) && CG_UNIFORM == cgGetParameterVariability(param)) { if (firstParameter) { firstParameter = false; json.AddArray("parameters", true); json.BeginData(true); } const char * const paramName = cgGetParameterName(param); AddMappedParameter(json, paramName, programString, uniformRemapping); } param = cgGetNextParameter(param); } param = cgGetFirstParameter(program, CG_PROGRAM); while (NULL != param) { if (cgIsParameterUsed(param, program) && CG_UNIFORM == cgGetParameterVariability(param)) { if (firstParameter) { firstParameter = false; json.AddArray("parameters", true); json.BeginData(true); } const char * const paramName = cgGetParameterName(param); AddMappedParameter(json, paramName, programString, uniformRemapping); } param = cgGetNextParameter(param); } } } if (!firstParameter) { json.EndData(); json.CloseArray(true); // parameters } json.AddArray("semantics", true); json.BeginData(true); CGprogram vertexProgram = cgGetPassProgram(pass, CG_VERTEX_DOMAIN); CGparameter vertexInputParameter = cgGetFirstLeafParameter(vertexProgram, CG_PROGRAM); while (NULL != vertexInputParameter) { const CGenum variability = cgGetParameterVariability(vertexInputParameter); if (CG_VARYING == variability) { const CGenum direction = cgGetParameterDirection(vertexInputParameter); if (CG_IN == direction || CG_INOUT == direction) { const char * const semantic = cgGetParameterSemantic(vertexInputParameter); json.AddData(semantic, strlen(semantic)); } } vertexInputParameter = cgGetNextLeafParameter(vertexInputParameter); } json.EndData(); json.CloseArray(true); // semantics json.AddObject("states"); CGstateassignment state = cgGetFirstStateAssignment(pass); if (NULL != state) { do { success &= AddState(json, state); state = cgGetNextStateAssignment(state); } while (NULL != state); } json.CloseObject(); // states json.AddArray("programs", true); json.BeginData(true); for (int domain = CG_FIRST_DOMAIN; domain < CG_NUMBER_OF_DOMAINS; domain++) { const CGprogram program = cgGetPassProgram(pass, (CGdomain)domain); if (NULL != program) { const char * const entryPoint = cgGetProgramString(program, CG_PROGRAM_ENTRY); json.AddData(entryPoint, strlen(entryPoint)); } else if (domain == CG_VERTEX_DOMAIN) { ErrorMessage("%s : No vertex program.", cgGetTechniqueName(technique)); success = false; } else if(domain == CG_FRAGMENT_DOMAIN) { ErrorMessage("%s : No fragment program.", cgGetTechniqueName(technique)); success = false; } } json.EndData(); json.CloseArray(true); // programs json.CloseObject(); // pass return success; }
void csShaderGLCGCommon::DoDebugDump () { csString output; DumpProgramInfo (output); output << "CG program type: " << programType << "\n"; output << "CG profile: " << cgGetProgramString (program, CG_PROGRAM_PROFILE) << "\n"; output << "CG entry point: " << (entrypoint ? entrypoint : "main") << "\n"; output << "CG program valid: " << IsValid() << "\n"; output << "\n"; output << "Variable mappings:\n"; for (size_t v = 0; v < variablemap.GetSize (); v++) { const VariableMapEntry& vme = variablemap[v]; ShaderParameter* sparam = reinterpret_cast<ShaderParameter*> (vme.userVal); output << stringsSvName->Request (vme.name); output << '(' << vme.name << ") -> "; output << vme.destination << ' '; if (sparam == 0) { output << "(null)"; } else { if (sparam->paramType != 0) output << cgGetTypeString (sparam->paramType) << ' '; if (sparam->param != 0) output << cgGetParameterName (sparam->param) << " "; output << "baseslot " << sparam->baseSlot; if (sparam->assumeConstant) output << " assumed constant"; } output << '\n'; } output << "\n"; output << "Program leaf parameters:\n"; CGparameter param = cgGetFirstLeafParameter (program, CG_PROGRAM); while (param) { DebugDumpParam (output, param); param = cgGetNextLeafParameter (param); } output << "\n"; output << "Program global parameters:\n"; param = cgGetFirstLeafParameter (program, CG_GLOBAL); while (param) { DebugDumpParam (output, param); param = cgGetNextLeafParameter (param); } output << "\n"; output << "Program source:\n"; output << cgGetProgramString (program, CG_PROGRAM_SOURCE); output << "\n"; output << "Compiled program:\n"; output << cgGetProgramString (program, CG_COMPILED_PROGRAM); output << "\n"; csRef<iVFS> vfs = csQueryRegistry<iVFS> (objectReg); EnsureDumpFile(); csRef<iFile> debugFile = vfs->Open (debugFN, VFS_FILE_APPEND); if (!debugFile) { csReport (objectReg, CS_REPORTER_SEVERITY_WARNING, "crystalspace.graphics3d.shader.glcg", "Could not write %s", CS::Quote::Single (debugFN.GetData())); } else { debugFile->Write (output.GetData(), output.Length ()); csReport (objectReg, CS_REPORTER_SEVERITY_NOTIFY, "crystalspace.graphics3d.shader.glcg", "Dumped Cg program info to %s", CS::Quote::Single (debugFN.GetData())); } }
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; }
String FragmentShaderCg::GetSourceCode() const { return m_pCgFragmentProgram ? cgGetProgramString(m_pCgFragmentProgram, CG_PROGRAM_SOURCE) : ""; }
cCgShaderHelper::cCgShaderHelper(const zsString& shaderPath) { cFileUtil::ReplaceIncludeDirectives(shaderPath, cgFileLines, includedFilesPaths); // Setup context, for creation (Yeah silly, but use OpenGL cg state and params) because equal with dx... CGcontext con = cgCreateContext(); cgGLRegisterStates(con); cgGLSetManageTextureParameters(con, CG_TRUE); // Create cg effect from file (load) assert(shaderPath.size() <= 256); char ansiShaderPath[256]; cStrUtil::ToAnsi(shaderPath, ansiShaderPath, 256); CGeffect effect = cgCreateEffectFromFile(con, ansiShaderPath, nullptr); if (effect == nullptr) { lastErrorMsg = cgGetLastListing(con); // Free up cgDestroyEffect(effect); cgDestroyContext(con); return; } // Tech creation CGtechnique tech = cgGetFirstTechnique(effect); if (tech == nullptr) { lastErrorMsg = L"There is no Technique in shader: " + shaderPath; // Free up cgDestroyEffect(effect); cgDestroyContext(con); return; } // Pass creation CGpass pass = cgGetFirstPass(tech); if (pass == nullptr) { lastErrorMsg = L"There is no pass in shader: " + shaderPath; // Free up cgDestroyEffect(effect); cgDestroyContext(con); return; } CGprogram shaderPrograms[NDOMAINS]; shaderPrograms[VS] = cgGetPassProgram(pass, CGdomain::CG_VERTEX_DOMAIN); shaderPrograms[HS] = cgGetPassProgram(pass, CGdomain::CG_TESSELLATION_CONTROL_DOMAIN); shaderPrograms[DS] = cgGetPassProgram(pass, CGdomain::CG_TESSELLATION_EVALUATION_DOMAIN); shaderPrograms[GS] = cgGetPassProgram(pass, CGdomain::CG_GEOMETRY_DOMAIN); shaderPrograms[PS] = cgGetPassProgram(pass, CGdomain::CG_FRAGMENT_DOMAIN); // Domain infos for (uint8_t i = 0; i < NDOMAINS; i++) { // Domain existence info.domainsExist[i] = shaderPrograms[i] != nullptr; // if exist save entry name if (info.domainsExist[i]) info.domainsEntry[i] = cgGetProgramString(shaderPrograms[i], CGenum::CG_PROGRAM_ENTRY); } // Free up cgDestroyEffect(effect); cgDestroyContext(con); }