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