Пример #1
0
    //-----------------------------------------------------------------------
    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());
		}
    }
Пример #2
0
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);
}
Пример #3
0
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;
}
Пример #4
0
    //
    // 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 ); 
    }
Пример #5
0
//[-------------------------------------------------------]
//[ 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;
	}
}
Пример #6
0
    //-----------------------------------------------------------------------
    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);
		}
    }
Пример #7
0
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;
  }
}
Пример #8
0
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
}
Пример #9
0
	//-----------------------------------------------------------------------
	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();
			}
		}


	}
Пример #10
0
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;
}
Пример #11
0
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()));
  }
}
Пример #12
0
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;
}
Пример #13
0
String FragmentShaderCg::GetSourceCode() const
{
	return m_pCgFragmentProgram ? cgGetProgramString(m_pCgFragmentProgram, CG_PROGRAM_SOURCE) : "";
}
Пример #14
0
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);
}