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