1 /*
2  -----------------------------------------------------------------------------
3  This source file is part of OGRE
4  (Object-oriented Graphics Rendering Engine)
5  For the latest info, see http://www.ogre3d.org/
6 
7  Copyright (c) 2000-2013 Torus Knot Software Ltd
8 
9  Permission is hereby granted, free of charge, to any person obtaining a copy
10  of this software and associated documentation files (the "Software"), to deal
11  in the Software without restriction, including without limitation the rights
12  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  copies of the Software, and to permit persons to whom the Software is
14  furnished to do so, subject to the following conditions:
15 
16  The above copyright notice and this permission notice shall be included in
17  all copies or substantial portions of the Software.
18 
19  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25  THE SOFTWARE.
26  -----------------------------------------------------------------------------
27  */
28 
29 #include "OgreGLSLProgramPipeline.h"
30 #include "OgreStringConverter.h"
31 #include "OgreGLSLGpuProgram.h"
32 #include "OgreGLSLProgram.h"
33 #include "OgreGLSLProgramPipelineManager.h"
34 #include "OgreGpuProgramManager.h"
35 #include "OgreGL3PlusUtil.h"
36 #include "OgreLogManager.h"
37 
38 namespace Ogre
39 {
GLSLProgramPipeline(GLSLGpuProgram * vertexProgram,GLSLGpuProgram * geometryProgram,GLSLGpuProgram * fragmentProgram,GLSLGpuProgram * hullProgram,GLSLGpuProgram * domainProgram,GLSLGpuProgram * computeProgram)40     GLSLProgramPipeline::GLSLProgramPipeline(GLSLGpuProgram* vertexProgram, GLSLGpuProgram* geometryProgram, GLSLGpuProgram* fragmentProgram, GLSLGpuProgram* hullProgram, GLSLGpuProgram* domainProgram, GLSLGpuProgram* computeProgram) :
41     GLSLProgramCommon(vertexProgram, geometryProgram, fragmentProgram, hullProgram, domainProgram, computeProgram) { }
42 
~GLSLProgramPipeline()43     GLSLProgramPipeline::~GLSLProgramPipeline()
44     {
45         OGRE_CHECK_GL_ERROR(glDeleteProgramPipelines(1, &mGLProgramPipelineHandle));
46     }
47 
compileAndLink()48     void GLSLProgramPipeline::compileAndLink()
49 	{
50         OGRE_CHECK_GL_ERROR(glGenProgramPipelines(1, &mGLProgramPipelineHandle));
51         OGRE_CHECK_GL_ERROR(glBindProgramPipeline(mGLProgramPipelineHandle));
52 
53         mVertexArrayObject = new GL3PlusVertexArrayObject();
54         mVertexArrayObject->bind();
55 
56         compileIndividualProgram(mVertexProgram);
57         compileIndividualProgram(mFragmentProgram);
58         compileIndividualProgram(mGeometryProgram);
59         compileIndividualProgram(mDomainProgram);
60         compileIndividualProgram(mHullProgram);
61         compileIndividualProgram(mComputeProgram);
62 
63 		if(mLinked)
64 		{
65 			if ( GpuProgramManager::getSingleton().getSaveMicrocodesToCache() )
66 			{
67 				// Add to the microcode to the cache
68 				String name;
69 				name = getCombinedName();
70 
71 				// Get buffer size
72 				GLint binaryLength = 0;
73 
74 				OGRE_CHECK_GL_ERROR(glGetProgramiv(mGLProgramPipelineHandle, GL_PROGRAM_BINARY_LENGTH, &binaryLength));
75 
76                 // Create microcode
77                 GpuProgramManager::Microcode newMicrocode =
78                     GpuProgramManager::getSingleton().createMicrocode(binaryLength + sizeof(GLenum));
79 
80 				// Get binary
81 				OGRE_CHECK_GL_ERROR(glGetProgramBinary(mGLProgramPipelineHandle, binaryLength, NULL, (GLenum *)newMicrocode->getPtr(), newMicrocode->getPtr() + sizeof(GLenum)));
82 
83         		// Add to the microcode to the cache
84 				GpuProgramManager::getSingleton().addMicrocodeToCache(name, newMicrocode);
85 			}
86             if(mVertexProgram && mVertexProgram->isLinked())
87             {
88                 OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_VERTEX_SHADER_BIT, mVertexProgram->getGLSLProgram()->getGLProgramHandle()));
89             }
90             if(mFragmentProgram && mFragmentProgram->isLinked())
91             {
92                 OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_FRAGMENT_SHADER_BIT, mFragmentProgram->getGLSLProgram()->getGLProgramHandle()));
93             }
94             if(mGeometryProgram && mGeometryProgram->isLinked())
95             {
96                 OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_GEOMETRY_SHADER_BIT, mGeometryProgram->getGLSLProgram()->getGLProgramHandle()));
97             }
98             if(mDomainProgram && mDomainProgram->isLinked())
99             {
100                 OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_TESS_EVALUATION_SHADER_BIT, mDomainProgram->getGLSLProgram()->getGLProgramHandle()));
101             }
102             if(mHullProgram && mHullProgram->isLinked())
103             {
104                 OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_TESS_CONTROL_SHADER_BIT, mHullProgram->getGLSLProgram()->getGLProgramHandle()));
105             }
106             if(mComputeProgram && mComputeProgram->isLinked())
107             {
108                 OGRE_CHECK_GL_ERROR(glUseProgramStages(mGLProgramPipelineHandle, GL_COMPUTE_SHADER_BIT, mComputeProgram->getGLSLProgram()->getGLProgramHandle()));
109             }
110 
111             // Validate pipeline
112             logObjectInfo( getCombinedName() + String("GLSL program pipeline result : "), mGLProgramPipelineHandle );
113 
114 //            if(getGLSupport()->checkExtension("GL_KHR_debug") || gl3wIsSupported(4, 3))
115 //                glObjectLabel(GL_PROGRAM_PIPELINE, mGLProgramPipelineHandle, 0,
116 //                                 (mVertexProgram->getName() + "/" + mFragmentProgram->getName()).c_str());
117 		}
118 	}
119 
compileIndividualProgram(GLSLGpuProgram * program)120     void GLSLProgramPipeline::compileIndividualProgram(GLSLGpuProgram *program)
121     {
122         GLint linkStatus = 0;
123 		// Compile and attach program
124         if(program && !program->isLinked())
125         {
126             try
127             {
128                 program->getGLSLProgram()->compile(true);
129             }
130             catch (Exception& e)
131             {
132 				LogManager::getSingleton().stream() << e.getDescription();
133                 mTriedToLinkAndFailed = true;
134                 return;
135             }
136             GLuint programHandle = program->getGLSLProgram()->getGLProgramHandle();
137             OGRE_CHECK_GL_ERROR(glProgramParameteri(programHandle, GL_PROGRAM_SEPARABLE, GL_TRUE));
138             program->getGLSLProgram()->attachToProgramObject(programHandle);
139             OGRE_CHECK_GL_ERROR(glLinkProgram(programHandle));
140             OGRE_CHECK_GL_ERROR(glGetProgramiv(programHandle, GL_LINK_STATUS, &linkStatus));
141 
142             program->setLinked(linkStatus);
143             mLinked = linkStatus;
144 
145             mTriedToLinkAndFailed = !linkStatus;
146 
147             logObjectInfo( getCombinedName() + String("GLSL program result : "), programHandle );
148 
149             if(program->getType() == GPT_VERTEX_PROGRAM)
150                 setSkeletalAnimationIncluded(program->isSkeletalAnimationIncluded());
151         }
152     }
153 
_useProgram(void)154     void GLSLProgramPipeline::_useProgram(void)
155     {
156 		if (mLinked)
157 		{
158             OGRE_CHECK_GL_ERROR(glBindProgramPipeline(mGLProgramPipelineHandle));
159 		}
160     }
161 
162 	//-----------------------------------------------------------------------
getAttributeIndex(VertexElementSemantic semantic,uint index)163 	GLint GLSLProgramPipeline::getAttributeIndex(VertexElementSemantic semantic, uint index)
164 	{
165 		GLint res = mCustomAttributesIndexes[semantic-1][index];
166 		if (res == NULL_CUSTOM_ATTRIBUTES_INDEX)
167 		{
168             GLuint handle = mVertexProgram->getGLSLProgram()->getGLProgramHandle();
169 			const char * attString = getAttributeSemanticString(semantic);
170 			GLint attrib;
171             OGRE_CHECK_GL_ERROR(attrib = glGetAttribLocation(handle, attString));
172 
173 			// Sadly position is a special case
174 			if (attrib == NOT_FOUND_CUSTOM_ATTRIBUTES_INDEX && semantic == VES_POSITION)
175 			{
176 				OGRE_CHECK_GL_ERROR(attrib = glGetAttribLocation(handle, "position"));
177 			}
178 
179 			// For uv and other case the index is a part of the name
180 			if (attrib == NOT_FOUND_CUSTOM_ATTRIBUTES_INDEX)
181 			{
182 				String attStringWithSemantic = String(attString) + StringConverter::toString(index);
183 				OGRE_CHECK_GL_ERROR(attrib = glGetAttribLocation(handle, attStringWithSemantic.c_str()));
184 			}
185 
186 			// Update mCustomAttributesIndexes with the index we found (or didn't find)
187 			mCustomAttributesIndexes[semantic-1][index] = attrib;
188 			res = attrib;
189 		}
190 
191 		return res;
192 	}
193 
194     //-----------------------------------------------------------------------
activate(void)195 	void GLSLProgramPipeline::activate(void)
196 	{
197 		if (!mLinked && !mTriedToLinkAndFailed)
198 		{
199 			if ( GpuProgramManager::getSingleton().canGetCompiledShaderBuffer() &&
200 				GpuProgramManager::getSingleton().isMicrocodeAvailableInCache(getCombinedName()) )
201 			{
202 				getMicrocodeFromCache();
203 			}
204 			else
205 			{
206 				compileAndLink();
207 			}
208 
209             extractLayoutQualifiers();
210 
211 			buildGLUniformReferences();
212 		}
213 
214         _useProgram();
215 	}
216 
217     //-----------------------------------------------------------------------
updateUniformBlocks(GpuProgramParametersSharedPtr params,uint16 mask,GpuProgramType fromProgType)218 	void GLSLProgramPipeline::updateUniformBlocks(GpuProgramParametersSharedPtr params,
219                                               uint16 mask, GpuProgramType fromProgType)
220 	{
221         // Iterate through the list of uniform buffers and update them as needed
222 		GLUniformBufferIterator currentBuffer = mGLUniformBufferReferences.begin();
223 		GLUniformBufferIterator endBuffer = mGLUniformBufferReferences.end();
224 
225         const GpuProgramParameters::GpuSharedParamUsageList& sharedParams = params->getSharedParameters();
226 
227 		GpuProgramParameters::GpuSharedParamUsageList::const_iterator it, end = sharedParams.end();
228 		for (it = sharedParams.begin(); it != end; ++it)
229         {
230             for (;currentBuffer != endBuffer; ++currentBuffer)
231             {
232                 GL3PlusHardwareUniformBuffer* hwGlBuffer = static_cast<GL3PlusHardwareUniformBuffer*>(currentBuffer->get());
233                 GpuSharedParametersPtr paramsPtr = it->getSharedParams();
234 
235                 // Block name is stored in mSharedParams->mName of GpuSharedParamUsageList items
236                 GLint UniformTransform;
237                 OGRE_CHECK_GL_ERROR(UniformTransform = glGetUniformBlockIndex(mGLProgramHandle, it->getName().c_str()));
238                 OGRE_CHECK_GL_ERROR(glUniformBlockBinding(mGLProgramHandle, UniformTransform, hwGlBuffer->getGLBufferBinding()));
239 
240                 hwGlBuffer->writeData(0, hwGlBuffer->getSizeInBytes(), &paramsPtr->getFloatConstantList().front());
241             }
242         }
243 	}
244 
245     //-----------------------------------------------------------------------
buildGLUniformReferences(void)246 	void GLSLProgramPipeline::buildGLUniformReferences(void)
247 	{
248 		if (!mUniformRefsBuilt)
249 		{
250 			const GpuConstantDefinitionMap* vertParams = 0;
251 			const GpuConstantDefinitionMap* fragParams = 0;
252 			const GpuConstantDefinitionMap* geomParams = 0;
253 			const GpuConstantDefinitionMap* hullParams = 0;
254 			const GpuConstantDefinitionMap* domainParams = 0;
255 			const GpuConstantDefinitionMap* computeParams = 0;
256 			if (mVertexProgram)
257 			{
258 				vertParams = &(mVertexProgram->getGLSLProgram()->getConstantDefinitions().map);
259                 GLSLProgramPipelineManager::getSingleton().extractUniforms(mVertexProgram->getGLSLProgram()->getGLProgramHandle(),
260                                                                            vertParams, NULL, NULL, NULL, NULL, NULL, mGLUniformReferences, mGLUniformBufferReferences);
261 			}
262 			if (mGeometryProgram)
263 			{
264 				geomParams = &(mGeometryProgram->getGLSLProgram()->getConstantDefinitions().map);
265                 GLSLProgramPipelineManager::getSingleton().extractUniforms(mGeometryProgram->getGLSLProgram()->getGLProgramHandle(),
266                                                                            NULL, geomParams, NULL, NULL, NULL, NULL, mGLUniformReferences, mGLUniformBufferReferences);
267 			}
268 			if (mFragmentProgram)
269 			{
270 				fragParams = &(mFragmentProgram->getGLSLProgram()->getConstantDefinitions().map);
271                 GLSLProgramPipelineManager::getSingleton().extractUniforms(mFragmentProgram->getGLSLProgram()->getGLProgramHandle(),
272                                                                            NULL, NULL, fragParams, NULL, NULL, NULL, mGLUniformReferences, mGLUniformBufferReferences);
273 			}
274 			if (mHullProgram)
275 			{
276 				hullParams = &(mHullProgram->getGLSLProgram()->getConstantDefinitions().map);
277                 GLSLProgramPipelineManager::getSingleton().extractUniforms(mHullProgram->getGLSLProgram()->getGLProgramHandle(),
278                                                                            NULL, NULL, NULL, hullParams, NULL, NULL, mGLUniformReferences, mGLUniformBufferReferences);
279 			}
280 			if (mDomainProgram)
281 			{
282 				domainParams = &(mDomainProgram->getGLSLProgram()->getConstantDefinitions().map);
283                 GLSLProgramPipelineManager::getSingleton().extractUniforms(mDomainProgram->getGLSLProgram()->getGLProgramHandle(),
284                                                                            NULL, NULL, NULL, NULL, domainParams, NULL, mGLUniformReferences, mGLUniformBufferReferences);
285 			}
286 			if (mComputeProgram)
287 			{
288 				computeParams = &(mComputeProgram->getGLSLProgram()->getConstantDefinitions().map);
289                 GLSLProgramPipelineManager::getSingleton().extractUniforms(mComputeProgram->getGLSLProgram()->getGLProgramHandle(),
290                                                                            NULL, NULL, NULL, NULL, NULL, computeParams, mGLUniformReferences, mGLUniformBufferReferences);
291 			}
292 
293 			mUniformRefsBuilt = true;
294 		}
295 	}
296 
297 	//-----------------------------------------------------------------------
updateUniforms(GpuProgramParametersSharedPtr params,uint16 mask,GpuProgramType fromProgType)298 	void GLSLProgramPipeline::updateUniforms(GpuProgramParametersSharedPtr params,
299                                            uint16 mask, GpuProgramType fromProgType)
300 	{
301 		// Iterate through uniform reference list and update uniform values
302 		GLUniformReferenceIterator currentUniform = mGLUniformReferences.begin();
303 		GLUniformReferenceIterator endUniform = mGLUniformReferences.end();
304 
305         // determine if we need to transpose matrices when binding
306         int transpose = GL_TRUE;
307         if ((fromProgType == GPT_FRAGMENT_PROGRAM && mVertexProgram && (!mVertexProgram->getGLSLProgram()->getColumnMajorMatrices())) ||
308             (fromProgType == GPT_VERTEX_PROGRAM && mFragmentProgram && (!mFragmentProgram->getGLSLProgram()->getColumnMajorMatrices())) ||
309             (fromProgType == GPT_GEOMETRY_PROGRAM && mGeometryProgram && (!mGeometryProgram->getGLSLProgram()->getColumnMajorMatrices())) ||
310             (fromProgType == GPT_HULL_PROGRAM && mHullProgram && (!mHullProgram->getGLSLProgram()->getColumnMajorMatrices())) ||
311             (fromProgType == GPT_DOMAIN_PROGRAM && mDomainProgram && (!mDomainProgram->getGLSLProgram()->getColumnMajorMatrices())) ||
312             (fromProgType == GPT_COMPUTE_PROGRAM && mComputeProgram && (!mComputeProgram->getGLSLProgram()->getColumnMajorMatrices())))
313         {
314             transpose = GL_FALSE;
315         }
316 
317         GLuint progID = 0;
318         if(fromProgType == GPT_VERTEX_PROGRAM)
319         {
320             progID = mVertexProgram->getGLSLProgram()->getGLProgramHandle();
321         }
322         else if(fromProgType == GPT_FRAGMENT_PROGRAM)
323         {
324             progID = mFragmentProgram->getGLSLProgram()->getGLProgramHandle();
325         }
326         else if(fromProgType == GPT_GEOMETRY_PROGRAM)
327         {
328             progID = mGeometryProgram->getGLSLProgram()->getGLProgramHandle();
329         }
330         else if(fromProgType == GPT_HULL_PROGRAM)
331         {
332             progID = mHullProgram->getGLSLProgram()->getGLProgramHandle();
333         }
334         else if(fromProgType == GPT_DOMAIN_PROGRAM)
335         {
336             progID = mDomainProgram->getGLSLProgram()->getGLProgramHandle();
337         }
338         else if(fromProgType == GPT_COMPUTE_PROGRAM)
339         {
340             progID = mComputeProgram->getGLSLProgram()->getGLProgramHandle();
341         }
342 
343 		for (;currentUniform != endUniform; ++currentUniform)
344 		{
345 			// Only pull values from buffer it's supposed to be in (vertex or fragment)
346 			// This method will be called twice, once for vertex program params,
347 			// and once for fragment program params.
348 			if (fromProgType == currentUniform->mSourceProgType)
349 			{
350 				const GpuConstantDefinition* def = currentUniform->mConstantDef;
351 				if (def->variability & mask)
352 				{
353 					GLsizei glArraySize = (GLsizei)def->arraySize;
354 
355 					// Get the index in the parameter real list
356 					switch (def->constType)
357 					{
358                         case GCT_FLOAT1:
359                             OGRE_CHECK_GL_ERROR(glProgramUniform1fv(progID, currentUniform->mLocation, glArraySize,
360                                                                     params->getFloatPointer(def->physicalIndex)));
361                             break;
362                         case GCT_FLOAT2:
363                             OGRE_CHECK_GL_ERROR(glProgramUniform2fv(progID, currentUniform->mLocation, glArraySize,
364                                                                     params->getFloatPointer(def->physicalIndex)));
365                             break;
366                         case GCT_FLOAT3:
367                             OGRE_CHECK_GL_ERROR(glProgramUniform3fv(progID, currentUniform->mLocation, glArraySize,
368                                                                     params->getFloatPointer(def->physicalIndex)));
369                             break;
370                         case GCT_FLOAT4:
371                             OGRE_CHECK_GL_ERROR(glProgramUniform4fv(progID, currentUniform->mLocation, glArraySize,
372                                                                     params->getFloatPointer(def->physicalIndex)));
373                             break;
374                         case GCT_MATRIX_2X2:
375                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix2fv(progID, currentUniform->mLocation, glArraySize,
376                                                                           transpose, params->getFloatPointer(def->physicalIndex)));
377                             break;
378                         case GCT_MATRIX_3X3:
379                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix3fv(progID, currentUniform->mLocation, glArraySize,
380                                                                           transpose, params->getFloatPointer(def->physicalIndex)));
381                             break;
382                         case GCT_MATRIX_4X4:
383                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix4fv(progID, currentUniform->mLocation, glArraySize,
384                                                                           transpose, params->getFloatPointer(def->physicalIndex)));
385                             break;
386                         case GCT_INT1:
387                             OGRE_CHECK_GL_ERROR(glProgramUniform1iv(progID, currentUniform->mLocation, glArraySize,
388                                                                     params->getIntPointer(def->physicalIndex)));
389                             break;
390                         case GCT_INT2:
391                             OGRE_CHECK_GL_ERROR(glProgramUniform2iv(progID, currentUniform->mLocation, glArraySize,
392                                                                     params->getIntPointer(def->physicalIndex)));
393                             break;
394                         case GCT_INT3:
395                             OGRE_CHECK_GL_ERROR(glProgramUniform3iv(progID, currentUniform->mLocation, glArraySize,
396                                                                     params->getIntPointer(def->physicalIndex)));
397                             break;
398                         case GCT_INT4:
399                             OGRE_CHECK_GL_ERROR(glProgramUniform4iv(progID, currentUniform->mLocation, glArraySize,
400                                                                     params->getIntPointer(def->physicalIndex)));
401                             break;
402                         case GCT_MATRIX_2X3:
403                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix2x3fv(progID, currentUniform->mLocation, glArraySize,
404                                                                             transpose, params->getFloatPointer(def->physicalIndex)));
405                             break;
406                         case GCT_MATRIX_2X4:
407                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix2x4fv(progID, currentUniform->mLocation, glArraySize,
408                                                                             transpose, params->getFloatPointer(def->physicalIndex)));
409                             break;
410                         case GCT_MATRIX_3X2:
411                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix3x2fv(progID, currentUniform->mLocation, glArraySize,
412                                                                             transpose, params->getFloatPointer(def->physicalIndex)));
413                             break;
414                         case GCT_MATRIX_3X4:
415                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix3x4fv(progID, currentUniform->mLocation, glArraySize,
416                                                                             transpose, params->getFloatPointer(def->physicalIndex)));
417                             break;
418                         case GCT_MATRIX_4X2:
419                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix4x2fv(progID, currentUniform->mLocation, glArraySize,
420                                                                             transpose, params->getFloatPointer(def->physicalIndex)));
421                             break;
422                         case GCT_MATRIX_4X3:
423                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix4x3fv(progID, currentUniform->mLocation, glArraySize,
424                                                                             transpose, params->getFloatPointer(def->physicalIndex)));
425                             break;
426                         case GCT_DOUBLE1:
427                             OGRE_CHECK_GL_ERROR(glProgramUniform1dv(progID, currentUniform->mLocation, glArraySize,
428                                                                     params->getDoublePointer(def->physicalIndex)));
429                             break;
430                         case GCT_DOUBLE2:
431                             OGRE_CHECK_GL_ERROR(glProgramUniform2dv(progID, currentUniform->mLocation, glArraySize,
432                                                                     params->getDoublePointer(def->physicalIndex)));
433                             break;
434                         case GCT_DOUBLE3:
435                             OGRE_CHECK_GL_ERROR(glProgramUniform3dv(progID, currentUniform->mLocation, glArraySize,
436                                                                     params->getDoublePointer(def->physicalIndex)));
437                             break;
438                         case GCT_DOUBLE4:
439                             OGRE_CHECK_GL_ERROR(glProgramUniform4dv(progID, currentUniform->mLocation, glArraySize,
440                                                                     params->getDoublePointer(def->physicalIndex)));
441                             break;
442                         case GCT_MATRIX_DOUBLE_2X2:
443                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix2dv(progID, currentUniform->mLocation, glArraySize,
444                                                                           transpose, params->getDoublePointer(def->physicalIndex)));
445                             break;
446                         case GCT_MATRIX_DOUBLE_3X3:
447                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix3dv(progID, currentUniform->mLocation, glArraySize,
448                                                                           transpose, params->getDoublePointer(def->physicalIndex)));
449                             break;
450                         case GCT_MATRIX_DOUBLE_4X4:
451                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix4dv(progID, currentUniform->mLocation, glArraySize,
452                                                                           transpose, params->getDoublePointer(def->physicalIndex)));
453                             break;
454                         case GCT_MATRIX_DOUBLE_2X3:
455                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix2x3dv(progID, currentUniform->mLocation, glArraySize,
456                                                                             transpose, params->getDoublePointer(def->physicalIndex)));
457                             break;
458                         case GCT_MATRIX_DOUBLE_2X4:
459                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix2x4dv(progID, currentUniform->mLocation, glArraySize,
460                                                                             transpose, params->getDoublePointer(def->physicalIndex)));
461                             break;
462                         case GCT_MATRIX_DOUBLE_3X2:
463                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix3x2dv(progID, currentUniform->mLocation, glArraySize,
464                                                                             transpose, params->getDoublePointer(def->physicalIndex)));
465                             break;
466                         case GCT_MATRIX_DOUBLE_3X4:
467                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix3x4dv(progID, currentUniform->mLocation, glArraySize,
468                                                                             transpose, params->getDoublePointer(def->physicalIndex)));
469                             break;
470                         case GCT_MATRIX_DOUBLE_4X2:
471                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix4x2dv(progID, currentUniform->mLocation, glArraySize,
472                                                                             transpose, params->getDoublePointer(def->physicalIndex)));
473                             break;
474                         case GCT_MATRIX_DOUBLE_4X3:
475                             OGRE_CHECK_GL_ERROR(glProgramUniformMatrix4x3dv(progID, currentUniform->mLocation, glArraySize,
476                                                                             transpose, params->getDoublePointer(def->physicalIndex)));
477                             break;
478                         case GCT_SAMPLER1D:
479                         case GCT_SAMPLER1DSHADOW:
480                         case GCT_SAMPLER2D:
481                         case GCT_SAMPLER2DSHADOW:
482                         case GCT_SAMPLER2DARRAY:
483                         case GCT_SAMPLER3D:
484                         case GCT_SAMPLERCUBE:
485                         case GCT_SAMPLERRECT:
486                             // Samplers handled like 1-element ints
487                             OGRE_CHECK_GL_ERROR(glProgramUniform1iv(progID, currentUniform->mLocation, 1,
488                                                                     params->getIntPointer(def->physicalIndex)));
489                             break;
490                         case GCT_UNKNOWN:
491                         case GCT_SUBROUTINE:
492                             break;
493 
494 					} // End switch
495 				} // Variability & mask
496 			} // fromProgType == currentUniform->mSourceProgType
497 
498   		} // End for
499 	}
500 	//-----------------------------------------------------------------------
updatePassIterationUniforms(GpuProgramParametersSharedPtr params)501 	void GLSLProgramPipeline::updatePassIterationUniforms(GpuProgramParametersSharedPtr params)
502 	{
503 		if (params->hasPassIterationNumber())
504 		{
505 			size_t index = params->getPassIterationNumberIndex();
506 
507 			GLUniformReferenceIterator currentUniform = mGLUniformReferences.begin();
508 			GLUniformReferenceIterator endUniform = mGLUniformReferences.end();
509 
510 			// Need to find the uniform that matches the multi pass entry
511 			for (;currentUniform != endUniform; ++currentUniform)
512 			{
513 				// Get the index in the parameter real list
514 				if (index == currentUniform->mConstantDef->physicalIndex)
515 				{
516                     GLuint progID = 0;
517                     if (mVertexProgram && currentUniform->mSourceProgType == GPT_VERTEX_PROGRAM)
518                     {
519                         progID = mVertexProgram->getGLSLProgram()->getGLProgramHandle();
520                     }
521 
522                     if (mFragmentProgram && currentUniform->mSourceProgType == GPT_FRAGMENT_PROGRAM)
523                     {
524                         progID = mFragmentProgram->getGLSLProgram()->getGLProgramHandle();
525                     }
526 
527                     if (mGeometryProgram && currentUniform->mSourceProgType == GPT_GEOMETRY_PROGRAM)
528                     {
529                         progID = mGeometryProgram->getGLSLProgram()->getGLProgramHandle();
530                     }
531 
532                     if (mDomainProgram && currentUniform->mSourceProgType == GPT_DOMAIN_PROGRAM)
533                     {
534                         progID = mDomainProgram->getGLSLProgram()->getGLProgramHandle();
535                     }
536 
537                     if (mHullProgram && currentUniform->mSourceProgType == GPT_HULL_PROGRAM)
538                     {
539                         progID = mHullProgram->getGLSLProgram()->getGLProgramHandle();
540                     }
541 
542                     if (mComputeProgram && currentUniform->mSourceProgType == GPT_COMPUTE_PROGRAM)
543                     {
544                         progID = mComputeProgram->getGLSLProgram()->getGLProgramHandle();
545                     }
546 
547                     OGRE_CHECK_GL_ERROR(glProgramUniform1fv(progID, currentUniform->mLocation, 1, params->getFloatPointer(index)));
548 
549                     // There will only be one multipass entry
550 					return;
551 				}
552 			}
553 		}
554     }
555 }
556