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