//-----------------------------------------------------------------------------
bool ProgramManager::createGpuPrograms(ProgramSet* programSet)
{
	// Before we start we need to make sure that the pixel shader input
	//  parameters are the same as the vertex output, this required by 
	//  shader models 4 and 5.
	// This change may incrase the number of register used in older shader
	//  models - this is why the check is present here.
	bool isVs4 = GpuProgramManager::getSingleton().isSyntaxSupported("vs_4_0");
	if (isVs4)
	{
		synchronizePixelnToBeVertexOut(programSet);
	}

	// Grab the matching writer.
	const String& language = ShaderGenerator::getSingleton().getTargetLanguage();
	ProgramWriterIterator itWriter = mProgramWritersMap.find(language);
	ProgramWriter* programWriter = NULL;

	// No writer found -> create new one.
	if (itWriter == mProgramWritersMap.end())
	{
		programWriter = ProgramWriterManager::getSingletonPtr()->createProgramWriter(language);
		mProgramWritersMap[language] = programWriter;
	}
	else
	{
		programWriter = itWriter->second;
	}

	ProgramProcessorIterator itProcessor = mProgramProcessorsMap.find(language);
	ProgramProcessor* programProcessor = NULL;

	if (itProcessor == mProgramProcessorsMap.end())
	{
		OGRE_EXCEPT(Exception::ERR_DUPLICATE_ITEM,
			"Could not find processor for language '" + language,
			"ProgramManager::createGpuPrograms");		
	}

	programProcessor = itProcessor->second;

	bool success;
	
	// Call the pre creation of GPU programs method.
	success = programProcessor->preCreateGpuPrograms(programSet);
	if (success == false)	
		return false;	
	
	// Create the vertex shader program.
	GpuProgramPtr vsGpuProgram;
	
	vsGpuProgram = createGpuProgram(programSet->getCpuVertexProgram(), 
		programWriter,
		language, 
		ShaderGenerator::getSingleton().getVertexShaderProfiles(),
		ShaderGenerator::getSingleton().getVertexShaderProfilesList(),
		ShaderGenerator::getSingleton().getShaderCachePath());

	if (vsGpuProgram.isNull())	
		return false;

	programSet->setGpuVertexProgram(vsGpuProgram);

	//update flags
	programSet->getGpuVertexProgram()->setSkeletalAnimationIncluded(
		programSet->getCpuVertexProgram()->getSkeletalAnimationIncluded());
	// Create the fragment shader program.
	GpuProgramPtr psGpuProgram;

	psGpuProgram = createGpuProgram(programSet->getCpuFragmentProgram(), 
		programWriter,
		language, 
		ShaderGenerator::getSingleton().getFragmentShaderProfiles(),
		ShaderGenerator::getSingleton().getFragmentShaderProfilesList(),
		ShaderGenerator::getSingleton().getShaderCachePath());

	if (psGpuProgram.isNull())	
		return false;

	programSet->setGpuFragmentProgram(psGpuProgram);

	// Call the post creation of GPU programs method.
	success = programProcessor->postCreateGpuPrograms(programSet);
	if (success == false)	
		return false;	

	
	return true;
	
}
    //---------------------------------------------------------------------
    //---------------------------------------------------------------------
    void ShadowVolumeExtrudeProgram::initialise(void)
    {
		if (!mInitialised)
		{
			String syntax;
			bool vertexProgramFinite[OGRE_NUM_SHADOW_EXTRUDER_PROGRAMS] = 
			{
				false, false, false, false, 
					true, true, true, true
			};
			bool vertexProgramDebug[OGRE_NUM_SHADOW_EXTRUDER_PROGRAMS] = 
			{
				false, true, false, true, 
					false, true, false, true
			};
			Light::LightTypes vertexProgramLightTypes[OGRE_NUM_SHADOW_EXTRUDER_PROGRAMS] = 
			{
				Light::LT_POINT, Light::LT_POINT, 
					Light::LT_DIRECTIONAL, Light::LT_DIRECTIONAL, 
					Light::LT_POINT, Light::LT_POINT, 
					Light::LT_DIRECTIONAL, Light::LT_DIRECTIONAL 
			};

			// load hardware extrusion programs for point & dir lights
			if (GpuProgramManager::getSingleton().isSyntaxSupported("arbvp1"))
			{
				// ARBvp1
				syntax = "arbvp1";
			}
			else if (GpuProgramManager::getSingleton().isSyntaxSupported("vs_1_1"))
			{
				syntax = "vs_1_1";
			}
			else if (GpuProgramManager::getSingleton().isSyntaxSupported("vs_4_0"))
			{
				syntax = "vs_4_0";
			}
			else
			{
				OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
					"Vertex programs are supposedly supported, but neither "
					"arbvp1, vs_1_1 nor vs_4_0 syntaxes are present.", 
					"SceneManager::initShadowVolumeMaterials");
			}
			// Create all programs
			for (unsigned short v = 0; v < OGRE_NUM_SHADOW_EXTRUDER_PROGRAMS; ++v)
			{
				// Create debug extruders
				if (GpuProgramManager::getSingleton().getByName(
					programNames[v]).isNull())
				{
					if (syntax == "vs_4_0")
					{
						HighLevelGpuProgramPtr vp = 
							HighLevelGpuProgramManager::getSingleton().createProgram(
							programNames[v], ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME,
							"hlsl", GPT_VERTEX_PROGRAM);
						vp->setSource(ShadowVolumeExtrudeProgram::getProgramSource(
							vertexProgramLightTypes[v], syntax, 
							vertexProgramFinite[v], vertexProgramDebug[v]));
						vp->setParameter("target", syntax);
						vp->setParameter("entry_point", "vs_main");			
						vp->load();

						if (frgProgramName.empty())
						{
							frgProgramName = "Ogre/ShadowFrgProgram";
							HighLevelGpuProgramPtr fp = 
								HighLevelGpuProgramManager::getSingleton().createProgram(
								frgProgramName, ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME,
								"hlsl", GPT_FRAGMENT_PROGRAM);
							fp->setSource(mGeneralFs_4_0);
							fp->setParameter("target", "ps_4_0");
							fp->setParameter("entry_point", "fs_main");			
							fp->load();
						}
					}
					else
					{
						GpuProgramPtr vp = 
							GpuProgramManager::getSingleton().createProgramFromString(
							programNames[v], ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME,
							ShadowVolumeExtrudeProgram::getProgramSource(
							vertexProgramLightTypes[v], syntax, 
							vertexProgramFinite[v], vertexProgramDebug[v]),
							GPT_VERTEX_PROGRAM, syntax);
						vp->load();
					}

				}
			}
			mInitialised = true;
		}
    }
//-----------------------------------------------------------------------------
void GLSLProgramProcessor::bindSubShaders(Program* program, GpuProgramPtr pGpuProgram)
{
	if (program->getDependencyCount() > 0)
	{
		// Get all attached shaders so we do not attach shaders twice.
		// maybe GLSLProgram should take care of that ( prevent add duplicate shaders )
		String attachedShaders = pGpuProgram->getParameter("attach");
		String subShaderDef = "";

		for (unsigned int i=0; i < program->getDependencyCount(); ++i)
		{
			// Here we append _VS and _FS to the library shaders (so max each lib shader
			// is compiled twice once as vertex and once as fragment shader)
			String subShaderName = program->getDependency(i);
			if (program->getType() == GPT_VERTEX_PROGRAM)
			{
				subShaderName += "_VS";
			}
			else
			{
				subShaderName += "_FS";
			}					

			// Check if the library shader already compiled
			if(!HighLevelGpuProgramManager::getSingleton().resourceExists(subShaderName))
			{
				// Create the library shader
				HighLevelGpuProgramPtr pSubGpuProgram = HighLevelGpuProgramManager::getSingleton().createProgram(subShaderName,
					ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TargetLanguage, program->getType());

				// Set the source name
				String sourceName = program->getDependency(i) + "." + TargetLanguage;
				pSubGpuProgram->setSourceFile(sourceName);
                pSubGpuProgram->load();

                // Prepend the current GLSL version
                String versionLine = "#version " + StringConverter::toString(Root::getSingleton().getRenderSystem()->getNativeShadingLanguageVersion()) + "\n";
                pSubGpuProgram->setSource(versionLine + pSubGpuProgram->getSource());

				// If we have compile errors than stop processing
				if (pSubGpuProgram->hasCompileError())
				{
					OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
						"Could not compile shader library from the source file: " + sourceName, 
						"GLSLProgramProcessor::bindSubShaders" );	
				}

				mLibraryPrograms.push_back(subShaderName);
			}

			// Check if the lib shader already attached to this shader
			if (attachedShaders.find(subShaderName) == String::npos)
			{
				// Append the shader name to subShaders
				subShaderDef += subShaderName + " ";
			}
		}

		// Check if we have something to attach
		if (subShaderDef.length() > 0)
		{
			pGpuProgram->setParameter("attach", subShaderDef);
		}
	}
	
}