• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Program.cpp: Implements the Program class. Implements GL program objects
16 // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
17 
18 #include "Program.h"
19 
20 #include "main.h"
21 #include "Buffer.h"
22 #include "Shader.h"
23 #include "TransformFeedback.h"
24 #include "utilities.h"
25 #include "common/debug.h"
26 #include "Shader/PixelShader.hpp"
27 #include "Shader/VertexShader.hpp"
28 
29 #include <algorithm>
30 #include <string>
31 #include <stdlib.h>
32 
33 namespace es2
34 {
35 	unsigned int Program::currentSerial = 1;
36 
str(int i)37 	std::string str(int i)
38 	{
39 		char buffer[20];
40 		sprintf(buffer, "%d", i);
41 		return buffer;
42 	}
43 
BlockInfo(const glsl::Uniform & uniform,int blockIndex)44 	Uniform::BlockInfo::BlockInfo(const glsl::Uniform& uniform, int blockIndex)
45 	{
46 		if(blockIndex >= 0)
47 		{
48 			index = blockIndex;
49 			offset = uniform.blockInfo.offset;
50 			arrayStride = uniform.blockInfo.arrayStride;
51 			matrixStride = uniform.blockInfo.matrixStride;
52 			isRowMajorMatrix = uniform.blockInfo.isRowMajorMatrix;
53 		}
54 	}
55 
Uniform(const glsl::Uniform & uniform,const BlockInfo & blockInfo)56 	Uniform::Uniform(const glsl::Uniform &uniform, const BlockInfo &blockInfo)
57 	 : type(uniform.type), precision(uniform.precision), name(uniform.name),
58 	   arraySize(uniform.arraySize), blockInfo(blockInfo), fields(uniform.fields)
59 	{
60 		if((blockInfo.index == -1) && uniform.fields.empty())
61 		{
62 			size_t bytes = UniformTypeSize(type) * size();
63 			data = new unsigned char[bytes];
64 			memset(data, 0, bytes);
65 		}
66 	}
67 
~Uniform()68 	Uniform::~Uniform()
69 	{
70 		delete[] data;
71 	}
72 
isArray() const73 	bool Uniform::isArray() const
74 	{
75 		return arraySize >= 1;
76 	}
77 
size() const78 	int Uniform::size() const
79 	{
80 		return arraySize > 0 ? arraySize : 1;
81 	}
82 
registerCount() const83 	int Uniform::registerCount() const
84 	{
85 		return size() * VariableRegisterCount(type);
86 	}
87 
UniformBlock(const std::string & name,unsigned int elementIndex,unsigned int dataSize,std::vector<unsigned int> memberUniformIndexes)88 	UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize, std::vector<unsigned int> memberUniformIndexes) :
89 		name(name), elementIndex(elementIndex), dataSize(dataSize), memberUniformIndexes(memberUniformIndexes), psRegisterIndex(GL_INVALID_INDEX), vsRegisterIndex(GL_INVALID_INDEX)
90 	{
91 	}
92 
setRegisterIndex(GLenum shader,unsigned int registerIndex)93 	void UniformBlock::setRegisterIndex(GLenum shader, unsigned int registerIndex)
94 	{
95 		switch(shader)
96 		{
97 		case GL_VERTEX_SHADER:
98 			vsRegisterIndex = registerIndex;
99 			break;
100 		case GL_FRAGMENT_SHADER:
101 			psRegisterIndex = registerIndex;
102 			break;
103 		default:
104 			UNREACHABLE(shader);
105 		}
106 	}
107 
isArrayElement() const108 	bool UniformBlock::isArrayElement() const
109 	{
110 		return elementIndex != GL_INVALID_INDEX;
111 	}
112 
isReferencedByVertexShader() const113 	bool UniformBlock::isReferencedByVertexShader() const
114 	{
115 		return vsRegisterIndex != GL_INVALID_INDEX;
116 	}
117 
isReferencedByFragmentShader() const118 	bool UniformBlock::isReferencedByFragmentShader() const
119 	{
120 		return psRegisterIndex != GL_INVALID_INDEX;
121 	}
122 
UniformLocation(const std::string & name,unsigned int element,unsigned int index)123 	UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) : name(name), element(element), index(index)
124 	{
125 	}
126 
LinkedVarying()127 	LinkedVarying::LinkedVarying()
128 	{
129 	}
130 
LinkedVarying(const std::string & name,GLenum type,GLsizei size,int reg,int col)131 	LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, int reg, int col)
132 	 : name(name), type(type), size(size), reg(reg), col(col)
133 	{
134 	}
135 
Program(ResourceManager * manager,GLuint handle)136 	Program::Program(ResourceManager *manager, GLuint handle) : serial(issueSerial()), resourceManager(manager), handle(handle)
137 	{
138 		fragmentShader = 0;
139 		vertexShader = 0;
140 		pixelBinary = 0;
141 		vertexBinary = 0;
142 
143 		transformFeedbackBufferMode = GL_INTERLEAVED_ATTRIBS;
144 		totalLinkedVaryingsComponents = 0;
145 
146 		infoLog = 0;
147 		validated = false;
148 
149 		resetUniformBlockBindings();
150 		unlink();
151 
152 		orphaned = false;
153 		retrievableBinary = false;
154 		referenceCount = 0;
155 	}
156 
~Program()157 	Program::~Program()
158 	{
159 		unlink();
160 
161 		if(vertexShader)
162 		{
163 			vertexShader->release();
164 		}
165 
166 		if(fragmentShader)
167 		{
168 			fragmentShader->release();
169 		}
170 	}
171 
attachShader(Shader * shader)172 	bool Program::attachShader(Shader *shader)
173 	{
174 		if(shader->getType() == GL_VERTEX_SHADER)
175 		{
176 			if(vertexShader)
177 			{
178 				return false;
179 			}
180 
181 			vertexShader = (VertexShader*)shader;
182 			vertexShader->addRef();
183 		}
184 		else if(shader->getType() == GL_FRAGMENT_SHADER)
185 		{
186 			if(fragmentShader)
187 			{
188 				return false;
189 			}
190 
191 			fragmentShader = (FragmentShader*)shader;
192 			fragmentShader->addRef();
193 		}
194 		else UNREACHABLE(shader->getType());
195 
196 		return true;
197 	}
198 
detachShader(Shader * shader)199 	bool Program::detachShader(Shader *shader)
200 	{
201 		if(shader->getType() == GL_VERTEX_SHADER)
202 		{
203 			if(vertexShader != shader)
204 			{
205 				return false;
206 			}
207 
208 			vertexShader->release();
209 			vertexShader = 0;
210 		}
211 		else if(shader->getType() == GL_FRAGMENT_SHADER)
212 		{
213 			if(fragmentShader != shader)
214 			{
215 				return false;
216 			}
217 
218 			fragmentShader->release();
219 			fragmentShader = 0;
220 		}
221 		else UNREACHABLE(shader->getType());
222 
223 		return true;
224 	}
225 
getAttachedShadersCount() const226 	int Program::getAttachedShadersCount() const
227 	{
228 		return (vertexShader ? 1 : 0) + (fragmentShader ? 1 : 0);
229 	}
230 
getPixelShader()231 	sw::PixelShader *Program::getPixelShader()
232 	{
233 		return pixelBinary;
234 	}
235 
getVertexShader()236 	sw::VertexShader *Program::getVertexShader()
237 	{
238 		return vertexBinary;
239 	}
240 
getFragDataLocation(const GLchar * name)241 	GLint Program::getFragDataLocation(const GLchar *name)
242 	{
243 		if(name && linked)
244 		{
245 			std::string baseName(name);
246 			unsigned int subscript = GL_INVALID_INDEX;
247 			baseName = ParseUniformName(baseName, &subscript);
248 			for(auto const &varying : fragmentShader->varyings)
249 			{
250 				if(varying.qualifier == EvqFragmentOut)
251 				{
252 					if(varying.name == baseName)
253 					{
254 						ASSERT(varying.registerIndex >= 0);
255 
256 						if(subscript == GL_INVALID_INDEX)   // No subscript
257 						{
258 							return varying.registerIndex;
259 						}
260 
261 						int rowCount = VariableRowCount(varying.type);
262 						int colCount = VariableColumnCount(varying.type);
263 
264 						return varying.registerIndex + (rowCount > 1 ? colCount * subscript : subscript);
265 					}
266 				}
267 			}
268 		}
269 
270 		return -1;
271 	}
272 
bindAttributeLocation(GLuint index,const char * name)273 	void Program::bindAttributeLocation(GLuint index, const char *name)
274 	{
275 		attributeBinding[name] = index;
276 	}
277 
getAttributeLocation(const char * name)278 	GLint Program::getAttributeLocation(const char *name)
279 	{
280 		return name ? getAttributeLocation(std::string(name)) : -1;
281 	}
282 
getAttributeStream(int attributeIndex)283 	int Program::getAttributeStream(int attributeIndex)
284 	{
285 		ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
286 
287 		return attributeStream[attributeIndex];
288 	}
289 
290 	// Returns the index of the texture image unit (0-19) corresponding to a sampler index (0-15 for the pixel shader and 0-3 for the vertex shader)
getSamplerMapping(sw::SamplerType type,unsigned int samplerIndex)291 	GLint Program::getSamplerMapping(sw::SamplerType type, unsigned int samplerIndex)
292 	{
293 		GLint logicalTextureUnit = -1;
294 
295 		switch(type)
296 		{
297 		case sw::SAMPLER_PIXEL:
298 			ASSERT(samplerIndex < sizeof(samplersPS) / sizeof(samplersPS[0]));
299 
300 			if(samplersPS[samplerIndex].active)
301 			{
302 				logicalTextureUnit = samplersPS[samplerIndex].logicalTextureUnit;
303 			}
304 			break;
305 		case sw::SAMPLER_VERTEX:
306 			ASSERT(samplerIndex < sizeof(samplersVS) / sizeof(samplersVS[0]));
307 
308 			if(samplersVS[samplerIndex].active)
309 			{
310 				logicalTextureUnit = samplersVS[samplerIndex].logicalTextureUnit;
311 			}
312 			break;
313 		default: UNREACHABLE(type);
314 		}
315 
316 		if(logicalTextureUnit < MAX_COMBINED_TEXTURE_IMAGE_UNITS)
317 		{
318 			return logicalTextureUnit;
319 		}
320 
321 		return -1;
322 	}
323 
324 	// Returns the texture type for a given sampler type and index (0-15 for the pixel shader and 0-3 for the vertex shader)
getSamplerTextureType(sw::SamplerType type,unsigned int samplerIndex)325 	TextureType Program::getSamplerTextureType(sw::SamplerType type, unsigned int samplerIndex)
326 	{
327 		switch(type)
328 		{
329 		case sw::SAMPLER_PIXEL:
330 			ASSERT(samplerIndex < sizeof(samplersPS)/sizeof(samplersPS[0]));
331 			ASSERT(samplersPS[samplerIndex].active);
332 			return samplersPS[samplerIndex].textureType;
333 		case sw::SAMPLER_VERTEX:
334 			ASSERT(samplerIndex < sizeof(samplersVS)/sizeof(samplersVS[0]));
335 			ASSERT(samplersVS[samplerIndex].active);
336 			return samplersVS[samplerIndex].textureType;
337 		default: UNREACHABLE(type);
338 		}
339 
340 		return TEXTURE_2D;
341 	}
342 
getUniform(const std::string & name) const343 	Uniform *Program::getUniform(const std::string &name) const
344 	{
345 		unsigned int subscript = GL_INVALID_INDEX;
346 		std::string baseName = es2::ParseUniformName(name, &subscript);
347 
348 		for(size_t index = 0; index < uniforms.size(); index++)
349 		{
350 			if(uniforms[index]->name == baseName)
351 			{
352 				return uniforms[index];
353 			}
354 		}
355 
356 		return nullptr;
357 	}
358 
getUniformLocation(const std::string & name) const359 	GLint Program::getUniformLocation(const std::string &name) const
360 	{
361 		unsigned int subscript = GL_INVALID_INDEX;
362 		std::string baseName = es2::ParseUniformName(name, &subscript);
363 
364 		for(size_t location = 0; location < uniformIndex.size(); location++)
365 		{
366 			if(uniformIndex[location].name == baseName)
367 			{
368 				const unsigned int index = uniformIndex[location].index;
369 
370 				if(index != GL_INVALID_INDEX)
371 				{
372 					if(subscript == GL_INVALID_INDEX)
373 					{
374 						return (GLint)location;
375 					}
376 					else if(uniforms[index]->isArray())
377 					{
378 						if(uniformIndex[location].element == subscript)
379 						{
380 							return (GLint)location;
381 						}
382 					}
383 				}
384 			}
385 		}
386 
387 		return -1;
388 	}
389 
getUniformIndex(const std::string & name) const390 	GLuint Program::getUniformIndex(const std::string &name) const
391 	{
392 		unsigned int subscript = GL_INVALID_INDEX;
393 		std::string baseName = es2::ParseUniformName(name, &subscript);
394 
395 		// The app is not allowed to specify array indices other than 0 for arrays of basic types
396 		if(subscript != 0 && subscript != GL_INVALID_INDEX)
397 		{
398 			return GL_INVALID_INDEX;
399 		}
400 
401 		size_t numUniforms = uniforms.size();
402 		for(GLuint index = 0; index < numUniforms; index++)
403 		{
404 			if(uniforms[index]->name == baseName)
405 			{
406 				if(uniforms[index]->isArray() || subscript == GL_INVALID_INDEX)
407 				{
408 					return index;
409 				}
410 			}
411 		}
412 
413 		return GL_INVALID_INDEX;
414 	}
415 
getActiveUniformBlockiv(GLuint uniformBlockIndex,GLenum pname,GLint * params) const416 	void Program::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const
417 	{
418 		ASSERT(uniformBlockIndex < getActiveUniformBlockCount());
419 
420 		const UniformBlock &uniformBlock = *uniformBlocks[uniformBlockIndex];
421 
422 		switch(pname)
423 		{
424 		case GL_UNIFORM_BLOCK_DATA_SIZE:
425 			*params = static_cast<GLint>(uniformBlock.dataSize);
426 			break;
427 		case GL_UNIFORM_BLOCK_NAME_LENGTH:
428 			*params = static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0));
429 			break;
430 		case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
431 			*params = static_cast<GLint>(uniformBlock.memberUniformIndexes.size());
432 			break;
433 		case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
434 			{
435 				for(unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
436 				{
437 					params[blockMemberIndex] = static_cast<GLint>(uniformBlock.memberUniformIndexes[blockMemberIndex]);
438 				}
439 			}
440 			break;
441 		case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
442 			*params = static_cast<GLint>(uniformBlock.isReferencedByVertexShader());
443 			break;
444 		case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
445 			*params = static_cast<GLint>(uniformBlock.isReferencedByFragmentShader());
446 			break;
447 		default: UNREACHABLE(pname);
448 		}
449 	}
450 
getUniformBlockIndex(const std::string & name) const451 	GLuint Program::getUniformBlockIndex(const std::string &name) const
452 	{
453 		unsigned int subscript = GL_INVALID_INDEX;
454 		std::string baseName = es2::ParseUniformName(name, &subscript);
455 
456 		size_t numUniformBlocks = getActiveUniformBlockCount();
457 		for(GLuint blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++)
458 		{
459 			const UniformBlock &uniformBlock = *uniformBlocks[blockIndex];
460 			if(uniformBlock.name == baseName)
461 			{
462 				const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0);
463 				if(subscript == uniformBlock.elementIndex || arrayElementZero)
464 				{
465 					return blockIndex;
466 				}
467 			}
468 		}
469 
470 		return GL_INVALID_INDEX;
471 	}
472 
bindUniformBlock(GLuint uniformBlockIndex,GLuint uniformBlockBinding)473 	void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
474 	{
475 		ASSERT(uniformBlockIndex < getActiveUniformBlockCount());
476 
477 		uniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
478 	}
479 
getUniformBlockBinding(GLuint uniformBlockIndex) const480 	GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
481 	{
482 		ASSERT(uniformBlockIndex < getActiveUniformBlockCount());
483 
484 		return uniformBlockBindings[uniformBlockIndex];
485 	}
486 
resetUniformBlockBindings()487 	void Program::resetUniformBlockBindings()
488 	{
489 		for(unsigned int blockId = 0; blockId < MAX_UNIFORM_BUFFER_BINDINGS; blockId++)
490 		{
491 			uniformBlockBindings[blockId] = 0;
492 		}
493 	}
494 
setUniformfv(GLint location,GLsizei count,const GLfloat * v,int numElements)495 	bool Program::setUniformfv(GLint location, GLsizei count, const GLfloat *v, int numElements)
496 	{
497 		ASSERT(numElements >= 1 && numElements <= 4);
498 
499 		static GLenum floatType[] = { GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4 };
500 		static GLenum boolType[] = { GL_BOOL, GL_BOOL_VEC2, GL_BOOL_VEC3, GL_BOOL_VEC4 };
501 
502 		if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
503 		{
504 			return false;
505 		}
506 
507 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
508 		targetUniform->dirty = true;
509 
510 		int size = targetUniform->size();
511 
512 		if(size == 1 && count > 1)
513 		{
514 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
515 		}
516 
517 		count = std::min(size - (int)uniformIndex[location].element, count);
518 
519 		int index = numElements - 1;
520 		if(targetUniform->type == floatType[index])
521 		{
522 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat)* numElements,
523 				   v, numElements * sizeof(GLfloat) * count);
524 		}
525 		else if(targetUniform->type == boolType[index])
526 		{
527 			GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * numElements;
528 
529 			for(int i = 0; i < count * numElements; i++)
530 			{
531 				boolParams[i] = (v[i] == 0.0f) ? GL_FALSE : GL_TRUE;
532 			}
533 		}
534 		else
535 		{
536 			return false;
537 		}
538 
539 		return true;
540 	}
541 
setUniform1fv(GLint location,GLsizei count,const GLfloat * v)542 	bool Program::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
543 	{
544 		return setUniformfv(location, count, v, 1);
545 	}
546 
setUniform2fv(GLint location,GLsizei count,const GLfloat * v)547 	bool Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
548 	{
549 		return setUniformfv(location, count, v, 2);
550 	}
551 
setUniform3fv(GLint location,GLsizei count,const GLfloat * v)552 	bool Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
553 	{
554 		return setUniformfv(location, count, v, 3);
555 	}
556 
setUniform4fv(GLint location,GLsizei count,const GLfloat * v)557 	bool Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
558 	{
559 		return setUniformfv(location, count, v, 4);
560 	}
561 
setUniformMatrixfv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value,GLenum type)562 	bool Program::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum type)
563 	{
564 		int numElements;
565 		switch(type)
566 		{
567 		case GL_FLOAT_MAT2:
568 			numElements = 4;
569 			break;
570 		case GL_FLOAT_MAT2x3:
571 		case GL_FLOAT_MAT3x2:
572 			numElements = 6;
573 			break;
574 		case GL_FLOAT_MAT2x4:
575 		case GL_FLOAT_MAT4x2:
576 			numElements = 8;
577 			break;
578 		case GL_FLOAT_MAT3:
579 			numElements = 9;
580 			break;
581 		case GL_FLOAT_MAT3x4:
582 		case GL_FLOAT_MAT4x3:
583 			numElements = 12;
584 			break;
585 		case GL_FLOAT_MAT4:
586 			numElements = 16;
587 			break;
588 		default:
589 			return false;
590 		}
591 
592 		if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
593 		{
594 			return false;
595 		}
596 
597 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
598 		targetUniform->dirty = true;
599 
600 		if(targetUniform->type != type)
601 		{
602 			return false;
603 		}
604 
605 		int size = targetUniform->size();
606 
607 		if(size == 1 && count > 1)
608 		{
609 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
610 		}
611 
612 		count = std::min(size - (int)uniformIndex[location].element, count);
613 
614 		GLfloat* dst = reinterpret_cast<GLfloat*>(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * numElements);
615 
616 		if(transpose == GL_FALSE)
617 		{
618 			memcpy(dst, value, numElements * sizeof(GLfloat) * count);
619 		}
620 		else
621 		{
622 			const int rowSize = VariableRowCount(type);
623 			const int colSize = VariableColumnCount(type);
624 			for(int n = 0; n < count; ++n)
625 			{
626 				for(int i = 0; i < colSize; ++i)
627 				{
628 					for(int j = 0; j < rowSize; ++j)
629 					{
630 						dst[i * rowSize + j] = value[j * colSize + i];
631 					}
632 				}
633 				dst += numElements;
634 				value += numElements;
635 			}
636 		}
637 
638 
639 		return true;
640 	}
641 
setUniformMatrix2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)642 	bool Program::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
643 	{
644 		return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT2);
645 	}
646 
setUniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)647 	bool Program::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
648 	{
649 		return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT2x3);
650 	}
651 
setUniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)652 	bool Program::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
653 	{
654 		return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT2x4);
655 	}
656 
setUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)657 	bool Program::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
658 	{
659 		return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT3);
660 	}
661 
setUniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)662 	bool Program::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
663 	{
664 		return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT3x2);
665 	}
666 
setUniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)667 	bool Program::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
668 	{
669 		return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT3x4);
670 	}
671 
setUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)672 	bool Program::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
673 	{
674 		return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT4);
675 	}
676 
setUniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)677 	bool Program::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
678 	{
679 		return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT4x2);
680 	}
681 
setUniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)682 	bool Program::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
683 	{
684 		return setUniformMatrixfv(location, count, transpose, value, GL_FLOAT_MAT4x3);
685 	}
686 
setUniform1iv(GLint location,GLsizei count,const GLint * v)687 	bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
688 	{
689 		if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
690 		{
691 			return false;
692 		}
693 
694 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
695 		targetUniform->dirty = true;
696 
697 		int size = targetUniform->size();
698 
699 		if(size == 1 && count > 1)
700 		{
701 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
702 		}
703 
704 		count = std::min(size - (int)uniformIndex[location].element, count);
705 
706 		if(targetUniform->type == GL_INT || IsSamplerUniform(targetUniform->type))
707 		{
708 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint),
709 				   v, sizeof(GLint) * count);
710 		}
711 		else if(targetUniform->type == GL_BOOL)
712 		{
713 			GLboolean *boolParams = new GLboolean[count];
714 
715 			for(int i = 0; i < count; i++)
716 			{
717 				if(v[i] == 0)
718 				{
719 					boolParams[i] = GL_FALSE;
720 				}
721 				else
722 				{
723 					boolParams[i] = GL_TRUE;
724 				}
725 			}
726 
727 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean),
728 				   boolParams, sizeof(GLboolean) * count);
729 
730 			delete[] boolParams;
731 		}
732 		else
733 		{
734 			return false;
735 		}
736 
737 		return true;
738 	}
739 
setUniformiv(GLint location,GLsizei count,const GLint * v,int numElements)740 	bool Program::setUniformiv(GLint location, GLsizei count, const GLint *v, int numElements)
741 	{
742 		static GLenum intType[] = { GL_INT, GL_INT_VEC2, GL_INT_VEC3, GL_INT_VEC4 };
743 		static GLenum boolType[] = { GL_BOOL, GL_BOOL_VEC2, GL_BOOL_VEC3, GL_BOOL_VEC4 };
744 
745 		if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
746 		{
747 			return false;
748 		}
749 
750 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
751 		targetUniform->dirty = true;
752 
753 		int size = targetUniform->size();
754 
755 		if(size == 1 && count > 1)
756 		{
757 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
758 		}
759 
760 		count = std::min(size - (int)uniformIndex[location].element, count);
761 
762 		int index = numElements - 1;
763 		if(targetUniform->type == intType[index])
764 		{
765 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint)* numElements,
766 				   v, numElements * sizeof(GLint)* count);
767 		}
768 		else if(targetUniform->type == boolType[index])
769 		{
770 			GLboolean *boolParams = new GLboolean[count * numElements];
771 
772 			for(int i = 0; i < count * numElements; i++)
773 			{
774 				boolParams[i] = (v[i] == 0) ? GL_FALSE : GL_TRUE;
775 			}
776 
777 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean)* numElements,
778 				   boolParams, numElements * sizeof(GLboolean)* count);
779 
780 			delete[] boolParams;
781 		}
782 		else
783 		{
784 			return false;
785 		}
786 
787 		return true;
788 	}
789 
setUniform2iv(GLint location,GLsizei count,const GLint * v)790 	bool Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
791 	{
792 		return setUniformiv(location, count, v, 2);
793 	}
794 
setUniform3iv(GLint location,GLsizei count,const GLint * v)795 	bool Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
796 	{
797 		return setUniformiv(location, count, v, 3);
798 	}
799 
setUniform4iv(GLint location,GLsizei count,const GLint * v)800 	bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
801 	{
802 		return setUniformiv(location, count, v, 4);
803 	}
804 
setUniform1uiv(GLint location,GLsizei count,const GLuint * v)805 	bool Program::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
806 	{
807 		if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
808 		{
809 			return false;
810 		}
811 
812 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
813 		targetUniform->dirty = true;
814 
815 		int size = targetUniform->size();
816 
817 		if(size == 1 && count > 1)
818 		{
819 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
820 		}
821 
822 		count = std::min(size - (int)uniformIndex[location].element, count);
823 
824 		if(targetUniform->type == GL_UNSIGNED_INT)
825 		{
826 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLuint),
827 				   v, sizeof(GLuint)* count);
828 		}
829 		else if(targetUniform->type == GL_BOOL)
830 		{
831 			GLboolean *boolParams = new GLboolean[count];
832 
833 			for(int i = 0; i < count; i++)
834 			{
835 				if(v[i] == 0)
836 				{
837 					boolParams[i] = GL_FALSE;
838 				}
839 				else
840 				{
841 					boolParams[i] = GL_TRUE;
842 				}
843 			}
844 
845 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean),
846 				   boolParams, sizeof(GLboolean)* count);
847 
848 			delete[] boolParams;
849 		}
850 		else
851 		{
852 			return false;
853 		}
854 
855 		return true;
856 	}
857 
setUniformuiv(GLint location,GLsizei count,const GLuint * v,int numElements)858 	bool Program::setUniformuiv(GLint location, GLsizei count, const GLuint *v, int numElements)
859 	{
860 		static GLenum uintType[] = { GL_UNSIGNED_INT, GL_UNSIGNED_INT_VEC2, GL_UNSIGNED_INT_VEC3, GL_UNSIGNED_INT_VEC4 };
861 		static GLenum boolType[] = { GL_BOOL, GL_BOOL_VEC2, GL_BOOL_VEC3, GL_BOOL_VEC4 };
862 
863 		if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
864 		{
865 			return false;
866 		}
867 
868 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
869 		targetUniform->dirty = true;
870 
871 		int size = targetUniform->size();
872 
873 		if(size == 1 && count > 1)
874 		{
875 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
876 		}
877 
878 		count = std::min(size - (int)uniformIndex[location].element, count);
879 
880 		int index = numElements - 1;
881 		if(targetUniform->type == uintType[index])
882 		{
883 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLuint)* numElements,
884 				   v, numElements * sizeof(GLuint)* count);
885 		}
886 		else if(targetUniform->type == boolType[index])
887 		{
888 			GLboolean *boolParams = new GLboolean[count * numElements];
889 
890 			for(int i = 0; i < count * numElements; i++)
891 			{
892 				boolParams[i] = (v[i] == 0) ? GL_FALSE : GL_TRUE;
893 			}
894 
895 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean)* numElements,
896 				   boolParams, numElements * sizeof(GLboolean)* count);
897 
898 			delete[] boolParams;
899 		}
900 		else
901 		{
902 			return false;
903 		}
904 
905 		return true;
906 	}
907 
setUniform2uiv(GLint location,GLsizei count,const GLuint * v)908 	bool Program::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
909 	{
910 		return setUniformuiv(location, count, v, 2);
911 	}
912 
setUniform3uiv(GLint location,GLsizei count,const GLuint * v)913 	bool Program::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
914 	{
915 		return setUniformuiv(location, count, v, 3);
916 	}
917 
setUniform4uiv(GLint location,GLsizei count,const GLuint * v)918 	bool Program::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
919 	{
920 		return setUniformuiv(location, count, v, 4);
921 	}
922 
getUniformfv(GLint location,GLsizei * bufSize,GLfloat * params)923 	bool Program::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params)
924 	{
925 		if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
926 		{
927 			return false;
928 		}
929 
930 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
931 		unsigned int count = UniformComponentCount(targetUniform->type);
932 
933 		// Sized query - ensure the provided buffer is large enough
934 		if(bufSize && static_cast<unsigned int>(*bufSize) < count * sizeof(GLfloat))
935 		{
936 			return false;
937 		}
938 
939 		switch(UniformComponentType(targetUniform->type))
940 		{
941 		case GL_BOOL:
942 			{
943 				GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * count;
944 
945 				for(unsigned int i = 0; i < count; i++)
946 				{
947 					params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
948 				}
949 			}
950 			break;
951 		case GL_FLOAT:
952 			memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLfloat),
953 				   count * sizeof(GLfloat));
954 			break;
955 		case GL_INT:
956 			{
957 				GLint *intParams = (GLint*)targetUniform->data + uniformIndex[location].element * count;
958 
959 				for(unsigned int i = 0; i < count; i++)
960 				{
961 					params[i] = (float)intParams[i];
962 				}
963 			}
964 			break;
965 		case GL_UNSIGNED_INT:
966 			{
967 				GLuint *uintParams = (GLuint*)targetUniform->data + uniformIndex[location].element * count;
968 
969 				for(unsigned int i = 0; i < count; i++)
970 				{
971 					params[i] = (float)uintParams[i];
972 				}
973 			}
974 			break;
975 		default: UNREACHABLE(targetUniform->type);
976 		}
977 
978 		return true;
979 	}
980 
getUniformiv(GLint location,GLsizei * bufSize,GLint * params)981 	bool Program::getUniformiv(GLint location, GLsizei *bufSize, GLint *params)
982 	{
983 		if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
984 		{
985 			return false;
986 		}
987 
988 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
989 		unsigned int count = UniformComponentCount(targetUniform->type);
990 
991 		// Sized query - ensure the provided buffer is large enough
992 		if(bufSize && static_cast<unsigned int>(*bufSize) < count * sizeof(GLint))
993 		{
994 			return false;
995 		}
996 
997 		switch(UniformComponentType(targetUniform->type))
998 		{
999 		case GL_BOOL:
1000 			{
1001 				GLboolean *boolParams = targetUniform->data + uniformIndex[location].element * count;
1002 
1003 				for(unsigned int i = 0; i < count; i++)
1004 				{
1005 					params[i] = (GLint)boolParams[i];
1006 				}
1007 			}
1008 			break;
1009 		case GL_FLOAT:
1010 			{
1011 				GLfloat *floatParams = (GLfloat*)targetUniform->data + uniformIndex[location].element * count;
1012 
1013 				for(unsigned int i = 0; i < count; i++)
1014 				{
1015 					params[i] = (GLint)floatParams[i];
1016 				}
1017 			}
1018 			break;
1019 		case GL_INT:
1020 		case GL_UNSIGNED_INT:
1021 			memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLint),
1022 				   count * sizeof(GLint));
1023 			break;
1024 		default: UNREACHABLE(targetUniform->type);
1025 		}
1026 
1027 		return true;
1028 	}
1029 
getUniformuiv(GLint location,GLsizei * bufSize,GLuint * params)1030 	bool Program::getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params)
1031 	{
1032 		if(location < 0 || location >= (int)uniformIndex.size() || (uniformIndex[location].index == GL_INVALID_INDEX))
1033 		{
1034 			return false;
1035 		}
1036 
1037 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
1038 		unsigned int count = UniformComponentCount(targetUniform->type);
1039 
1040 		// Sized query - ensure the provided buffer is large enough
1041 		if(bufSize && static_cast<unsigned int>(*bufSize) < count * sizeof(GLuint))
1042 		{
1043 			return false;
1044 		}
1045 
1046 		switch(UniformComponentType(targetUniform->type))
1047 		{
1048 		case GL_BOOL:
1049 		{
1050 			GLboolean *boolParams = targetUniform->data + uniformIndex[location].element * count;
1051 
1052 			for(unsigned int i = 0; i < count; i++)
1053 			{
1054 				params[i] = (GLuint)boolParams[i];
1055 			}
1056 		}
1057 			break;
1058 		case GL_FLOAT:
1059 		{
1060 			GLfloat *floatParams = (GLfloat*)targetUniform->data + uniformIndex[location].element * count;
1061 
1062 			for(unsigned int i = 0; i < count; i++)
1063 			{
1064 				params[i] = (GLuint)floatParams[i];
1065 			}
1066 		}
1067 			break;
1068 		case GL_INT:
1069 		case GL_UNSIGNED_INT:
1070 			memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLuint),
1071 				   count * sizeof(GLuint));
1072 			break;
1073 		default: UNREACHABLE(targetUniform->type);
1074 		}
1075 
1076 		return true;
1077 	}
1078 
dirtyAllUniforms()1079 	void Program::dirtyAllUniforms()
1080 	{
1081 		size_t numUniforms = uniforms.size();
1082 		for(size_t index = 0; index < numUniforms; index++)
1083 		{
1084 			uniforms[index]->dirty = true;
1085 		}
1086 	}
1087 
1088 	// Applies all the uniforms set for this program object to the device
applyUniforms(Device * device)1089 	void Program::applyUniforms(Device *device)
1090 	{
1091 		GLint numUniforms = static_cast<GLint>(uniformIndex.size());
1092 		for(GLint location = 0; location < numUniforms; location++)
1093 		{
1094 			if((uniformIndex[location].element != 0) || (uniformIndex[location].index == GL_INVALID_INDEX))
1095 			{
1096 				continue;
1097 			}
1098 
1099 			Uniform *targetUniform = uniforms[uniformIndex[location].index];
1100 
1101 			if(targetUniform->dirty && (targetUniform->blockInfo.index == -1))
1102 			{
1103 				GLsizei size = targetUniform->size();
1104 				GLfloat *f = (GLfloat*)targetUniform->data;
1105 				GLint *i = (GLint*)targetUniform->data;
1106 				GLuint *ui = (GLuint*)targetUniform->data;
1107 				GLboolean *b = (GLboolean*)targetUniform->data;
1108 
1109 				switch(targetUniform->type)
1110 				{
1111 				case GL_BOOL:       applyUniform1bv(device, location, size, b);       break;
1112 				case GL_BOOL_VEC2:  applyUniform2bv(device, location, size, b);       break;
1113 				case GL_BOOL_VEC3:  applyUniform3bv(device, location, size, b);       break;
1114 				case GL_BOOL_VEC4:  applyUniform4bv(device, location, size, b);       break;
1115 				case GL_FLOAT:      applyUniform1fv(device, location, size, f);       break;
1116 				case GL_FLOAT_VEC2: applyUniform2fv(device, location, size, f);       break;
1117 				case GL_FLOAT_VEC3: applyUniform3fv(device, location, size, f);       break;
1118 				case GL_FLOAT_VEC4: applyUniform4fv(device, location, size, f);       break;
1119 				case GL_FLOAT_MAT2:   applyUniformMatrix2fv(device, location, size, f);   break;
1120 				case GL_FLOAT_MAT2x3: applyUniformMatrix2x3fv(device, location, size, f); break;
1121 				case GL_FLOAT_MAT2x4: applyUniformMatrix2x4fv(device, location, size, f); break;
1122 				case GL_FLOAT_MAT3x2: applyUniformMatrix3x2fv(device, location, size, f); break;
1123 				case GL_FLOAT_MAT3:   applyUniformMatrix3fv(device, location, size, f);   break;
1124 				case GL_FLOAT_MAT3x4: applyUniformMatrix3x4fv(device, location, size, f); break;
1125 				case GL_FLOAT_MAT4x2: applyUniformMatrix4x2fv(device, location, size, f); break;
1126 				case GL_FLOAT_MAT4x3: applyUniformMatrix4x3fv(device, location, size, f); break;
1127 				case GL_FLOAT_MAT4:   applyUniformMatrix4fv(device, location, size, f);   break;
1128 				case GL_SAMPLER_2D:
1129 				case GL_SAMPLER_CUBE:
1130 				case GL_SAMPLER_2D_RECT_ARB:
1131 				case GL_SAMPLER_EXTERNAL_OES:
1132 				case GL_SAMPLER_3D_OES:
1133 				case GL_SAMPLER_2D_ARRAY:
1134 				case GL_SAMPLER_2D_SHADOW:
1135 				case GL_SAMPLER_CUBE_SHADOW:
1136 				case GL_SAMPLER_2D_ARRAY_SHADOW:
1137 				case GL_INT_SAMPLER_2D:
1138 				case GL_UNSIGNED_INT_SAMPLER_2D:
1139 				case GL_INT_SAMPLER_CUBE:
1140 				case GL_UNSIGNED_INT_SAMPLER_CUBE:
1141 				case GL_INT_SAMPLER_3D:
1142 				case GL_UNSIGNED_INT_SAMPLER_3D:
1143 				case GL_INT_SAMPLER_2D_ARRAY:
1144 				case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
1145 				case GL_INT:        applyUniform1iv(device, location, size, i);       break;
1146 				case GL_INT_VEC2:   applyUniform2iv(device, location, size, i);       break;
1147 				case GL_INT_VEC3:   applyUniform3iv(device, location, size, i);       break;
1148 				case GL_INT_VEC4:   applyUniform4iv(device, location, size, i);       break;
1149 				case GL_UNSIGNED_INT:      applyUniform1uiv(device, location, size, ui); break;
1150 				case GL_UNSIGNED_INT_VEC2: applyUniform2uiv(device, location, size, ui); break;
1151 				case GL_UNSIGNED_INT_VEC3: applyUniform3uiv(device, location, size, ui); break;
1152 				case GL_UNSIGNED_INT_VEC4: applyUniform4uiv(device, location, size, ui); break;
1153 				default:
1154 					UNREACHABLE(targetUniform->type);
1155 				}
1156 
1157 				targetUniform->dirty = false;
1158 			}
1159 		}
1160 	}
1161 
applyUniformBuffers(Device * device,BufferBinding * uniformBuffers)1162 	void Program::applyUniformBuffers(Device *device, BufferBinding* uniformBuffers)
1163 	{
1164 		GLint vertexUniformBuffers[MAX_UNIFORM_BUFFER_BINDINGS];
1165 		GLint fragmentUniformBuffers[MAX_UNIFORM_BUFFER_BINDINGS];
1166 
1167 		for(unsigned int bufferBindingIndex = 0; bufferBindingIndex < MAX_UNIFORM_BUFFER_BINDINGS; bufferBindingIndex++)
1168 		{
1169 			vertexUniformBuffers[bufferBindingIndex] = -1;
1170 		}
1171 
1172 		for(unsigned int bufferBindingIndex = 0; bufferBindingIndex < MAX_UNIFORM_BUFFER_BINDINGS; bufferBindingIndex++)
1173 		{
1174 			fragmentUniformBuffers[bufferBindingIndex] = -1;
1175 		}
1176 
1177 		int vertexUniformBufferIndex = 0;
1178 		int fragmentUniformBufferIndex = 0;
1179 		for(unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlocks.size(); uniformBlockIndex++)
1180 		{
1181 			UniformBlock &uniformBlock = *uniformBlocks[uniformBlockIndex];
1182 
1183 			// Unnecessary to apply an unreferenced standard or shared UBO
1184 			if(!uniformBlock.isReferencedByVertexShader() && !uniformBlock.isReferencedByFragmentShader())
1185 			{
1186 				continue;
1187 			}
1188 
1189 			GLuint blockBinding = uniformBlockBindings[uniformBlockIndex];
1190 
1191 			if(uniformBlock.isReferencedByVertexShader())
1192 			{
1193 				vertexUniformBuffers[vertexUniformBufferIndex++] = blockBinding;
1194 			}
1195 
1196 			if(uniformBlock.isReferencedByFragmentShader())
1197 			{
1198 				fragmentUniformBuffers[fragmentUniformBufferIndex++] = blockBinding;
1199 			}
1200 		}
1201 
1202 		for(unsigned int bufferBindingIndex = 0; bufferBindingIndex < MAX_UNIFORM_BUFFER_BINDINGS; bufferBindingIndex++)
1203 		{
1204 			int index = vertexUniformBuffers[bufferBindingIndex];
1205 			Buffer* vsBuffer = (index != -1) ? (Buffer*)uniformBuffers[index].get() : nullptr;
1206 			device->VertexProcessor::setUniformBuffer(bufferBindingIndex,
1207 				vsBuffer ? vsBuffer->getResource() : nullptr, (index != -1) ? uniformBuffers[index].getOffset() : 0);
1208 			index = fragmentUniformBuffers[bufferBindingIndex];
1209 			Buffer* psBuffer = (index != -1) ? (Buffer*)uniformBuffers[index].get() : nullptr;
1210 			device->PixelProcessor::setUniformBuffer(bufferBindingIndex,
1211 				psBuffer ? psBuffer->getResource() : nullptr, (index != -1) ? uniformBuffers[index].getOffset() : 0);
1212 		}
1213 	}
1214 
applyTransformFeedback(Device * device,TransformFeedback * transformFeedback)1215 	void Program::applyTransformFeedback(Device *device, TransformFeedback* transformFeedback)
1216 	{
1217 		// Make sure the flags will fit in a 64 bit unsigned int variable
1218 		ASSERT(sw::max<int>(MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS) <= 64);
1219 
1220 		BufferBinding* transformFeedbackBuffers = (transformFeedback && transformFeedback->isActive() && !transformFeedback->isPaused()) ? transformFeedback->getBuffers() : nullptr;
1221 
1222 		uint64_t enableTransformFeedback = 0;
1223 		if(!transformFeedbackBuffers)
1224 		{
1225 			for(unsigned int index = 0; index < sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; ++index)
1226 			{
1227 				device->VertexProcessor::setTransformFeedbackBuffer(index, nullptr, 0, 0, 0, 0, 0);
1228 			}
1229 			device->VertexProcessor::enableTransformFeedback(enableTransformFeedback);
1230 			return;
1231 		}
1232 
1233 		unsigned int maxVaryings = static_cast<unsigned int>(transformFeedbackLinkedVaryings.size());
1234 		switch(transformFeedbackBufferMode)
1235 		{
1236 		case GL_SEPARATE_ATTRIBS:
1237 		{
1238 			maxVaryings = sw::min(maxVaryings, (unsigned int)MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS);
1239 			// Attribs go to separate buffers
1240 			for(unsigned int index = 0; index < maxVaryings; ++index)
1241 			{
1242 				int size = transformFeedbackLinkedVaryings[index].size;
1243 				int rowCount = VariableRowCount(transformFeedbackLinkedVaryings[index].type);
1244 				int colCount = VariableColumnCount(transformFeedbackLinkedVaryings[index].type);
1245 				int nbRegs = rowCount > 1 ? colCount * size : size;
1246 				int nbComponentsPerReg = rowCount > 1 ? rowCount : colCount;
1247 				int componentStride = rowCount * colCount * size;
1248 				int baseOffset = transformFeedback->vertexOffset() * componentStride * sizeof(float);
1249 				device->VertexProcessor::setTransformFeedbackBuffer(index,
1250 					transformFeedbackBuffers[index].get()->getResource(),
1251 					transformFeedbackBuffers[index].getOffset() + baseOffset,
1252 					transformFeedbackLinkedVaryings[index].reg * 4 + transformFeedbackLinkedVaryings[index].col,
1253 					nbRegs, nbComponentsPerReg, componentStride);
1254 				enableTransformFeedback |= 1ULL << index;
1255 			}
1256 		}
1257 			break;
1258 		case GL_INTERLEAVED_ATTRIBS:
1259 		{
1260 			// OpenGL ES 3.0.4 spec, section 2.15.2:
1261 			// In INTERLEAVED_ATTRIBS mode, the values of one or more output variables
1262 			// written by a vertex shader are written, interleaved, into the buffer object
1263 			// bound to the first transform feedback binding point (index = 0).
1264 			sw::Resource* resource = transformFeedbackBuffers[0].get() ?
1265 			                         transformFeedbackBuffers[0].get()->getResource() :
1266 			                         nullptr;
1267 			int componentStride = static_cast<int>(totalLinkedVaryingsComponents);
1268 			int baseOffset = transformFeedbackBuffers[0].getOffset() + (transformFeedback->vertexOffset() * componentStride * sizeof(float));
1269 			maxVaryings = sw::min(maxVaryings, (unsigned int)sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
1270 			ASSERT(resource || (maxVaryings == 0));
1271 
1272 			int totalComponents = 0;
1273 			for(unsigned int index = 0; index < maxVaryings; ++index)
1274 			{
1275 				int size = transformFeedbackLinkedVaryings[index].size;
1276 				int rowCount = VariableRowCount(transformFeedbackLinkedVaryings[index].type);
1277 				int colCount = VariableColumnCount(transformFeedbackLinkedVaryings[index].type);
1278 				int nbRegs = rowCount > 1 ? colCount * size : size;
1279 				int nbComponentsPerReg = rowCount > 1 ? rowCount : colCount;
1280 				device->VertexProcessor::setTransformFeedbackBuffer(index, resource,
1281 					baseOffset + (totalComponents * sizeof(float)),
1282 					transformFeedbackLinkedVaryings[index].reg * 4 + transformFeedbackLinkedVaryings[index].col,
1283 					nbRegs, nbComponentsPerReg, componentStride);
1284 				totalComponents += rowCount * colCount * size;
1285 				enableTransformFeedback |= 1ULL << index;
1286 			}
1287 		}
1288 			break;
1289 		default:
1290 			UNREACHABLE(transformFeedbackBufferMode);
1291 			break;
1292 		}
1293 
1294 		// Unset all other transform feedback buffers
1295 		for(unsigned int index = maxVaryings; index < sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; ++index)
1296 		{
1297 			device->VertexProcessor::setTransformFeedbackBuffer(index, nullptr, 0, 0, 0, 0, 0);
1298 		}
1299 
1300 		device->VertexProcessor::enableTransformFeedback(enableTransformFeedback);
1301 	}
1302 
linkVaryings()1303 	bool Program::linkVaryings()
1304 	{
1305 		glsl::VaryingList &psVaryings = fragmentShader->varyings;
1306 		glsl::VaryingList &vsVaryings = vertexShader->varyings;
1307 
1308 		for(auto const &input : psVaryings)
1309 		{
1310 			bool matched = false;
1311 
1312 			for(auto const &output : vsVaryings)
1313 			{
1314 				if(output.name == input.name)
1315 				{
1316 					if(output.type != input.type || output.size() != input.size())
1317 					{
1318 						appendToInfoLog("Type of vertex varying %s does not match that of the fragment varying", output.name.c_str());
1319 
1320 						return false;
1321 					}
1322 
1323 					if((output.qualifier == EvqFlatOut) ^ (input.qualifier == EvqFlatIn))
1324 					{
1325 						appendToInfoLog("Interpolation qualifiers for %s differ between vertex and fragment shaders", output.name.c_str());
1326 
1327 						return false;
1328 					}
1329 
1330 					if(!areMatchingFields(input.fields, output.fields, input.name))
1331 					{
1332 						return false;
1333 					}
1334 
1335 					matched = true;
1336 					break;
1337 				}
1338 			}
1339 
1340 			if(!matched)
1341 			{
1342 				// If a fragment varying is declared but not statically used, it's not an error to not have a matching vertex varying.
1343 				if(input.registerIndex >= 0)
1344 				{
1345 					appendToInfoLog("Fragment varying %s does not match any vertex varying", input.name.c_str());
1346 
1347 					return false;
1348 				}
1349 			}
1350 		}
1351 
1352 		for(auto const &output : vsVaryings)
1353 		{
1354 			bool matched = false;
1355 
1356 			for(auto const &input : psVaryings)
1357 			{
1358 				if(output.name == input.name)
1359 				{
1360 					int in = input.registerIndex;
1361 					int out = output.registerIndex;
1362 					int components = VariableRegisterSize(output.type);
1363 					int registers = VariableRegisterCount(output.type) * output.size();
1364 
1365 					if(in < 0)  // Fragment varying declared but not used
1366 					{
1367 						continue;
1368 					}
1369 
1370 					if(in + registers >= MAX_VARYING_VECTORS)
1371 					{
1372 						appendToInfoLog("Too many varyings");
1373 						return false;
1374 					}
1375 
1376 					if(out >= 0)
1377 					{
1378 						if(out + registers >= MAX_VARYING_VECTORS)
1379 						{
1380 							appendToInfoLog("Too many varyings");
1381 							return false;
1382 						}
1383 
1384 						for(int i = 0; i < registers; i++)
1385 						{
1386 							vertexBinary->setOutput(out + i, components, sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i, pixelBinary->getInput(in + i, 0).flat));
1387 						}
1388 					}
1389 					else   // Vertex varying is declared but not written to
1390 					{
1391 						for(int i = 0; i < registers; i++)
1392 						{
1393 							pixelBinary->setInput(in + i, components, sw::Shader::Semantic());
1394 						}
1395 					}
1396 
1397 					matched = true;
1398 					break;
1399 				}
1400 			}
1401 
1402 			if(!matched)
1403 			{
1404 				// For openGL ES 3.0, we need to still add the vertex shader outputs for unmatched varyings, for transform feedback.
1405 				for(const std::string &indexedTfVaryingName : transformFeedbackVaryings)
1406 				{
1407 					std::string tfVaryingName = es2::ParseUniformName(indexedTfVaryingName, nullptr);
1408 
1409 					if(tfVaryingName == output.name)
1410 					{
1411 						int out = output.registerIndex;
1412 						int components = VariableRegisterSize(output.type);
1413 						int registers = VariableRegisterCount(output.type) * output.size();
1414 
1415 						if(out >= 0)
1416 						{
1417 							if(out + registers >= MAX_VARYING_VECTORS)
1418 							{
1419 								appendToInfoLog("Too many varyings");
1420 								return false;
1421 							}
1422 
1423 							for(int i = 0; i < registers; i++)
1424 							{
1425 								vertexBinary->setOutput(out + i, components, sw::Shader::Semantic(sw::Shader::USAGE_COLOR));
1426 							}
1427 						}
1428 						break;
1429 					}
1430 				}
1431 			}
1432 		}
1433 
1434 		return true;
1435 	}
1436 
linkTransformFeedback()1437 	bool Program::linkTransformFeedback()
1438 	{
1439 		size_t totalComponents = 0;
1440 		totalLinkedVaryingsComponents = 0;
1441 
1442 		std::set<std::string> uniqueNames;
1443 
1444 		for(const std::string &indexedTfVaryingName : transformFeedbackVaryings)
1445 		{
1446 			unsigned int subscript = GL_INVALID_INDEX;
1447 			std::string tfVaryingName = es2::ParseUniformName(indexedTfVaryingName, &subscript);
1448 			bool hasSubscript = (subscript != GL_INVALID_INDEX);
1449 
1450 			if(tfVaryingName.find('[') != std::string::npos)
1451 			{
1452 				appendToInfoLog("Capture of array sub-elements is undefined and not supported.");
1453 				return false;
1454 			}
1455 
1456 			bool found = false;
1457 			for(const glsl::Varying varying : vertexShader->varyings)
1458 			{
1459 				if(tfVaryingName == varying.name)
1460 				{
1461 					if(uniqueNames.count(indexedTfVaryingName) > 0)
1462 					{
1463 						appendToInfoLog("Two transform feedback varyings specify the same output variable (%s)", indexedTfVaryingName.c_str());
1464 						return false;
1465 					}
1466 					uniqueNames.insert(indexedTfVaryingName);
1467 
1468 					if(hasSubscript && ((static_cast<int>(subscript)) >= varying.size()))
1469 					{
1470 						appendToInfoLog("Specified transform feedback varying index out of bounds (%s)", indexedTfVaryingName.c_str());
1471 						return false;
1472 					}
1473 
1474 					int size = hasSubscript ? 1 : varying.size();
1475 
1476 					int rowCount = VariableRowCount(varying.type);
1477 					int colCount = VariableColumnCount(varying.type);
1478 					int componentCount = rowCount * colCount * size;
1479 					if(transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
1480 					   componentCount > sw::MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS)
1481 					{
1482 						appendToInfoLog("Transform feedback varying's %s components (%d) exceed the maximum separate components (%d).",
1483 						                varying.name.c_str(), componentCount, sw::MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS);
1484 						return false;
1485 					}
1486 
1487 					totalComponents += componentCount;
1488 
1489 					int reg = varying.registerIndex;
1490 					if(hasSubscript)
1491 					{
1492 						reg += rowCount > 1 ? colCount * subscript : subscript;
1493 					}
1494 					int col = varying.column;
1495 					if(tfVaryingName == "gl_PointSize")
1496 					{
1497 						// Point size is stored in the y element of the vector, not the x element
1498 						col = 1; // FIXME: varying.col could already contain this information
1499 					}
1500 					transformFeedbackLinkedVaryings.push_back(LinkedVarying(varying.name, varying.type, size, reg, col));
1501 
1502 					found = true;
1503 					break;
1504 				}
1505 			}
1506 
1507 			if(!found)
1508 			{
1509 				appendToInfoLog("Transform feedback varying %s does not exist in the vertex shader.", tfVaryingName.c_str());
1510 				return false;
1511 			}
1512 		}
1513 
1514 		if(transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS &&
1515 		   totalComponents > sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS)
1516 		{
1517 			appendToInfoLog("Transform feedback varying total components (%d) exceed the maximum separate components (%d).",
1518 			                totalComponents, sw::MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS);
1519 			return false;
1520 		}
1521 
1522 		totalLinkedVaryingsComponents = totalComponents;
1523 
1524 		return true;
1525 	}
1526 
1527 	// Links the code of the vertex and pixel shader by matching up their varyings,
1528 	// compiling them into binaries, determining the attribute mappings, and collecting
1529 	// a list of uniforms
link()1530 	void Program::link()
1531 	{
1532 		unlink();
1533 
1534 		resetUniformBlockBindings();
1535 
1536 		if(!fragmentShader || !fragmentShader->isCompiled())
1537 		{
1538 			return;
1539 		}
1540 
1541 		if(!vertexShader || !vertexShader->isCompiled())
1542 		{
1543 			return;
1544 		}
1545 
1546 		vertexBinary = new sw::VertexShader(vertexShader->getVertexShader());
1547 		pixelBinary = new sw::PixelShader(fragmentShader->getPixelShader());
1548 
1549 		if(!linkVaryings())
1550 		{
1551 			return;
1552 		}
1553 
1554 		if(!linkAttributes())
1555 		{
1556 			return;
1557 		}
1558 
1559 		// Link uniform blocks before uniforms to make it easy to assign block indices to fields
1560 		if(!linkUniformBlocks(vertexShader, fragmentShader))
1561 		{
1562 			return;
1563 		}
1564 
1565 		if(!linkUniforms(fragmentShader))
1566 		{
1567 			return;
1568 		}
1569 
1570 		if(!linkUniforms(vertexShader))
1571 		{
1572 			return;
1573 		}
1574 
1575 		if(!linkTransformFeedback())
1576 		{
1577 			return;
1578 		}
1579 
1580 		linked = true;   // Success
1581 	}
1582 
1583 	// Determines the mapping between GL attributes and vertex stream usage indices
linkAttributes()1584 	bool Program::linkAttributes()
1585 	{
1586 		static_assert(MAX_VERTEX_ATTRIBS <= 32, "attribute count exceeds bitfield count");
1587 		unsigned int usedLocations = 0;
1588 
1589 		// Link attributes that have a GLSL layout location qualifier
1590 		for(auto const &attribute : vertexShader->activeAttributes)
1591 		{
1592 			if(attribute.layoutLocation != -1)
1593 			{
1594 				if(!linkAttribute(attribute, attribute.layoutLocation, usedLocations))
1595 				{
1596 					return false;
1597 				}
1598 			}
1599 		}
1600 
1601 		// Link attributes that have an API provided binding location but no GLSL layout location
1602 		for(auto const &attribute : vertexShader->activeAttributes)
1603 		{
1604 			int bindingLocation = (attributeBinding.find(attribute.name) != attributeBinding.end()) ? attributeBinding[attribute.name] : -1;
1605 
1606 			if(attribute.layoutLocation == -1 && bindingLocation != -1)
1607 			{
1608 				if(!linkAttribute(attribute, bindingLocation, usedLocations))
1609 				{
1610 					return false;
1611 				}
1612 			}
1613 		}
1614 
1615 		// Link attributes that don't have a binding location nor a layout location
1616 		for(auto const &attribute : vertexShader->activeAttributes)
1617 		{
1618 			if(attribute.layoutLocation == -1 && attributeBinding.find(attribute.name) == attributeBinding.end())
1619 			{
1620 				if(!linkAttribute(attribute, -1, usedLocations))
1621 				{
1622 					return false;
1623 				}
1624 			}
1625 		}
1626 
1627 		ASSERT(linkedAttribute.size() == vertexShader->activeAttributes.size());
1628 
1629 		for(auto const &attribute : linkedAttribute)
1630 		{
1631 			int location = getAttributeLocation(attribute.name);
1632 			ASSERT(location >= 0);
1633 			int index = vertexShader->getSemanticIndex(attribute.name);
1634 			int rows = VariableRegisterCount(attribute.type);
1635 
1636 			for(int r = 0; r < rows; r++)
1637 			{
1638 				attributeStream[r + location] = index++;
1639 			}
1640 		}
1641 
1642 		return true;
1643 	}
1644 
linkAttribute(const glsl::Attribute & attribute,int location,unsigned int & usedLocations)1645 	bool Program::linkAttribute(const glsl::Attribute &attribute, int location, unsigned int &usedLocations)
1646 	{
1647 		int rows = VariableRegisterCount(attribute.type);
1648 
1649 		if(location == -1)
1650 		{
1651 			location = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
1652 
1653 			if(location == -1 || location + rows > MAX_VERTEX_ATTRIBS)
1654 			{
1655 				appendToInfoLog("Too many active attributes (%s)", attribute.name.c_str());
1656 				return false;   // Fail to link
1657 			}
1658 		}
1659 		else
1660 		{
1661 			if(rows + location > MAX_VERTEX_ATTRIBS)
1662 			{
1663 				appendToInfoLog("Active attribute (%s) at location %d is too big to fit", attribute.name.c_str(), location);
1664 				return false;
1665 			}
1666 
1667 			// In GLSL 3.00, attribute aliasing produces a link error
1668 			// In GLSL 1.00, attribute aliasing is allowed
1669 			if(vertexShader->getShaderVersion() >= 300)
1670 			{
1671 				for(auto const &previousAttrib : linkedAttribute)
1672 				{
1673 					int previousLocation = getAttributeLocation(previousAttrib.name);
1674 					int previousRows = VariableRegisterCount(previousAttrib.type);
1675 
1676 					if(location >= previousLocation && location < previousLocation + previousRows)
1677 					{
1678 						appendToInfoLog("Attribute '%s' aliases attribute '%s' at location %d", attribute.name.c_str(), previousAttrib.name.c_str(), location);
1679 						return false;
1680 					}
1681 
1682 					if(location <= previousLocation && location + rows > previousLocation)
1683 					{
1684 						appendToInfoLog("Attribute '%s' aliases attribute '%s' at location %d", attribute.name.c_str(), previousAttrib.name.c_str(), previousLocation);
1685 						return false;
1686 					}
1687 				}
1688 			}
1689 
1690 			for(int i = 0; i < rows; i++)
1691 			{
1692 				usedLocations |= 1 << (location + i);
1693 			}
1694 		}
1695 
1696 		linkedAttributeLocation[attribute.name] = location;
1697 		linkedAttribute.push_back(attribute);
1698 
1699 		return true;
1700 	}
1701 
getAttributeLocation(const std::string & name)1702 	int Program::getAttributeLocation(const std::string &name)
1703 	{
1704 		std::map<std::string, GLuint>::const_iterator attribute = linkedAttributeLocation.find(name);
1705 		if(attribute != linkedAttributeLocation.end())
1706 		{
1707 			return attribute->second;
1708 		}
1709 
1710 		return -1;
1711 	}
1712 
linkUniforms(const Shader * shader)1713 	bool Program::linkUniforms(const Shader *shader)
1714 	{
1715 		for(const auto &uniform : shader->activeUniforms)
1716 		{
1717 			unsigned int blockIndex = GL_INVALID_INDEX;
1718 			if(uniform.blockId >= 0)
1719 			{
1720 				const glsl::ActiveUniformBlocks &activeUniformBlocks = shader->activeUniformBlocks;
1721 				ASSERT(static_cast<size_t>(uniform.blockId) < activeUniformBlocks.size());
1722 				const std::string &uniformBlockName = activeUniformBlocks[uniform.blockId].name;
1723 				blockIndex = getUniformBlockIndex(uniformBlockName);
1724 				ASSERT(blockIndex != GL_INVALID_INDEX);
1725 
1726 				if(activeUniformBlocks[uniform.blockId].dataSize > MAX_UNIFORM_BLOCK_SIZE)
1727 				{
1728 					if(shader->getType() == GL_VERTEX_SHADER)
1729 					{
1730 						appendToInfoLog("Vertex shader active uniform block (%s) exceeds GL_MAX_UNIFORM_BLOCK_SIZE (%d)", uniformBlockName.c_str(), MAX_UNIFORM_BLOCK_SIZE);
1731 						return false;
1732 					}
1733 					else if(shader->getType() == GL_FRAGMENT_SHADER)
1734 					{
1735 						appendToInfoLog("Fragment shader active uniform block (%s) exceeds GL_MAX_UNIFORM_BLOCK_SIZE (%d)", uniformBlockName.c_str(), MAX_UNIFORM_BLOCK_SIZE);
1736 						return false;
1737 					}
1738 					else UNREACHABLE(shader->getType());
1739 				}
1740 			}
1741 
1742 			if(!defineUniform(shader->getType(), uniform, Uniform::BlockInfo(uniform, blockIndex)))
1743 			{
1744 				return false;
1745 			}
1746 		}
1747 
1748 		for(const auto &uniformStruct : shader->activeUniformStructs)
1749 		{
1750 			if(!validateUniformStruct(shader->getType(), uniformStruct))
1751 			{
1752 				return false;
1753 			}
1754 		}
1755 
1756 		return true;
1757 	}
1758 
defineUniform(GLenum shader,const glsl::Uniform & glslUniform,const Uniform::BlockInfo & blockInfo)1759 	bool Program::defineUniform(GLenum shader, const glsl::Uniform &glslUniform, const Uniform::BlockInfo& blockInfo)
1760 	{
1761 		if(IsSamplerUniform(glslUniform.type))
1762 		{
1763 			int index = glslUniform.registerIndex;
1764 
1765 			do
1766 			{
1767 				if(shader == GL_VERTEX_SHADER)
1768 				{
1769 					if(index < MAX_VERTEX_TEXTURE_IMAGE_UNITS)
1770 					{
1771 						samplersVS[index].active = true;
1772 
1773 						switch(glslUniform.type)
1774 						{
1775 						default:                      UNREACHABLE(glslUniform.type);
1776 						case GL_INT_SAMPLER_2D:
1777 						case GL_UNSIGNED_INT_SAMPLER_2D:
1778 						case GL_SAMPLER_2D_SHADOW:
1779 						case GL_SAMPLER_2D:           samplersVS[index].textureType = TEXTURE_2D;       break;
1780 						case GL_INT_SAMPLER_CUBE:
1781 						case GL_UNSIGNED_INT_SAMPLER_CUBE:
1782 						case GL_SAMPLER_CUBE_SHADOW:
1783 						case GL_SAMPLER_CUBE:         samplersVS[index].textureType = TEXTURE_CUBE;     break;
1784 						case GL_INT_SAMPLER_3D:
1785 						case GL_UNSIGNED_INT_SAMPLER_3D:
1786 						case GL_SAMPLER_3D_OES:       samplersVS[index].textureType = TEXTURE_3D;       break;
1787 						case GL_SAMPLER_2D_RECT_ARB:  samplersVS[index].textureType = TEXTURE_2D_RECT;  break;
1788 						case GL_SAMPLER_EXTERNAL_OES: samplersVS[index].textureType = TEXTURE_EXTERNAL; break;
1789 						case GL_INT_SAMPLER_2D_ARRAY:
1790 						case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
1791 						case GL_SAMPLER_2D_ARRAY_SHADOW:
1792 						case GL_SAMPLER_2D_ARRAY:     samplersVS[index].textureType = TEXTURE_2D_ARRAY; break;
1793 						}
1794 
1795 						samplersVS[index].logicalTextureUnit = 0;
1796 					}
1797 					else
1798 					{
1799 					   appendToInfoLog("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", MAX_VERTEX_TEXTURE_IMAGE_UNITS);
1800 					   return false;
1801 					}
1802 				}
1803 				else if(shader == GL_FRAGMENT_SHADER)
1804 				{
1805 					if(index < MAX_TEXTURE_IMAGE_UNITS)
1806 					{
1807 						samplersPS[index].active = true;
1808 
1809 						switch(glslUniform.type)
1810 						{
1811 						default:                      UNREACHABLE(glslUniform.type);
1812 						case GL_INT_SAMPLER_2D:
1813 						case GL_UNSIGNED_INT_SAMPLER_2D:
1814 						case GL_SAMPLER_2D_SHADOW:
1815 						case GL_SAMPLER_2D:           samplersPS[index].textureType = TEXTURE_2D;       break;
1816 						case GL_INT_SAMPLER_CUBE:
1817 						case GL_UNSIGNED_INT_SAMPLER_CUBE:
1818 						case GL_SAMPLER_CUBE_SHADOW:
1819 						case GL_SAMPLER_CUBE:         samplersPS[index].textureType = TEXTURE_CUBE;     break;
1820 						case GL_INT_SAMPLER_3D:
1821 						case GL_UNSIGNED_INT_SAMPLER_3D:
1822 						case GL_SAMPLER_3D_OES:       samplersPS[index].textureType = TEXTURE_3D;       break;
1823 						case GL_SAMPLER_2D_RECT_ARB:  samplersPS[index].textureType = TEXTURE_2D_RECT;  break;
1824 						case GL_SAMPLER_EXTERNAL_OES: samplersPS[index].textureType = TEXTURE_EXTERNAL; break;
1825 						case GL_INT_SAMPLER_2D_ARRAY:
1826 						case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
1827 						case GL_SAMPLER_2D_ARRAY_SHADOW:
1828 						case GL_SAMPLER_2D_ARRAY:     samplersPS[index].textureType = TEXTURE_2D_ARRAY; break;
1829 						}
1830 
1831 						samplersPS[index].logicalTextureUnit = 0;
1832 					}
1833 					else
1834 					{
1835 						appendToInfoLog("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
1836 						return false;
1837 					}
1838 				}
1839 				else UNREACHABLE(shader);
1840 
1841 				index++;
1842 			}
1843 			while(index < glslUniform.registerIndex + static_cast<int>(glslUniform.arraySize));
1844 		}
1845 
1846 		Uniform *uniform = getUniform(glslUniform.name);
1847 
1848 		if(!uniform)
1849 		{
1850 			uniform = new Uniform(glslUniform, blockInfo);
1851 			uniforms.push_back(uniform);
1852 
1853 			unsigned int index = (blockInfo.index == -1) ? static_cast<unsigned int>(uniforms.size() - 1) : GL_INVALID_INDEX;
1854 
1855 			for(int i = 0; i < uniform->size(); i++)
1856 			{
1857 				uniformIndex.push_back(UniformLocation(glslUniform.name, i, index));
1858 			}
1859 		}
1860 		else   // Previously defined, types must match
1861 		{
1862 			if(uniform->type != glslUniform.type)
1863 			{
1864 				appendToInfoLog("Types for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str());
1865 				return false;
1866 			}
1867 
1868 			if(uniform->precision != glslUniform.precision)
1869 			{
1870 				appendToInfoLog("Precisions for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str());
1871 				return false;
1872 			}
1873 
1874 			if(!areMatchingFields(uniform->fields, glslUniform.fields, uniform->name))
1875 			{
1876 				return false;
1877 			}
1878 		}
1879 
1880 		if(shader == GL_VERTEX_SHADER)
1881 		{
1882 			uniform->vsRegisterIndex = glslUniform.registerIndex;
1883 		}
1884 		else if(shader == GL_FRAGMENT_SHADER)
1885 		{
1886 			uniform->psRegisterIndex = glslUniform.registerIndex;
1887 		}
1888 		else UNREACHABLE(shader);
1889 
1890 		if(uniform->blockInfo.index < 0)
1891 		{
1892 			if(shader == GL_VERTEX_SHADER)
1893 			{
1894 				if(glslUniform.registerIndex + uniform->registerCount() > MAX_VERTEX_UNIFORM_VECTORS)
1895 				{
1896 					appendToInfoLog("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%d)", MAX_VERTEX_UNIFORM_VECTORS);
1897 					return false;
1898 				}
1899 			}
1900 			else if(shader == GL_FRAGMENT_SHADER)
1901 			{
1902 				if(glslUniform.registerIndex + uniform->registerCount() > MAX_FRAGMENT_UNIFORM_VECTORS)
1903 				{
1904 					appendToInfoLog("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%d)", MAX_FRAGMENT_UNIFORM_VECTORS);
1905 					return false;
1906 				}
1907 			}
1908 			else UNREACHABLE(shader);
1909 		}
1910 
1911 		return true;
1912 	}
1913 
validateUniformStruct(GLenum shader,const glsl::Uniform & newUniformStruct)1914 	bool Program::validateUniformStruct(GLenum shader, const glsl::Uniform &newUniformStruct)
1915 	{
1916 		for(const auto &uniformStruct : uniformStructs)
1917 		{
1918 			if(uniformStruct.name == newUniformStruct.name)
1919 			{
1920 				return areMatchingFields(uniformStruct.fields, newUniformStruct.fields, newUniformStruct.name);
1921 			}
1922 		}
1923 
1924 		uniformStructs.push_back(Uniform(newUniformStruct, Uniform::BlockInfo(newUniformStruct, -1)));
1925 
1926 		return true;
1927 	}
1928 
areMatchingUniformBlocks(const glsl::UniformBlock & block1,const glsl::UniformBlock & block2,const Shader * shader1,const Shader * shader2)1929 	bool Program::areMatchingUniformBlocks(const glsl::UniformBlock &block1, const glsl::UniformBlock &block2, const Shader *shader1, const Shader *shader2)
1930 	{
1931 		// validate blocks for the same member types
1932 		if(block1.fields.size() != block2.fields.size())
1933 		{
1934 			appendToInfoLog("Types for interface block '%s' differ between vertex and fragment shaders", block1.name.c_str());
1935 			return false;
1936 		}
1937 		if(block1.arraySize != block2.arraySize)
1938 		{
1939 			appendToInfoLog("Array sizes differ for interface block '%s' between vertex and fragment shaders", block1.name.c_str());
1940 			return false;
1941 		}
1942 		if(block1.layout != block2.layout || block1.isRowMajorLayout != block2.isRowMajorLayout)
1943 		{
1944 			appendToInfoLog("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", block1.name.c_str());
1945 			return false;
1946 		}
1947 		const size_t numBlockMembers = block1.fields.size();
1948 		for(size_t blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
1949 		{
1950 			const glsl::Uniform& member1 = shader1->activeUniforms[block1.fields[blockMemberIndex]];
1951 			const glsl::Uniform& member2 = shader2->activeUniforms[block2.fields[blockMemberIndex]];
1952 			if(member1.name != member2.name)
1953 			{
1954 				appendToInfoLog("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')",
1955 				                blockMemberIndex, block1.name.c_str(), member1.name.c_str(), member2.name.c_str());
1956 				return false;
1957 			}
1958 			if(member1.arraySize != member2.arraySize)
1959 			{
1960 				appendToInfoLog("Array sizes for %s differ between vertex and fragment shaders", member1.name.c_str());
1961 				return false;
1962 			}
1963 			if(member1.precision != member2.precision)
1964 			{
1965 				appendToInfoLog("Precisions for %s differ between vertex and fragment shaders", member1.name.c_str());
1966 				return false;
1967 			}
1968 			if(member1.type != member2.type)
1969 			{
1970 				appendToInfoLog("Types for %s differ between vertex and fragment shaders", member1.name.c_str());
1971 				return false;
1972 			}
1973 			if(member1.blockInfo.isRowMajorMatrix != member2.blockInfo.isRowMajorMatrix)
1974 			{
1975 				appendToInfoLog("Matrix packings for %s differ between vertex and fragment shaders", member1.name.c_str());
1976 				return false;
1977 			}
1978 		}
1979 		return true;
1980 	}
1981 
areMatchingFields(const std::vector<glsl::ShaderVariable> & fields1,const std::vector<glsl::ShaderVariable> & fields2,const std::string & name)1982 	bool Program::areMatchingFields(const std::vector<glsl::ShaderVariable>& fields1, const std::vector<glsl::ShaderVariable>& fields2, const std::string& name)
1983 	{
1984 		if(fields1.size() != fields2.size())
1985 		{
1986 			appendToInfoLog("Structure lengths for %s differ between vertex and fragment shaders", name.c_str());
1987 			return false;
1988 		}
1989 
1990 		for(size_t i = 0; i < fields1.size(); ++i)
1991 		{
1992 			if(fields1[i].name != fields2[i].name)
1993 			{
1994 				appendToInfoLog("Name mismatch for field '%d' of %s: ('%s', '%s')",
1995 				                i, name.c_str(), fields1[i].name.c_str(), fields2[i].name.c_str());
1996 				return false;
1997 			}
1998 			if(fields1[i].type != fields2[i].type)
1999 			{
2000 				appendToInfoLog("Type for %s.%s differ between vertex and fragment shaders", name.c_str(), fields1[i].name.c_str());
2001 				return false;
2002 			}
2003 			if(fields1[i].arraySize != fields2[i].arraySize)
2004 			{
2005 				appendToInfoLog("Array size for %s.%s differ between vertex and fragment shaders", name.c_str(), fields1[i].name.c_str());
2006 				return false;
2007 			}
2008 			if(!areMatchingFields(fields1[i].fields, fields2[i].fields, fields1[i].name))
2009 			{
2010 				return false;
2011 			}
2012 		}
2013 
2014 		return true;
2015 	}
2016 
linkUniformBlocks(const Shader * vertexShader,const Shader * fragmentShader)2017 	bool Program::linkUniformBlocks(const Shader *vertexShader, const Shader *fragmentShader)
2018 	{
2019 		const glsl::ActiveUniformBlocks &vertexUniformBlocks = vertexShader->activeUniformBlocks;
2020 		const glsl::ActiveUniformBlocks &fragmentUniformBlocks = fragmentShader->activeUniformBlocks;
2021 		// Check that interface blocks defined in the vertex and fragment shaders are identical
2022 		typedef std::map<std::string, const glsl::UniformBlock*> UniformBlockMap;
2023 		UniformBlockMap linkedUniformBlocks;
2024 		for(unsigned int blockIndex = 0; blockIndex < vertexUniformBlocks.size(); blockIndex++)
2025 		{
2026 			const glsl::UniformBlock &vertexUniformBlock = vertexUniformBlocks[blockIndex];
2027 			linkedUniformBlocks[vertexUniformBlock.name] = &vertexUniformBlock;
2028 		}
2029 		for(unsigned int blockIndex = 0; blockIndex < fragmentUniformBlocks.size(); blockIndex++)
2030 		{
2031 			const glsl::UniformBlock &fragmentUniformBlock = fragmentUniformBlocks[blockIndex];
2032 			UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentUniformBlock.name);
2033 			if(entry != linkedUniformBlocks.end())
2034 			{
2035 				const glsl::UniformBlock &vertexUniformBlock = *entry->second;
2036 				if(!areMatchingUniformBlocks(vertexUniformBlock, fragmentUniformBlock, vertexShader, fragmentShader))
2037 				{
2038 					return false;
2039 				}
2040 			}
2041 		}
2042 		for(unsigned int blockIndex = 0; blockIndex < vertexUniformBlocks.size(); blockIndex++)
2043 		{
2044 			const glsl::UniformBlock &uniformBlock = vertexUniformBlocks[blockIndex];
2045 			if(!defineUniformBlock(vertexShader, uniformBlock))
2046 			{
2047 				return false;
2048 			}
2049 		}
2050 		for(unsigned int blockIndex = 0; blockIndex < fragmentUniformBlocks.size(); blockIndex++)
2051 		{
2052 			const glsl::UniformBlock &uniformBlock = fragmentUniformBlocks[blockIndex];
2053 			if(!defineUniformBlock(fragmentShader, uniformBlock))
2054 			{
2055 				return false;
2056 			}
2057 		}
2058 		return true;
2059 	}
2060 
defineUniformBlock(const Shader * shader,const glsl::UniformBlock & block)2061 	bool Program::defineUniformBlock(const Shader *shader, const glsl::UniformBlock &block)
2062 	{
2063 		GLuint blockIndex = getUniformBlockIndex(block.name);
2064 
2065 		if(blockIndex == GL_INVALID_INDEX)
2066 		{
2067 			const std::vector<int>& fields = block.fields;
2068 			std::vector<unsigned int> memberUniformIndexes;
2069 			for(size_t i = 0; i < fields.size(); ++i)
2070 			{
2071 				memberUniformIndexes.push_back(fields[i]);
2072 			}
2073 
2074 			if(block.arraySize > 0)
2075 			{
2076 				int regIndex = block.registerIndex;
2077 				int regInc = block.dataSize / (glsl::BlockLayoutEncoder::BytesPerComponent * glsl::BlockLayoutEncoder::ComponentsPerRegister);
2078 				for(unsigned int i = 0; i < block.arraySize; ++i, regIndex += regInc)
2079 				{
2080 					uniformBlocks.push_back(new UniformBlock(block.name, i, block.dataSize, memberUniformIndexes));
2081 					uniformBlocks[uniformBlocks.size() - 1]->setRegisterIndex(shader->getType(), regIndex);
2082 				}
2083 			}
2084 			else
2085 			{
2086 				uniformBlocks.push_back(new UniformBlock(block.name, GL_INVALID_INDEX, block.dataSize, memberUniformIndexes));
2087 				uniformBlocks[uniformBlocks.size() - 1]->setRegisterIndex(shader->getType(), block.registerIndex);
2088 			}
2089 		}
2090 		else
2091 		{
2092 			int regIndex = block.registerIndex;
2093 			int regInc = block.dataSize / (glsl::BlockLayoutEncoder::BytesPerComponent * glsl::BlockLayoutEncoder::ComponentsPerRegister);
2094 			int nbBlocks = (block.arraySize > 0) ? block.arraySize : 1;
2095 			for(int i = 0; i < nbBlocks; ++i, regIndex += regInc)
2096 			{
2097 				uniformBlocks[blockIndex + i]->setRegisterIndex(shader->getType(), regIndex);
2098 			}
2099 		}
2100 
2101 		return true;
2102 	}
2103 
applyUniform(Device * device,GLint location,float * data)2104 	bool Program::applyUniform(Device *device, GLint location, float* data)
2105 	{
2106 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
2107 
2108 		if(targetUniform->psRegisterIndex != -1)
2109 		{
2110 			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, data, targetUniform->registerCount());
2111 		}
2112 
2113 		if(targetUniform->vsRegisterIndex != -1)
2114 		{
2115 			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, data, targetUniform->registerCount());
2116 		}
2117 
2118 		return true;
2119 	}
2120 
applyUniform1bv(Device * device,GLint location,GLsizei count,const GLboolean * v)2121 	bool Program::applyUniform1bv(Device *device, GLint location, GLsizei count, const GLboolean *v)
2122 	{
2123 		int vector[MAX_UNIFORM_VECTORS][4];
2124 
2125 		for(int i = 0; i < count; i++)
2126 		{
2127 			vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2128 			vector[i][1] = 0;
2129 			vector[i][2] = 0;
2130 			vector[i][3] = 0;
2131 
2132 			v += 1;
2133 		}
2134 
2135 		return applyUniform(device, location, (float*)vector);
2136 	}
2137 
applyUniform2bv(Device * device,GLint location,GLsizei count,const GLboolean * v)2138 	bool Program::applyUniform2bv(Device *device, GLint location, GLsizei count, const GLboolean *v)
2139 	{
2140 		int vector[MAX_UNIFORM_VECTORS][4];
2141 
2142 		for(int i = 0; i < count; i++)
2143 		{
2144 			vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2145 			vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2146 			vector[i][2] = 0;
2147 			vector[i][3] = 0;
2148 
2149 			v += 2;
2150 		}
2151 
2152 		return applyUniform(device, location, (float*)vector);
2153 	}
2154 
applyUniform3bv(Device * device,GLint location,GLsizei count,const GLboolean * v)2155 	bool Program::applyUniform3bv(Device *device, GLint location, GLsizei count, const GLboolean *v)
2156 	{
2157 		int vector[MAX_UNIFORM_VECTORS][4];
2158 
2159 		for(int i = 0; i < count; i++)
2160 		{
2161 			vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2162 			vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2163 			vector[i][2] = (v[2] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2164 			vector[i][3] = 0;
2165 
2166 			v += 3;
2167 		}
2168 
2169 		return applyUniform(device, location, (float*)vector);
2170 	}
2171 
applyUniform4bv(Device * device,GLint location,GLsizei count,const GLboolean * v)2172 	bool Program::applyUniform4bv(Device *device, GLint location, GLsizei count, const GLboolean *v)
2173 	{
2174 		int vector[MAX_UNIFORM_VECTORS][4];
2175 
2176 		for(int i = 0; i < count; i++)
2177 		{
2178 			vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2179 			vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2180 			vector[i][2] = (v[2] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2181 			vector[i][3] = (v[3] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
2182 
2183 			v += 4;
2184 		}
2185 
2186 		return applyUniform(device, location, (float*)vector);
2187 	}
2188 
applyUniform1fv(Device * device,GLint location,GLsizei count,const GLfloat * v)2189 	bool Program::applyUniform1fv(Device *device, GLint location, GLsizei count, const GLfloat *v)
2190 	{
2191 		float vector[MAX_UNIFORM_VECTORS][4];
2192 
2193 		for(int i = 0; i < count; i++)
2194 		{
2195 			vector[i][0] = v[0];
2196 			vector[i][1] = 0;
2197 			vector[i][2] = 0;
2198 			vector[i][3] = 0;
2199 
2200 			v += 1;
2201 		}
2202 
2203 		return applyUniform(device, location, (float*)vector);
2204 	}
2205 
applyUniform2fv(Device * device,GLint location,GLsizei count,const GLfloat * v)2206 	bool Program::applyUniform2fv(Device *device, GLint location, GLsizei count, const GLfloat *v)
2207 	{
2208 		float vector[MAX_UNIFORM_VECTORS][4];
2209 
2210 		for(int i = 0; i < count; i++)
2211 		{
2212 			vector[i][0] = v[0];
2213 			vector[i][1] = v[1];
2214 			vector[i][2] = 0;
2215 			vector[i][3] = 0;
2216 
2217 			v += 2;
2218 		}
2219 
2220 		return applyUniform(device, location, (float*)vector);
2221 	}
2222 
applyUniform3fv(Device * device,GLint location,GLsizei count,const GLfloat * v)2223 	bool Program::applyUniform3fv(Device *device, GLint location, GLsizei count, const GLfloat *v)
2224 	{
2225 		float vector[MAX_UNIFORM_VECTORS][4];
2226 
2227 		for(int i = 0; i < count; i++)
2228 		{
2229 			vector[i][0] = v[0];
2230 			vector[i][1] = v[1];
2231 			vector[i][2] = v[2];
2232 			vector[i][3] = 0;
2233 
2234 			v += 3;
2235 		}
2236 
2237 		return applyUniform(device, location, (float*)vector);
2238 	}
2239 
applyUniform4fv(Device * device,GLint location,GLsizei count,const GLfloat * v)2240 	bool Program::applyUniform4fv(Device *device, GLint location, GLsizei count, const GLfloat *v)
2241 	{
2242 		return applyUniform(device, location, (float*)v);
2243 	}
2244 
applyUniformMatrix2fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2245 	bool Program::applyUniformMatrix2fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2246 	{
2247 		float matrix[(MAX_UNIFORM_VECTORS + 1) / 2][2][4];
2248 
2249 		for(int i = 0; i < count; i++)
2250 		{
2251 			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];	matrix[i][0][2] = 0; matrix[i][0][3] = 0;
2252 			matrix[i][1][0] = value[2];	matrix[i][1][1] = value[3];	matrix[i][1][2] = 0; matrix[i][1][3] = 0;
2253 
2254 			value += 4;
2255 		}
2256 
2257 		return applyUniform(device, location, (float*)matrix);
2258 	}
2259 
applyUniformMatrix2x3fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2260 	bool Program::applyUniformMatrix2x3fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2261 	{
2262 		float matrix[(MAX_UNIFORM_VECTORS + 1) / 2][2][4];
2263 
2264 		for(int i = 0; i < count; i++)
2265 		{
2266 			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];	matrix[i][0][2] = value[2]; matrix[i][0][3] = 0;
2267 			matrix[i][1][0] = value[3];	matrix[i][1][1] = value[4];	matrix[i][1][2] = value[5]; matrix[i][1][3] = 0;
2268 
2269 			value += 6;
2270 		}
2271 
2272 		return applyUniform(device, location, (float*)matrix);
2273 	}
2274 
applyUniformMatrix2x4fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2275 	bool Program::applyUniformMatrix2x4fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2276 	{
2277 		float matrix[(MAX_UNIFORM_VECTORS + 1) / 2][2][4];
2278 
2279 		for(int i = 0; i < count; i++)
2280 		{
2281 			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];	matrix[i][0][2] = value[2]; matrix[i][0][3] = value[3];
2282 			matrix[i][1][0] = value[4];	matrix[i][1][1] = value[5];	matrix[i][1][2] = value[6]; matrix[i][1][3] = value[7];
2283 
2284 			value += 8;
2285 		}
2286 
2287 		return applyUniform(device, location, (float*)matrix);
2288 	}
2289 
applyUniformMatrix3fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2290 	bool Program::applyUniformMatrix3fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2291 	{
2292 		float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4];
2293 
2294 		for(int i = 0; i < count; i++)
2295 		{
2296 			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];	matrix[i][0][2] = value[2];	matrix[i][0][3] = 0;
2297 			matrix[i][1][0] = value[3];	matrix[i][1][1] = value[4];	matrix[i][1][2] = value[5];	matrix[i][1][3] = 0;
2298 			matrix[i][2][0] = value[6];	matrix[i][2][1] = value[7];	matrix[i][2][2] = value[8];	matrix[i][2][3] = 0;
2299 
2300 			value += 9;
2301 		}
2302 
2303 		return applyUniform(device, location, (float*)matrix);
2304 	}
2305 
applyUniformMatrix3x2fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2306 	bool Program::applyUniformMatrix3x2fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2307 	{
2308 		float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4];
2309 
2310 		for(int i = 0; i < count; i++)
2311 		{
2312 			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];	matrix[i][0][2] = 0; matrix[i][0][3] = 0;
2313 			matrix[i][1][0] = value[2];	matrix[i][1][1] = value[3];	matrix[i][1][2] = 0; matrix[i][1][3] = 0;
2314 			matrix[i][2][0] = value[4];	matrix[i][2][1] = value[5];	matrix[i][2][2] = 0; matrix[i][2][3] = 0;
2315 
2316 			value += 6;
2317 		}
2318 
2319 		return applyUniform(device, location, (float*)matrix);
2320 	}
2321 
applyUniformMatrix3x4fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2322 	bool Program::applyUniformMatrix3x4fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2323 	{
2324 		float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4];
2325 
2326 		for(int i = 0; i < count; i++)
2327 		{
2328 			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];	matrix[i][0][2] = value[2]; 	matrix[i][0][3] = value[3];
2329 			matrix[i][1][0] = value[4];	matrix[i][1][1] = value[5];	matrix[i][1][2] = value[6]; 	matrix[i][1][3] = value[7];
2330 			matrix[i][2][0] = value[8];	matrix[i][2][1] = value[9];	matrix[i][2][2] = value[10];	matrix[i][2][3] = value[11];
2331 
2332 			value += 12;
2333 		}
2334 
2335 		return applyUniform(device, location, (float*)matrix);
2336 	}
2337 
applyUniformMatrix4fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2338 	bool Program::applyUniformMatrix4fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2339 	{
2340 		return applyUniform(device, location, (float*)value);
2341 	}
2342 
applyUniformMatrix4x2fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2343 	bool Program::applyUniformMatrix4x2fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2344 	{
2345 		float matrix[(MAX_UNIFORM_VECTORS + 3) / 4][4][4];
2346 
2347 		for(int i = 0; i < count; i++)
2348 		{
2349 			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];	matrix[i][0][2] = 0; matrix[i][0][3] = 0;
2350 			matrix[i][1][0] = value[2];	matrix[i][1][1] = value[3];	matrix[i][1][2] = 0; matrix[i][1][3] = 0;
2351 			matrix[i][2][0] = value[4];	matrix[i][2][1] = value[5];	matrix[i][2][2] = 0; matrix[i][2][3] = 0;
2352 			matrix[i][3][0] = value[6];	matrix[i][3][1] = value[7];	matrix[i][3][2] = 0; matrix[i][3][3] = 0;
2353 
2354 			value += 8;
2355 		}
2356 
2357 		return applyUniform(device, location, (float*)matrix);
2358 	}
2359 
applyUniformMatrix4x3fv(Device * device,GLint location,GLsizei count,const GLfloat * value)2360 	bool Program::applyUniformMatrix4x3fv(Device *device, GLint location, GLsizei count, const GLfloat *value)
2361 	{
2362 		float matrix[(MAX_UNIFORM_VECTORS + 3) / 4][4][4];
2363 
2364 		for(int i = 0; i < count; i++)
2365 		{
2366 			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];  matrix[i][0][2] = value[2];  matrix[i][0][3] = 0;
2367 			matrix[i][1][0] = value[3];	matrix[i][1][1] = value[4];  matrix[i][1][2] = value[5];  matrix[i][1][3] = 0;
2368 			matrix[i][2][0] = value[6];	matrix[i][2][1] = value[7];  matrix[i][2][2] = value[8];  matrix[i][2][3] = 0;
2369 			matrix[i][3][0] = value[9];	matrix[i][3][1] = value[10]; matrix[i][3][2] = value[11]; matrix[i][3][3] = 0;
2370 
2371 			value += 12;
2372 		}
2373 
2374 		return applyUniform(device, location, (float*)matrix);
2375 	}
2376 
applyUniform1iv(Device * device,GLint location,GLsizei count,const GLint * v)2377 	bool Program::applyUniform1iv(Device *device, GLint location, GLsizei count, const GLint *v)
2378 	{
2379 		GLint vector[MAX_UNIFORM_VECTORS][4];
2380 
2381 		for(int i = 0; i < count; i++)
2382 		{
2383 			vector[i][0] = v[i];
2384 			vector[i][1] = 0;
2385 			vector[i][2] = 0;
2386 			vector[i][3] = 0;
2387 		}
2388 
2389 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
2390 		if(IsSamplerUniform(targetUniform->type))
2391 		{
2392 			if(targetUniform->psRegisterIndex != -1)
2393 			{
2394 				for(int i = 0; i < count; i++)
2395 				{
2396 					unsigned int samplerIndex = targetUniform->psRegisterIndex + i;
2397 
2398 					if(samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
2399 					{
2400 						ASSERT(samplersPS[samplerIndex].active);
2401 						samplersPS[samplerIndex].logicalTextureUnit = v[i];
2402 					}
2403 				}
2404 			}
2405 
2406 			if(targetUniform->vsRegisterIndex != -1)
2407 			{
2408 				for(int i = 0; i < count; i++)
2409 				{
2410 					unsigned int samplerIndex = targetUniform->vsRegisterIndex + i;
2411 
2412 					if(samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS)
2413 					{
2414 						ASSERT(samplersVS[samplerIndex].active);
2415 						samplersVS[samplerIndex].logicalTextureUnit = v[i];
2416 					}
2417 				}
2418 			}
2419 		}
2420 		else
2421 		{
2422 			return applyUniform(device, location, (float*)vector);
2423 		}
2424 
2425 		return true;
2426 	}
2427 
applyUniform2iv(Device * device,GLint location,GLsizei count,const GLint * v)2428 	bool Program::applyUniform2iv(Device *device, GLint location, GLsizei count, const GLint *v)
2429 	{
2430 		GLint vector[MAX_UNIFORM_VECTORS][4];
2431 
2432 		for(int i = 0; i < count; i++)
2433 		{
2434 			vector[i][0] = v[0];
2435 			vector[i][1] = v[1];
2436 			vector[i][2] = 0;
2437 			vector[i][3] = 0;
2438 
2439 			v += 2;
2440 		}
2441 
2442 		return applyUniform(device, location, (float*)vector);
2443 	}
2444 
applyUniform3iv(Device * device,GLint location,GLsizei count,const GLint * v)2445 	bool Program::applyUniform3iv(Device *device, GLint location, GLsizei count, const GLint *v)
2446 	{
2447 		GLint vector[MAX_UNIFORM_VECTORS][4];
2448 
2449 		for(int i = 0; i < count; i++)
2450 		{
2451 			vector[i][0] = v[0];
2452 			vector[i][1] = v[1];
2453 			vector[i][2] = v[2];
2454 			vector[i][3] = 0;
2455 
2456 			v += 3;
2457 		}
2458 
2459 		return applyUniform(device, location, (float*)vector);
2460 	}
2461 
applyUniform4iv(Device * device,GLint location,GLsizei count,const GLint * v)2462 	bool Program::applyUniform4iv(Device *device, GLint location, GLsizei count, const GLint *v)
2463 	{
2464 		GLint vector[MAX_UNIFORM_VECTORS][4];
2465 
2466 		for(int i = 0; i < count; i++)
2467 		{
2468 			vector[i][0] = v[0];
2469 			vector[i][1] = v[1];
2470 			vector[i][2] = v[2];
2471 			vector[i][3] = v[3];
2472 
2473 			v += 4;
2474 		}
2475 
2476 		return applyUniform(device, location, (float*)vector);
2477 	}
2478 
applyUniform1uiv(Device * device,GLint location,GLsizei count,const GLuint * v)2479 	bool Program::applyUniform1uiv(Device *device, GLint location, GLsizei count, const GLuint *v)
2480 	{
2481 		GLuint vector[MAX_UNIFORM_VECTORS][4];
2482 
2483 		for(int i = 0; i < count; i++)
2484 		{
2485 			vector[i][0] = v[i];
2486 			vector[i][1] = 0;
2487 			vector[i][2] = 0;
2488 			vector[i][3] = 0;
2489 		}
2490 
2491 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
2492 		if(IsSamplerUniform(targetUniform->type))
2493 		{
2494 			if(targetUniform->psRegisterIndex != -1)
2495 			{
2496 				for(int i = 0; i < count; i++)
2497 				{
2498 					unsigned int samplerIndex = targetUniform->psRegisterIndex + i;
2499 
2500 					if(samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
2501 					{
2502 						ASSERT(samplersPS[samplerIndex].active);
2503 						samplersPS[samplerIndex].logicalTextureUnit = v[i];
2504 					}
2505 				}
2506 			}
2507 
2508 			if(targetUniform->vsRegisterIndex != -1)
2509 			{
2510 				for(int i = 0; i < count; i++)
2511 				{
2512 					unsigned int samplerIndex = targetUniform->vsRegisterIndex + i;
2513 
2514 					if(samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS)
2515 					{
2516 						ASSERT(samplersVS[samplerIndex].active);
2517 						samplersVS[samplerIndex].logicalTextureUnit = v[i];
2518 					}
2519 				}
2520 			}
2521 		}
2522 		else
2523 		{
2524 			return applyUniform(device, location, (float*)vector);
2525 		}
2526 
2527 		return true;
2528 	}
2529 
applyUniform2uiv(Device * device,GLint location,GLsizei count,const GLuint * v)2530 	bool Program::applyUniform2uiv(Device *device, GLint location, GLsizei count, const GLuint *v)
2531 	{
2532 		GLuint vector[MAX_UNIFORM_VECTORS][4];
2533 
2534 		for(int i = 0; i < count; i++)
2535 		{
2536 			vector[i][0] = v[0];
2537 			vector[i][1] = v[1];
2538 			vector[i][2] = 0;
2539 			vector[i][3] = 0;
2540 
2541 			v += 2;
2542 		}
2543 
2544 		return applyUniform(device, location, (float*)vector);
2545 	}
2546 
applyUniform3uiv(Device * device,GLint location,GLsizei count,const GLuint * v)2547 	bool Program::applyUniform3uiv(Device *device, GLint location, GLsizei count, const GLuint *v)
2548 	{
2549 		GLuint vector[MAX_UNIFORM_VECTORS][4];
2550 
2551 		for(int i = 0; i < count; i++)
2552 		{
2553 			vector[i][0] = v[0];
2554 			vector[i][1] = v[1];
2555 			vector[i][2] = v[2];
2556 			vector[i][3] = 0;
2557 
2558 			v += 3;
2559 		}
2560 
2561 		return applyUniform(device, location, (float*)vector);
2562 	}
2563 
applyUniform4uiv(Device * device,GLint location,GLsizei count,const GLuint * v)2564 	bool Program::applyUniform4uiv(Device *device, GLint location, GLsizei count, const GLuint *v)
2565 	{
2566 		GLuint vector[MAX_UNIFORM_VECTORS][4];
2567 
2568 		for(int i = 0; i < count; i++)
2569 		{
2570 			vector[i][0] = v[0];
2571 			vector[i][1] = v[1];
2572 			vector[i][2] = v[2];
2573 			vector[i][3] = v[3];
2574 
2575 			v += 4;
2576 		}
2577 
2578 		return applyUniform(device, location, (float*)vector);
2579 	}
2580 
appendToInfoLog(const char * format,...)2581 	void Program::appendToInfoLog(const char *format, ...)
2582 	{
2583 		if(!format)
2584 		{
2585 			return;
2586 		}
2587 
2588 		char info[1024];
2589 
2590 		va_list vararg;
2591 		va_start(vararg, format);
2592 		vsnprintf(info, sizeof(info), format, vararg);
2593 		va_end(vararg);
2594 
2595 		size_t infoLength = strlen(info);
2596 
2597 		if(!infoLog)
2598 		{
2599 			infoLog = new char[infoLength + 2];
2600 			strcpy(infoLog, info);
2601 			strcpy(infoLog + infoLength, "\n");
2602 		}
2603 		else
2604 		{
2605 			size_t logLength = strlen(infoLog);
2606 			char *newLog = new char[logLength + infoLength + 2];
2607 			strcpy(newLog, infoLog);
2608 			strcpy(newLog + logLength, info);
2609 			strcpy(newLog + logLength + infoLength, "\n");
2610 
2611 			delete[] infoLog;
2612 			infoLog = newLog;
2613 		}
2614 	}
2615 
resetInfoLog()2616 	void Program::resetInfoLog()
2617 	{
2618 		if(infoLog)
2619 		{
2620 			delete[] infoLog;
2621 			infoLog = 0;
2622 		}
2623 	}
2624 
2625 	// Returns the program object to an unlinked state, before re-linking, or at destruction
unlink()2626 	void Program::unlink()
2627 	{
2628 		delete vertexBinary;
2629 		vertexBinary = 0;
2630 		delete pixelBinary;
2631 		pixelBinary = 0;
2632 
2633 		linkedAttribute.clear();
2634 		linkedAttributeLocation.clear();
2635 
2636 		for(int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
2637 		{
2638 			attributeStream[index] = -1;
2639 		}
2640 
2641 		for(int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
2642 		{
2643 			samplersPS[index].active = false;
2644 		}
2645 
2646 		for(int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++)
2647 		{
2648 			samplersVS[index].active = false;
2649 		}
2650 
2651 		while(!uniforms.empty())
2652 		{
2653 			delete uniforms.back();
2654 			uniforms.pop_back();
2655 		}
2656 
2657 		while(!uniformBlocks.empty())
2658 		{
2659 			delete uniformBlocks.back();
2660 			uniformBlocks.pop_back();
2661 		}
2662 
2663 		uniformIndex.clear();
2664 		transformFeedbackLinkedVaryings.clear();
2665 
2666 		delete[] infoLog;
2667 		infoLog = 0;
2668 
2669 		linked = false;
2670 	}
2671 
isLinked() const2672 	bool Program::isLinked() const
2673 	{
2674 		return linked;
2675 	}
2676 
isValidated() const2677 	bool Program::isValidated() const
2678 	{
2679 		return validated;
2680 	}
2681 
getBinaryLength() const2682 	GLint Program::getBinaryLength() const
2683 	{
2684 		UNIMPLEMENTED();
2685 		return 0;
2686 	}
2687 
release()2688 	void Program::release()
2689 	{
2690 		referenceCount--;
2691 
2692 		if(referenceCount == 0 && orphaned)
2693 		{
2694 			resourceManager->deleteProgram(handle);
2695 		}
2696 	}
2697 
addRef()2698 	void Program::addRef()
2699 	{
2700 		referenceCount++;
2701 	}
2702 
getRefCount() const2703 	unsigned int Program::getRefCount() const
2704 	{
2705 		return referenceCount;
2706 	}
2707 
getSerial() const2708 	unsigned int Program::getSerial() const
2709 	{
2710 		return serial;
2711 	}
2712 
issueSerial()2713 	unsigned int Program::issueSerial()
2714 	{
2715 		return currentSerial++;
2716 	}
2717 
getInfoLogLength() const2718 	size_t Program::getInfoLogLength() const
2719 	{
2720 		if(!infoLog)
2721 		{
2722 			return 0;
2723 		}
2724 		else
2725 		{
2726 		   return strlen(infoLog) + 1;
2727 		}
2728 	}
2729 
getInfoLog(GLsizei bufSize,GLsizei * length,char * buffer)2730 	void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *buffer)
2731 	{
2732 		int index = 0;
2733 
2734 		if(bufSize > 0)
2735 		{
2736 			if(infoLog)
2737 			{
2738 				index = std::min(bufSize - 1, (int)strlen(infoLog));
2739 				memcpy(buffer, infoLog, index);
2740 			}
2741 
2742 			buffer[index] = '\0';
2743 		}
2744 
2745 		if(length)
2746 		{
2747 			*length = index;
2748 		}
2749 	}
2750 
getAttachedShaders(GLsizei maxCount,GLsizei * count,GLuint * shaders)2751 	void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
2752 	{
2753 		int total = 0;
2754 
2755 		if(vertexShader && (total < maxCount))
2756 		{
2757 			shaders[total++] = vertexShader->getName();
2758 		}
2759 
2760 		if(fragmentShader && (total < maxCount))
2761 		{
2762 			shaders[total++] = fragmentShader->getName();
2763 		}
2764 
2765 		if(count)
2766 		{
2767 			*count = total;
2768 		}
2769 	}
2770 
getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2771 	void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
2772 	{
2773 		ASSERT(index < linkedAttribute.size());
2774 
2775 		std::vector<glsl::Attribute>::const_iterator it = linkedAttribute.begin() + index;
2776 
2777 		if(bufsize > 0)
2778 		{
2779 			const char *string = it->name.c_str();
2780 
2781 			strncpy(name, string, bufsize);
2782 			name[bufsize - 1] = '\0';
2783 
2784 			if(length)
2785 			{
2786 				*length = static_cast<GLsizei>(strlen(name));
2787 			}
2788 		}
2789 
2790 		*size = 1;   // Always a single 'type' instance
2791 
2792 		*type = it->type;
2793 	}
2794 
getActiveAttributeCount() const2795 	size_t Program::getActiveAttributeCount() const
2796 	{
2797 		return linkedAttribute.size();
2798 	}
2799 
getActiveAttributeMaxLength() const2800 	GLint Program::getActiveAttributeMaxLength() const
2801 	{
2802 		int maxLength = 0;
2803 
2804 		std::vector<glsl::Attribute>::const_iterator it = linkedAttribute.begin();
2805 		std::vector<glsl::Attribute>::const_iterator itEnd = linkedAttribute.end();
2806 		for(; it != itEnd; ++it)
2807 		{
2808 			maxLength = std::max((int)(it->name.length() + 1), maxLength);
2809 		}
2810 
2811 		return maxLength;
2812 	}
2813 
getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2814 	void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
2815 	{
2816 		if(bufsize > 0)
2817 		{
2818 			std::string string = uniforms[index]->name;
2819 
2820 			if(uniforms[index]->isArray())
2821 			{
2822 				string += "[0]";
2823 			}
2824 
2825 			strncpy(name, string.c_str(), bufsize);
2826 			name[bufsize - 1] = '\0';
2827 
2828 			if(length)
2829 			{
2830 				*length = static_cast<GLsizei>(strlen(name));
2831 			}
2832 		}
2833 
2834 		*size = uniforms[index]->size();
2835 
2836 		*type = uniforms[index]->type;
2837 	}
2838 
getActiveUniformCount() const2839 	size_t Program::getActiveUniformCount() const
2840 	{
2841 		return uniforms.size();
2842 	}
2843 
getActiveUniformMaxLength() const2844 	GLint Program::getActiveUniformMaxLength() const
2845 	{
2846 		int maxLength = 0;
2847 
2848 		size_t numUniforms = uniforms.size();
2849 		for(size_t uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
2850 		{
2851 			if(!uniforms[uniformIndex]->name.empty())
2852 			{
2853 				int length = (int)(uniforms[uniformIndex]->name.length() + 1);
2854 				if(uniforms[uniformIndex]->isArray())
2855 				{
2856 					length += 3;  // Counting in "[0]".
2857 				}
2858 				maxLength = std::max(length, maxLength);
2859 			}
2860 		}
2861 
2862 		return maxLength;
2863 	}
2864 
getActiveUniformi(GLuint index,GLenum pname) const2865 	GLint Program::getActiveUniformi(GLuint index, GLenum pname) const
2866 	{
2867 		const Uniform& uniform = *uniforms[index];
2868 		switch(pname)
2869 		{
2870 		case GL_UNIFORM_TYPE:         return static_cast<GLint>(uniform.type);
2871 		case GL_UNIFORM_SIZE:         return static_cast<GLint>(uniform.size());
2872 		case GL_UNIFORM_NAME_LENGTH:  return static_cast<GLint>(uniform.name.size() + 1 + (uniform.isArray() ? 3 : 0));
2873 		case GL_UNIFORM_BLOCK_INDEX:  return uniform.blockInfo.index;
2874 		case GL_UNIFORM_OFFSET:       return uniform.blockInfo.offset;
2875 		case GL_UNIFORM_ARRAY_STRIDE: return uniform.blockInfo.arrayStride;
2876 		case GL_UNIFORM_MATRIX_STRIDE: return uniform.blockInfo.matrixStride;
2877 		case GL_UNIFORM_IS_ROW_MAJOR: return static_cast<GLint>(uniform.blockInfo.isRowMajorMatrix);
2878 		default:
2879 			UNREACHABLE(pname);
2880 			break;
2881 		}
2882 		return 0;
2883 	}
2884 
getActiveUniformBlockName(GLuint index,GLsizei bufSize,GLsizei * length,GLchar * name) const2885 	void Program::getActiveUniformBlockName(GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name) const
2886 	{
2887 		ASSERT(index < getActiveUniformBlockCount());
2888 
2889 		const UniformBlock &uniformBlock = *uniformBlocks[index];
2890 
2891 		if(bufSize > 0)
2892 		{
2893 			std::string string = uniformBlock.name;
2894 
2895 			if(uniformBlock.isArrayElement())
2896 			{
2897 				std::ostringstream elementIndex;
2898 				elementIndex << uniformBlock.elementIndex;
2899 				string += "[" + elementIndex.str()  + "]";
2900 			}
2901 
2902 			strncpy(name, string.c_str(), bufSize);
2903 			name[bufSize - 1] = '\0';
2904 
2905 			if(length)
2906 			{
2907 				*length = static_cast<GLsizei>(strlen(name));
2908 			}
2909 		}
2910 	}
2911 
getActiveUniformBlockCount() const2912 	size_t Program::getActiveUniformBlockCount() const
2913 	{
2914 		return uniformBlocks.size();
2915 	}
2916 
getActiveUniformBlockMaxLength() const2917 	GLint Program::getActiveUniformBlockMaxLength() const
2918 	{
2919 		GLint maxLength = 0;
2920 
2921 		if(isLinked())
2922 		{
2923 			size_t numUniformBlocks = getActiveUniformBlockCount();
2924 			for(size_t uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
2925 			{
2926 				const UniformBlock &uniformBlock = *uniformBlocks[uniformBlockIndex];
2927 				if(!uniformBlock.name.empty())
2928 				{
2929 					GLint length = static_cast<GLint>(uniformBlock.name.length() + 1);
2930 
2931 					// Counting in "[0]".
2932 					const GLint arrayLength = (uniformBlock.isArrayElement() ? 3 : 0);
2933 
2934 					maxLength = std::max(length + arrayLength, maxLength);
2935 				}
2936 			}
2937 		}
2938 
2939 		return maxLength;
2940 	}
2941 
setTransformFeedbackVaryings(GLsizei count,const GLchar * const * varyings,GLenum bufferMode)2942 	void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode)
2943 	{
2944 		transformFeedbackVaryings.resize(count);
2945 		for(GLsizei i = 0; i < count; i++)
2946 		{
2947 			transformFeedbackVaryings[i] = varyings[i];
2948 		}
2949 
2950 		transformFeedbackBufferMode = bufferMode;
2951 	}
2952 
getTransformFeedbackVarying(GLuint index,GLsizei bufSize,GLsizei * length,GLsizei * size,GLenum * type,GLchar * name) const2953 	void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const
2954 	{
2955 		if(linked)
2956 		{
2957 			ASSERT(index < transformFeedbackLinkedVaryings.size());
2958 			const LinkedVarying &varying = transformFeedbackLinkedVaryings[index];
2959 			GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varying.name.length()));
2960 			if(length)
2961 			{
2962 				*length = lastNameIdx;
2963 			}
2964 			if(size)
2965 			{
2966 				*size = varying.size;
2967 			}
2968 			if(type)
2969 			{
2970 				*type = varying.type;
2971 			}
2972 			if(name)
2973 			{
2974 				memcpy(name, varying.name.c_str(), lastNameIdx);
2975 				name[lastNameIdx] = '\0';
2976 			}
2977 		}
2978 	}
2979 
getTransformFeedbackVaryingCount() const2980 	GLsizei Program::getTransformFeedbackVaryingCount() const
2981 	{
2982 		if(linked)
2983 		{
2984 			return static_cast<GLsizei>(transformFeedbackLinkedVaryings.size());
2985 		}
2986 		else
2987 		{
2988 			return 0;
2989 		}
2990 	}
2991 
getTransformFeedbackVaryingMaxLength() const2992 	GLsizei Program::getTransformFeedbackVaryingMaxLength() const
2993 	{
2994 		if(linked)
2995 		{
2996 			GLsizei maxSize = 0;
2997 			for(size_t i = 0; i < transformFeedbackLinkedVaryings.size(); i++)
2998 			{
2999 				const LinkedVarying &varying = transformFeedbackLinkedVaryings[i];
3000 				maxSize = std::max(maxSize, static_cast<GLsizei>(varying.name.length() + 1));
3001 			}
3002 
3003 			return maxSize;
3004 		}
3005 		else
3006 		{
3007 			return 0;
3008 		}
3009 	}
3010 
getTransformFeedbackBufferMode() const3011 	GLenum Program::getTransformFeedbackBufferMode() const
3012 	{
3013 		return transformFeedbackBufferMode;
3014 	}
3015 
flagForDeletion()3016 	void Program::flagForDeletion()
3017 	{
3018 		orphaned = true;
3019 	}
3020 
isFlaggedForDeletion() const3021 	bool Program::isFlaggedForDeletion() const
3022 	{
3023 		return orphaned;
3024 	}
3025 
validate(Device * device)3026 	void Program::validate(Device* device)
3027 	{
3028 		resetInfoLog();
3029 
3030 		if(!isLinked())
3031 		{
3032 			appendToInfoLog("Program has not been successfully linked.");
3033 			validated = false;
3034 		}
3035 		else
3036 		{
3037 			applyUniforms(device);
3038 			if(!validateSamplers(true))
3039 			{
3040 				validated = false;
3041 			}
3042 			else
3043 			{
3044 				validated = true;
3045 			}
3046 		}
3047 	}
3048 
validateSamplers(bool logErrors)3049 	bool Program::validateSamplers(bool logErrors)
3050 	{
3051 		// if any two active samplers in a program are of different types, but refer to the same
3052 		// texture image unit, and this is the current program, then ValidateProgram will fail, and
3053 		// DrawArrays and DrawElements will issue the INVALID_OPERATION error.
3054 
3055 		TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
3056 
3057 		for(unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS; i++)
3058 		{
3059 			textureUnitType[i] = TEXTURE_UNKNOWN;
3060 		}
3061 
3062 		for(unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
3063 		{
3064 			if(samplersPS[i].active)
3065 			{
3066 				unsigned int unit = samplersPS[i].logicalTextureUnit;
3067 
3068 				if(unit >= MAX_COMBINED_TEXTURE_IMAGE_UNITS)
3069 				{
3070 					if(logErrors)
3071 					{
3072 						appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, MAX_COMBINED_TEXTURE_IMAGE_UNITS);
3073 					}
3074 
3075 					return false;
3076 				}
3077 
3078 				if(textureUnitType[unit] != TEXTURE_UNKNOWN)
3079 				{
3080 					if(samplersPS[i].textureType != textureUnitType[unit])
3081 					{
3082 						if(logErrors)
3083 						{
3084 							appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
3085 						}
3086 
3087 						return false;
3088 					}
3089 				}
3090 				else
3091 				{
3092 					textureUnitType[unit] = samplersPS[i].textureType;
3093 				}
3094 			}
3095 		}
3096 
3097 		for(unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)
3098 		{
3099 			if(samplersVS[i].active)
3100 			{
3101 				unsigned int unit = samplersVS[i].logicalTextureUnit;
3102 
3103 				if(unit >= MAX_COMBINED_TEXTURE_IMAGE_UNITS)
3104 				{
3105 					if(logErrors)
3106 					{
3107 						appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, MAX_COMBINED_TEXTURE_IMAGE_UNITS);
3108 					}
3109 
3110 					return false;
3111 				}
3112 
3113 				if(textureUnitType[unit] != TEXTURE_UNKNOWN)
3114 				{
3115 					if(samplersVS[i].textureType != textureUnitType[unit])
3116 					{
3117 						if(logErrors)
3118 						{
3119 							appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
3120 						}
3121 
3122 						return false;
3123 					}
3124 				}
3125 				else
3126 				{
3127 					textureUnitType[unit] = samplersVS[i].textureType;
3128 				}
3129 			}
3130 		}
3131 
3132 		return true;
3133 	}
3134 }
3135