blob: 06190237135354cb45eed85fbc7e2d5d66998449 [file] [log] [blame]
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001//
Geoff Lang48dcae72014-02-05 16:28:24 -05002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Program.cpp: Implements the gl::Program class. Implements GL program objects
8// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
9
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +000010#include "libGLESv2/BinaryStream.h"
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000011#include "libGLESv2/ProgramBinary.h"
Geoff Lang04fb89a2014-06-09 15:05:36 -040012#include "libGLESv2/Framebuffer.h"
Jamie Madillaef95de2014-09-05 10:12:41 -040013#include "libGLESv2/FramebufferAttachment.h"
Geoff Lang04fb89a2014-06-09 15:05:36 -040014#include "libGLESv2/Renderbuffer.h"
shannon.woods@transgaming.comd2811d62013-02-28 23:11:19 +000015#include "libGLESv2/renderer/ShaderExecutable.h"
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000016
17#include "common/debug.h"
apatrick@chromium.org90080e32012-07-09 22:15:33 +000018#include "common/version.h"
shannonwoods@chromium.orga2ecfcc2013-05-30 00:11:59 +000019#include "common/utilities.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040020#include "common/platform.h"
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000021
22#include "libGLESv2/main.h"
23#include "libGLESv2/Shader.h"
shannon.woods@transgaming.comd2811d62013-02-28 23:11:19 +000024#include "libGLESv2/Program.h"
Brandon Jonesc9610c52014-08-25 17:02:59 -070025#include "libGLESv2/renderer/ProgramImpl.h"
Brandon Jonesf05cdee2014-08-27 15:24:07 -070026#include "libGLESv2/renderer/d3d/ShaderD3D.h"
Nicolas Capense6050882013-07-08 10:43:10 -040027#include "libGLESv2/Context.h"
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +000028#include "libGLESv2/Buffer.h"
Jamie Madillc600c8c2014-05-16 11:22:21 -040029#include "common/blocklayout.h"
Brandon Jones091540d2014-10-29 11:32:04 -070030#include "common/features.h"
Jamie Madillc2141fb2013-08-30 13:21:08 -040031
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000032namespace gl
33{
shannonwoods@chromium.orgb4e07b82013-05-30 00:19:31 +000034
Jamie Madill1b2a8f92014-05-14 13:09:39 -040035namespace
shannonwoods@chromium.org6d7b61c2013-05-30 00:06:38 +000036{
37
Jamie Madill8ff21ae2014-02-04 16:04:05 -050038unsigned int ParseAndStripArrayIndex(std::string* name)
shannonwoods@chromium.org6d7b61c2013-05-30 00:06:38 +000039{
40 unsigned int subscript = GL_INVALID_INDEX;
41
42 // Strip any trailing array operator and retrieve the subscript
43 size_t open = name->find_last_of('[');
44 size_t close = name->find_last_of(']');
45 if (open != std::string::npos && close == name->length() - 1)
46 {
47 subscript = atoi(name->substr(open + 1).c_str());
48 name->erase(open);
49 }
50
51 return subscript;
52}
53
54}
55
Jamie Madill1b2a8f92014-05-14 13:09:39 -040056VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index)
daniel@transgaming.comdb019952012-12-20 21:13:32 +000057 : name(name), element(element), index(index)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000058{
59}
60
Geoff Lang48dcae72014-02-05 16:28:24 -050061LinkedVarying::LinkedVarying()
62{
63}
64
65LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName,
66 unsigned int semanticIndex, unsigned int semanticIndexCount)
67 : name(name), type(type), size(size), semanticName(semanticName), semanticIndex(semanticIndex), semanticIndexCount(semanticIndexCount)
68{
69}
70
Geoff Langb543aff2014-09-30 14:52:54 -040071LinkResult::LinkResult(bool linkSuccess, const Error &error)
72 : linkSuccess(linkSuccess),
73 error(error)
74{
75}
76
daniel@transgaming.come87ca002012-07-24 18:30:43 +000077unsigned int ProgramBinary::mCurrentSerial = 1;
78
Brandon Jonesc9610c52014-08-25 17:02:59 -070079ProgramBinary::ProgramBinary(rx::ProgramImpl *impl)
Jamie Madill8ff21ae2014-02-04 16:04:05 -050080 : RefCountObject(0),
Brandon Jonesc9610c52014-08-25 17:02:59 -070081 mProgram(impl),
Jamie Madill8ff21ae2014-02-04 16:04:05 -050082 mValidated(false),
83 mSerial(issueSerial())
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000084{
Brandon Jonesc9610c52014-08-25 17:02:59 -070085 ASSERT(impl);
86
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000087 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
88 {
89 mSemanticIndex[index] = -1;
90 }
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000091}
92
93ProgramBinary::~ProgramBinary()
94{
Geoff Lang04fb89a2014-06-09 15:05:36 -040095 reset();
Brandon Jonesc9610c52014-08-25 17:02:59 -070096 SafeDelete(mProgram);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000097}
98
daniel@transgaming.come87ca002012-07-24 18:30:43 +000099unsigned int ProgramBinary::getSerial() const
100{
101 return mSerial;
102}
103
104unsigned int ProgramBinary::issueSerial()
105{
106 return mCurrentSerial++;
107}
108
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000109GLuint ProgramBinary::getAttributeLocation(const char *name)
110{
111 if (name)
112 {
113 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
114 {
115 if (mLinkedAttribute[index].name == std::string(name))
116 {
117 return index;
118 }
119 }
120 }
121
122 return -1;
123}
124
125int ProgramBinary::getSemanticIndex(int attributeIndex)
126{
127 ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
Jamie Madill1b2a8f92014-05-14 13:09:39 -0400128
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000129 return mSemanticIndex[attributeIndex];
130}
131
132// Returns one more than the highest sampler index used.
133GLint ProgramBinary::getUsedSamplerRange(SamplerType type)
134{
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700135 return mProgram->getUsedSamplerRange(type);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000136}
137
daniel@transgaming.com087e5782012-09-17 21:28:47 +0000138bool ProgramBinary::usesPointSize() const
139{
Brandon Jones44151a92014-09-10 11:32:25 -0700140 return mProgram->usesPointSize();
shannon.woods@transgaming.com3e773bb2013-01-25 21:55:47 +0000141}
142
Brandon Jones43a53e22014-08-28 16:23:22 -0700143GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000144{
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700145 return mProgram->getSamplerMapping(type, samplerIndex, caps);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000146}
147
Geoff Lang76b10c92014-09-05 16:28:14 -0400148GLenum ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000149{
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700150 return mProgram->getSamplerTextureType(type, samplerIndex);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000151}
152
153GLint ProgramBinary::getUniformLocation(std::string name)
154{
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700155 return mProgram->getUniformLocation(name);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000156}
157
shannonwoods@chromium.orgc2ed9912013-05-30 00:05:33 +0000158GLuint ProgramBinary::getUniformIndex(std::string name)
159{
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700160 return mProgram->getUniformIndex(name);
shannonwoods@chromium.orgc2ed9912013-05-30 00:05:33 +0000161}
162
shannonwoods@chromium.org42766252013-05-30 00:07:12 +0000163GLuint ProgramBinary::getUniformBlockIndex(std::string name)
164{
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700165 return mProgram->getUniformBlockIndex(name);
shannonwoods@chromium.org42766252013-05-30 00:07:12 +0000166}
167
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +0000168UniformBlock *ProgramBinary::getUniformBlockByIndex(GLuint blockIndex)
169{
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700170 return mProgram->getUniformBlockByIndex(blockIndex);
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +0000171}
172
Jamie Madilld1e78c92013-06-20 11:55:50 -0400173GLint ProgramBinary::getFragDataLocation(const char *name) const
174{
175 std::string baseName(name);
176 unsigned int arrayIndex;
Jamie Madill8ff21ae2014-02-04 16:04:05 -0500177 arrayIndex = ParseAndStripArrayIndex(&baseName);
Jamie Madilld1e78c92013-06-20 11:55:50 -0400178
179 for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++)
180 {
181 const VariableLocation &outputVariable = locationIt->second;
182
183 if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element))
184 {
185 return static_cast<GLint>(locationIt->first);
186 }
187 }
188
189 return -1;
190}
191
Geoff Lang48dcae72014-02-05 16:28:24 -0500192size_t ProgramBinary::getTransformFeedbackVaryingCount() const
193{
Brandon Joneseb994362014-09-24 10:27:28 -0700194 return mProgram->getTransformFeedbackLinkedVaryings().size();
Geoff Lang48dcae72014-02-05 16:28:24 -0500195}
196
197const LinkedVarying &ProgramBinary::getTransformFeedbackVarying(size_t idx) const
198{
Brandon Joneseb994362014-09-24 10:27:28 -0700199 return mProgram->getTransformFeedbackLinkedVaryings()[idx];
Geoff Lang48dcae72014-02-05 16:28:24 -0500200}
201
202GLenum ProgramBinary::getTransformFeedbackBufferMode() const
203{
Brandon Joneseb994362014-09-24 10:27:28 -0700204 return mProgram->getTransformFeedbackBufferMode();
Geoff Lang48dcae72014-02-05 16:28:24 -0500205}
206
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700207void ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat *v) {
208 mProgram->setUniform1fv(location, count, v);
Geoff Langae1990c2014-05-12 16:57:14 -0400209}
210
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700211void ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) {
212 mProgram->setUniform2fv(location, count, v);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000213}
214
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700215void ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) {
216 mProgram->setUniform3fv(location, count, v);
shannon.woods%transgaming.com@gtempaccount.com8a19eed2013-04-13 03:40:22 +0000217}
218
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700219void ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) {
220 mProgram->setUniform4fv(location, count, v);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000221}
222
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700223void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) {
224 mProgram->setUniform1iv(location, count, v);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000225}
226
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700227void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) {
228 mProgram->setUniform2iv(location, count, v);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000229}
230
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700231void ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v) {
232 mProgram->setUniform3iv(location, count, v);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000233}
234
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700235void ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v) {
236 mProgram->setUniform4iv(location, count, v);
shannon.woods%transgaming.com@gtempaccount.coma741b642013-04-13 03:40:10 +0000237}
238
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700239void ProgramBinary::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) {
240 mProgram->setUniform1uiv(location, count, v);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000241}
242
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700243void ProgramBinary::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) {
244 mProgram->setUniform2uiv(location, count, v);
shannon.woods%transgaming.com@gtempaccount.com36c76a92013-04-13 03:39:58 +0000245}
246
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700247void ProgramBinary::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) {
248 mProgram->setUniform3uiv(location, count, v);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000249}
250
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700251void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) {
252 mProgram->setUniform4uiv(location, count, v);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000253}
254
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700255void ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
256 mProgram->setUniformMatrix2fv(location, count, transpose, v);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000257}
258
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700259void ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
260 mProgram->setUniformMatrix3fv(location, count, transpose, v);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000261}
262
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700263void ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
264 mProgram->setUniformMatrix4fv(location, count, transpose, v);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000265}
266
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700267void ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
268 mProgram->setUniformMatrix2x3fv(location, count, transpose, v);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000269}
270
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700271void ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
272 mProgram->setUniformMatrix2x4fv(location, count, transpose, v);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000273}
274
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700275void ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
276 mProgram->setUniformMatrix3x2fv(location, count, transpose, v);
shannon.woods%transgaming.com@gtempaccount.comf1306162013-04-13 03:40:04 +0000277}
278
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700279void ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
280 mProgram->setUniformMatrix3x4fv(location, count, transpose, v);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000281}
282
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700283void ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
284 mProgram->setUniformMatrix4x2fv(location, count, transpose, v);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000285}
286
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700287void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
288 mProgram->setUniformMatrix4x3fv(location, count, transpose, v);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000289}
290
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700291void ProgramBinary::getUniformfv(GLint location, GLfloat *v) {
292 mProgram->getUniformfv(location, v);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000293}
294
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700295void ProgramBinary::getUniformiv(GLint location, GLint *v) {
296 mProgram->getUniformiv(location, v);
shannon.woods%transgaming.com@gtempaccount.com50ea4ab2013-04-13 03:40:36 +0000297}
298
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700299void ProgramBinary::getUniformuiv(GLint location, GLuint *v) {
300 mProgram->getUniformuiv(location, v);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000301}
302
Jamie Madilld4cfa572014-07-08 10:00:32 -0400303void ProgramBinary::updateSamplerMapping()
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000304{
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700305 return mProgram->updateSamplerMapping();
Jamie Madilld4cfa572014-07-08 10:00:32 -0400306}
307
308// Applies all the uniforms set for this program object to the renderer
Geoff Langc77e8c32014-09-08 16:28:24 -0400309Error ProgramBinary::applyUniforms()
Jamie Madilld4cfa572014-07-08 10:00:32 -0400310{
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700311 return mProgram->applyUniforms();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000312}
313
Geoff Langc77e8c32014-09-08 16:28:24 -0400314Error ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const Caps &caps)
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +0000315{
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700316 return mProgram->applyUniformBuffers(boundBuffers, caps);
shannonwoods@chromium.org1bddfb92013-05-30 00:11:29 +0000317}
318
Brandon Jones71620962014-08-20 14:04:59 -0700319bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000320{
Jamie Madilld15250e2014-09-03 09:40:44 -0400321 std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getVaryings();
322 std::vector<PackedVarying> &vertexVaryings = vertexShader->getVaryings();
Jamie Madill5f562732014-02-14 16:41:24 -0500323
324 for (size_t fragVaryingIndex = 0; fragVaryingIndex < fragmentVaryings.size(); fragVaryingIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000325 {
Jamie Madillff0d2ba2014-05-14 13:49:10 -0400326 PackedVarying *input = &fragmentVaryings[fragVaryingIndex];
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000327 bool matched = false;
328
Jamie Madill54ad4f82014-09-03 09:40:46 -0400329 // Built-in varyings obey special rules
330 if (input->isBuiltIn())
331 {
332 continue;
333 }
334
Jamie Madill5f562732014-02-14 16:41:24 -0500335 for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000336 {
Jamie Madillff0d2ba2014-05-14 13:49:10 -0400337 PackedVarying *output = &vertexVaryings[vertVaryingIndex];
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000338 if (output->name == input->name)
339 {
Jamie Madill42bcf322014-08-25 16:20:46 -0400340 if (!linkValidateVaryings(infoLog, output->name, *input, *output))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000341 {
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000342 return false;
343 }
344
Jamie Madill139b9092013-08-30 13:21:06 -0400345 output->registerIndex = input->registerIndex;
Austin Kinrossaf875522014-08-25 21:06:07 -0700346 output->columnIndex = input->columnIndex;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000347
348 matched = true;
349 break;
350 }
351 }
352
Jamie Madill54ad4f82014-09-03 09:40:46 -0400353 // We permit unmatched, unreferenced varyings
354 if (!matched && input->staticUse)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000355 {
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000356 infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str());
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000357 return false;
358 }
359 }
360
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000361 return true;
362}
363
Geoff Langb543aff2014-09-30 14:52:54 -0400364LinkResult ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length)
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000365{
Geoff Lang560eef12014-11-11 15:06:39 -0500366#if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_DISABLED
Geoff Langb543aff2014-09-30 14:52:54 -0400367 return LinkResult(false, Error(GL_NO_ERROR));
Jamie Madill9c4b24a2014-06-12 13:41:17 -0400368#else
Brandon Jones22502d52014-08-29 16:58:36 -0700369 ASSERT(binaryFormat == mProgram->getBinaryFormat());
Geoff Lang900013c2014-07-07 11:32:19 -0400370
Geoff Lang04fb89a2014-06-09 15:05:36 -0400371 reset();
372
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +0000373 BinaryInputStream stream(binary, length);
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000374
Brandon Jones22502d52014-08-29 16:58:36 -0700375 GLenum format = stream.readInt<GLenum>();
376 if (format != mProgram->getBinaryFormat())
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000377 {
378 infoLog.append("Invalid program binary format.");
Geoff Langb543aff2014-09-30 14:52:54 -0400379 return LinkResult(false, Error(GL_NO_ERROR));
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000380 }
381
Jamie Madill1b2a8f92014-05-14 13:09:39 -0400382 int majorVersion = stream.readInt<int>();
383 int minorVersion = stream.readInt<int>();
Jamie Madill0aa84f62014-02-13 13:17:23 -0500384 if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION)
Jamie Madill049108d2013-11-19 10:41:49 -0500385 {
386 infoLog.append("Invalid program binary version.");
Geoff Langb543aff2014-09-30 14:52:54 -0400387 return LinkResult(false, Error(GL_NO_ERROR));
Jamie Madill049108d2013-11-19 10:41:49 -0500388 }
389
Jamie Madill0aa84f62014-02-13 13:17:23 -0500390 unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
Jamie Madill1b2a8f92014-05-14 13:09:39 -0400391 stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE);
Jamie Madill0aa84f62014-02-13 13:17:23 -0500392 if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0)
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000393 {
394 infoLog.append("Invalid program binary version.");
Geoff Langb543aff2014-09-30 14:52:54 -0400395 return LinkResult(false, Error(GL_NO_ERROR));
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000396 }
397
Jamie Madill1b2a8f92014-05-14 13:09:39 -0400398 int compileFlags = stream.readInt<int>();
shannonwoods@chromium.orgf97a0842013-05-30 00:10:33 +0000399 if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
400 {
401 infoLog.append("Mismatched compilation flags.");
Geoff Langb543aff2014-09-30 14:52:54 -0400402 return LinkResult(false, Error(GL_NO_ERROR));
shannonwoods@chromium.orgf97a0842013-05-30 00:10:33 +0000403 }
404
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000405 for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
406 {
Jamie Madill1b2a8f92014-05-14 13:09:39 -0400407 stream.readInt(&mLinkedAttribute[i].type);
408 stream.readString(&mLinkedAttribute[i].name);
Brandon Joneseb994362014-09-24 10:27:28 -0700409 stream.readInt(&mProgram->getShaderAttributes()[i].type);
410 stream.readString(&mProgram->getShaderAttributes()[i].name);
Jamie Madill1b2a8f92014-05-14 13:09:39 -0400411 stream.readInt(&mSemanticIndex[i]);
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000412 }
413
Al Patrick3f2daa82013-08-07 12:58:57 -0700414 initAttributesByLayout();
415
Geoff Langb543aff2014-09-30 14:52:54 -0400416 LinkResult result = mProgram->load(infoLog, &stream);
417 if (result.error.isError() || !result.linkSuccess)
Brandon Jones22502d52014-08-29 16:58:36 -0700418 {
Geoff Langb543aff2014-09-30 14:52:54 -0400419 return result;
Brandon Jones22502d52014-08-29 16:58:36 -0700420 }
421
Geoff Langb543aff2014-09-30 14:52:54 -0400422 return LinkResult(true, Error(GL_NO_ERROR));
Brandon Jones091540d2014-10-29 11:32:04 -0700423#endif // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000424}
425
Geoff Langb543aff2014-09-30 14:52:54 -0400426Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length)
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000427{
Geoff Lang900013c2014-07-07 11:32:19 -0400428 if (binaryFormat)
429 {
Brandon Jones22502d52014-08-29 16:58:36 -0700430 *binaryFormat = mProgram->getBinaryFormat();
Geoff Lang900013c2014-07-07 11:32:19 -0400431 }
432
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +0000433 BinaryOutputStream stream;
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000434
Brandon Jones22502d52014-08-29 16:58:36 -0700435 stream.writeInt(mProgram->getBinaryFormat());
Jamie Madill1b2a8f92014-05-14 13:09:39 -0400436 stream.writeInt(ANGLE_MAJOR_VERSION);
437 stream.writeInt(ANGLE_MINOR_VERSION);
Ehsan Akhgariaa7e1662014-07-05 21:13:11 -0400438 stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE);
Jamie Madill1b2a8f92014-05-14 13:09:39 -0400439 stream.writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000440
441 for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
442 {
Jamie Madill1b2a8f92014-05-14 13:09:39 -0400443 stream.writeInt(mLinkedAttribute[i].type);
444 stream.writeString(mLinkedAttribute[i].name);
Brandon Joneseb994362014-09-24 10:27:28 -0700445 stream.writeInt(mProgram->getShaderAttributes()[i].type);
446 stream.writeString(mProgram->getShaderAttributes()[i].name);
Jamie Madill1b2a8f92014-05-14 13:09:39 -0400447 stream.writeInt(mSemanticIndex[i]);
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000448 }
449
Geoff Langb543aff2014-09-30 14:52:54 -0400450 mProgram->save(&stream);
Brandon Jones22502d52014-08-29 16:58:36 -0700451
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +0000452 GLsizei streamLength = stream.length();
453 const void *streamData = stream.data();
454
Brandon Jones18bd4102014-09-22 14:21:44 -0700455 if (streamLength > bufSize)
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000456 {
457 if (length)
458 {
459 *length = 0;
460 }
461
Geoff Langb543aff2014-09-30 14:52:54 -0400462 // TODO: This should be moved to the validation layer but computing the size of the binary before saving
463 // it causes the save to happen twice. It may be possible to write the binary to a separate buffer, validate
464 // sizes and then copy it.
465 return Error(GL_INVALID_OPERATION);
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000466 }
467
468 if (binary)
469 {
470 char *ptr = (char*) binary;
471
apatrick@chromium.org6f1796f2012-07-12 01:40:11 +0000472 memcpy(ptr, streamData, streamLength);
473 ptr += streamLength;
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000474
Brandon Jones18bd4102014-09-22 14:21:44 -0700475 ASSERT(ptr - streamLength == binary);
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000476 }
477
478 if (length)
479 {
Brandon Jones18bd4102014-09-22 14:21:44 -0700480 *length = streamLength;
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000481 }
482
Geoff Langb543aff2014-09-30 14:52:54 -0400483 return Error(GL_NO_ERROR);
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000484}
485
486GLint ProgramBinary::getLength()
487{
488 GLint length;
Geoff Langb543aff2014-09-30 14:52:54 -0400489 Error error = save(NULL, NULL, INT_MAX, &length);
490 if (error.isError())
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000491 {
492 return 0;
493 }
Geoff Langb543aff2014-09-30 14:52:54 -0400494
495 return length;
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000496}
497
Jamie Madillde8892b2014-11-11 13:00:22 -0500498LinkResult ProgramBinary::link(const Data &data, InfoLog &infoLog, const AttributeBindings &attributeBindings,
499 Shader *fragmentShader, Shader *vertexShader,
500 const std::vector<std::string> &transformFeedbackVaryings,
501 GLenum transformFeedbackBufferMode)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000502{
503 if (!fragmentShader || !fragmentShader->isCompiled())
504 {
Geoff Langb543aff2014-09-30 14:52:54 -0400505 return LinkResult(false, Error(GL_NO_ERROR));
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000506 }
Brandon Jones71620962014-08-20 14:04:59 -0700507 ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000508
509 if (!vertexShader || !vertexShader->isCompiled())
510 {
Geoff Langb543aff2014-09-30 14:52:54 -0400511 return LinkResult(false, Error(GL_NO_ERROR));
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000512 }
Brandon Jones71620962014-08-20 14:04:59 -0700513 ASSERT(vertexShader->getType() == GL_VERTEX_SHADER);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000514
Geoff Lang04fb89a2014-06-09 15:05:36 -0400515 reset();
516
Brandon Jones22502d52014-08-29 16:58:36 -0700517 int registers;
518 std::vector<LinkedVarying> linkedVaryings;
Jamie Madillde8892b2014-11-11 13:00:22 -0500519 LinkResult result = mProgram->link(data, infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, transformFeedbackBufferMode,
520 &registers, &linkedVaryings, &mOutputVariables);
Geoff Langb543aff2014-09-30 14:52:54 -0400521 if (result.error.isError() || !result.linkSuccess)
Jamie Madill5f562732014-02-14 16:41:24 -0500522 {
Geoff Langb543aff2014-09-30 14:52:54 -0400523 return result;
Jamie Madill5f562732014-02-14 16:41:24 -0500524 }
525
Jamie Madilld15250e2014-09-03 09:40:44 -0400526 if (!linkAttributes(infoLog, attributeBindings, vertexShader))
daniel@transgaming.comc68fa872012-11-28 20:58:32 +0000527 {
Geoff Langb543aff2014-09-30 14:52:54 -0400528 return LinkResult(false, Error(GL_NO_ERROR));
daniel@transgaming.comc68fa872012-11-28 20:58:32 +0000529 }
530
Jamie Madillde8892b2014-11-11 13:00:22 -0500531 if (!mProgram->linkUniforms(infoLog, *vertexShader, *fragmentShader, *data.caps))
daniel@transgaming.comc68fa872012-11-28 20:58:32 +0000532 {
Geoff Langb543aff2014-09-30 14:52:54 -0400533 return LinkResult(false, Error(GL_NO_ERROR));
daniel@transgaming.comfdc7f562012-12-20 21:12:37 +0000534 }
daniel@transgaming.comc68fa872012-11-28 20:58:32 +0000535
Jamie Madillde8892b2014-11-11 13:00:22 -0500536 if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, *data.caps))
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +0000537 {
Geoff Langb543aff2014-09-30 14:52:54 -0400538 return LinkResult(false, Error(GL_NO_ERROR));
shannonwoods@chromium.org1500f092013-05-30 00:11:20 +0000539 }
540
Geoff Lang48dcae72014-02-05 16:28:24 -0500541 if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings,
Jamie Madillde8892b2014-11-11 13:00:22 -0500542 transformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(), *data.caps))
Geoff Lang48dcae72014-02-05 16:28:24 -0500543 {
Geoff Langb543aff2014-09-30 14:52:54 -0400544 return LinkResult(false, Error(GL_NO_ERROR));
Geoff Lang48dcae72014-02-05 16:28:24 -0500545 }
546
Geoff Langb543aff2014-09-30 14:52:54 -0400547 // TODO: The concept of "executables" is D3D only, and as such this belongs in ProgramD3D. It must be called,
548 // however, last in this function, so it can't simply be moved to ProgramD3D::link without further shuffling.
549 result = mProgram->compileProgramExecutables(infoLog, fragmentShader, vertexShader, registers);
550 if (result.error.isError() || !result.linkSuccess)
Jamie Madilld1ac3c92013-06-25 10:40:30 -0400551 {
Geoff Langb543aff2014-09-30 14:52:54 -0400552 infoLog.append("Failed to create D3D shaders.");
553 reset();
554 return result;
Jamie Madilld1ac3c92013-06-25 10:40:30 -0400555 }
556
Geoff Langb543aff2014-09-30 14:52:54 -0400557 return LinkResult(true, Error(GL_NO_ERROR));
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000558}
559
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700560bool ProgramBinary::linkUniformBlocks(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader,
561 const gl::Caps &caps)
562{
563 const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks();
564 const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks();
565
566 // Check that interface blocks defined in the vertex and fragment shaders are identical
567 typedef std::map<std::string, const sh::InterfaceBlock*> UniformBlockMap;
568 UniformBlockMap linkedUniformBlocks;
569
570 for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
571 {
572 const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex];
573 linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock;
574 }
575
576 for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
577 {
578 const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex];
579 UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name);
580 if (entry != linkedUniformBlocks.end())
581 {
582 const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second;
583 if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock))
584 {
585 return false;
586 }
587 }
588 }
589
590 for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
591 {
592 const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex];
593
594 // Note: shared and std140 layouts are always considered active
595 if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
596 {
597 if (!mProgram->defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps))
598 {
599 return false;
600 }
601 }
602 }
603
604 for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
605 {
606 const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex];
607
608 // Note: shared and std140 layouts are always considered active
609 if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
610 {
611 if (!mProgram->defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps))
612 {
613 return false;
614 }
615 }
616 }
617
618 return true;
619}
620
621bool ProgramBinary::areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock,
622 const sh::InterfaceBlock &fragmentInterfaceBlock)
623{
624 const char* blockName = vertexInterfaceBlock.name.c_str();
625
626 // validate blocks for the same member types
627 if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size())
628 {
629 infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName);
630 return false;
631 }
632
633 if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize)
634 {
635 infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName);
636 return false;
637 }
638
639 if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout)
640 {
641 infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName);
642 return false;
643 }
644
645 const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size();
646 for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
647 {
648 const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex];
649 const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex];
650
651 if (vertexMember.name != fragmentMember.name)
652 {
653 infoLog.append("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')",
654 blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str());
655 return false;
656 }
657
658 std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'";
659 if (!gl::ProgramBinary::linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember))
660 {
661 return false;
662 }
663 }
664
665 return true;
666}
667
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000668// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
Jamie Madilld15250e2014-09-03 09:40:44 -0400669bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000670{
Jamie Madill2ad1dc42014-09-03 09:40:45 -0400671 const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
Brandon Jonesf05cdee2014-08-27 15:24:07 -0700672
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000673 unsigned int usedLocations = 0;
Jamie Madill54ad4f82014-09-03 09:40:46 -0400674 const std::vector<sh::Attribute> &shaderAttributes = vertexShader->getActiveAttributes();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000675
676 // Link attributes that have a binding location
Jamie Madill54ad4f82014-09-03 09:40:46 -0400677 for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000678 {
Jamie Madill54ad4f82014-09-03 09:40:46 -0400679 const sh::Attribute &attribute = shaderAttributes[attributeIndex];
680
681 ASSERT(attribute.staticUse);
682
Jamie Madilleba4eff2013-06-20 11:55:51 -0400683 const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000684
Brandon Joneseb994362014-09-24 10:27:28 -0700685 mProgram->getShaderAttributes()[attributeIndex] = attribute;
Jamie Madill2c7d84a2014-02-14 16:41:26 -0500686
Jamie Madilleba4eff2013-06-20 11:55:51 -0400687 if (location != -1) // Set by glBindAttribLocation or by location layout qualifier
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000688 {
Jamie Madillf2575982014-06-25 16:04:54 -0400689 const int rows = VariableRegisterCount(attribute.type);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000690
691 if (rows + location > MAX_VERTEX_ATTRIBS)
692 {
Jamie Madilldefb6742013-06-20 11:55:51 -0400693 infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute.name.c_str(), location);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000694
695 return false;
696 }
697
Jamie Madilleba4eff2013-06-20 11:55:51 -0400698 for (int row = 0; row < rows; row++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000699 {
Jamie Madilleba4eff2013-06-20 11:55:51 -0400700 const int rowLocation = location + row;
Jamie Madillf2575982014-06-25 16:04:54 -0400701 sh::ShaderVariable &linkedAttribute = mLinkedAttribute[rowLocation];
Jamie Madilleba4eff2013-06-20 11:55:51 -0400702
703 // In GLSL 3.00, attribute aliasing produces a link error
704 // In GLSL 1.00, attribute aliasing is allowed
Brandon Jones44151a92014-09-10 11:32:25 -0700705 if (mProgram->getShaderVersion() >= 300)
Jamie Madilleba4eff2013-06-20 11:55:51 -0400706 {
707 if (!linkedAttribute.name.empty())
708 {
709 infoLog.append("Attribute '%s' aliases attribute '%s' at location %d", attribute.name.c_str(), linkedAttribute.name.c_str(), rowLocation);
710 return false;
711 }
712 }
713
714 linkedAttribute = attribute;
715 usedLocations |= 1 << rowLocation;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000716 }
717 }
718 }
719
720 // Link attributes that don't have a binding location
Jamie Madill54ad4f82014-09-03 09:40:46 -0400721 for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000722 {
Jamie Madill54ad4f82014-09-03 09:40:46 -0400723 const sh::Attribute &attribute = shaderAttributes[attributeIndex];
724
725 ASSERT(attribute.staticUse);
726
Jamie Madilleba4eff2013-06-20 11:55:51 -0400727 const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000728
Jamie Madilleba4eff2013-06-20 11:55:51 -0400729 if (location == -1) // Not set by glBindAttribLocation or by location layout qualifier
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000730 {
Jamie Madillf2575982014-06-25 16:04:54 -0400731 int rows = VariableRegisterCount(attribute.type);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000732 int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
733
734 if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
735 {
Jamie Madilldefb6742013-06-20 11:55:51 -0400736 infoLog.append("Too many active attributes (%s)", attribute.name.c_str());
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000737
738 return false; // Fail to link
739 }
740
Jamie Madilldefb6742013-06-20 11:55:51 -0400741 mLinkedAttribute[availableIndex] = attribute;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000742 }
743 }
744
745 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
746 {
Brandon Jonesf05cdee2014-08-27 15:24:07 -0700747 int index = vertexShaderD3D->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
Jamie Madillf2575982014-06-25 16:04:54 -0400748 int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type);
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000749
750 for (int r = 0; r < rows; r++)
751 {
752 mSemanticIndex[attributeIndex++] = index++;
753 }
754 }
755
Al Patrick3f2daa82013-08-07 12:58:57 -0700756 initAttributesByLayout();
757
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000758 return true;
759}
760
Jamie Madillf2575982014-06-25 16:04:54 -0400761bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable,
762 const sh::ShaderVariable &fragmentVariable, bool validatePrecision)
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +0000763{
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400764 if (vertexVariable.type != fragmentVariable.type)
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +0000765 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400766 infoLog.append("Types for %s differ between vertex and fragment shaders", variableName.c_str());
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +0000767 return false;
768 }
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400769 if (vertexVariable.arraySize != fragmentVariable.arraySize)
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +0000770 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400771 infoLog.append("Array sizes for %s differ between vertex and fragment shaders", variableName.c_str());
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +0000772 return false;
773 }
Jamie Madill28167c62013-08-30 13:21:10 -0400774 if (validatePrecision && vertexVariable.precision != fragmentVariable.precision)
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +0000775 {
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400776 infoLog.append("Precisions for %s differ between vertex and fragment shaders", variableName.c_str());
Jamie Madill010fffa2013-06-20 11:55:53 -0400777 return false;
778 }
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +0000779
Jamie Madill42bcf322014-08-25 16:20:46 -0400780 if (vertexVariable.fields.size() != fragmentVariable.fields.size())
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400781 {
Jamie Madill42bcf322014-08-25 16:20:46 -0400782 infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", variableName.c_str());
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400783 return false;
784 }
Jamie Madill42bcf322014-08-25 16:20:46 -0400785 const unsigned int numMembers = vertexVariable.fields.size();
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +0000786 for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++)
787 {
Jamie Madill42bcf322014-08-25 16:20:46 -0400788 const sh::ShaderVariable &vertexMember = vertexVariable.fields[memberIndex];
789 const sh::ShaderVariable &fragmentMember = fragmentVariable.fields[memberIndex];
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +0000790
791 if (vertexMember.name != fragmentMember.name)
792 {
Jamie Madill28167c62013-08-30 13:21:10 -0400793 infoLog.append("Name mismatch for field '%d' of %s: (in vertex: '%s', in fragment: '%s')",
Jamie Madill42bcf322014-08-25 16:20:46 -0400794 memberIndex, variableName.c_str(),
795 vertexMember.name.c_str(), fragmentMember.name.c_str());
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +0000796 return false;
797 }
798
Jamie Madill42bcf322014-08-25 16:20:46 -0400799 const std::string memberName = variableName.substr(0, variableName.length() - 1) + "." +
800 vertexMember.name + "'";
801
802 if (!linkValidateVariablesBase(infoLog, vertexMember.name, vertexMember, fragmentMember, validatePrecision))
shannonwoods@chromium.org7923dd22013-05-30 00:11:04 +0000803 {
804 return false;
805 }
806 }
807
808 return true;
809}
810
Jamie Madill42bcf322014-08-25 16:20:46 -0400811bool ProgramBinary::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform)
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400812{
Jamie Madill28167c62013-08-30 13:21:10 -0400813 if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400814 {
815 return false;
816 }
817
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400818 return true;
819}
820
Jamie Madill42bcf322014-08-25 16:20:46 -0400821bool ProgramBinary::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying)
Jamie Madill28167c62013-08-30 13:21:10 -0400822{
823 if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false))
824 {
825 return false;
826 }
827
828 if (vertexVarying.interpolation != fragmentVarying.interpolation)
829 {
830 infoLog.append("Interpolation types for %s differ between vertex and fragment shaders", varyingName.c_str());
831 return false;
832 }
833
Jamie Madill28167c62013-08-30 13:21:10 -0400834 return true;
835}
836
Jamie Madill42bcf322014-08-25 16:20:46 -0400837bool ProgramBinary::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform)
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400838{
Jamie Madill28167c62013-08-30 13:21:10 -0400839 if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400840 {
841 return false;
842 }
843
Jamie Madilla6f267f2014-08-27 11:44:15 -0400844 if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout)
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400845 {
846 infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str());
847 return false;
848 }
849
Jamie Madill9d2ffb12013-08-30 13:21:04 -0400850 return true;
851}
852
Geoff Lang48dcae72014-02-05 16:28:24 -0500853bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
854 const std::vector<std::string> &transformFeedbackVaryingNames,
855 GLenum transformFeedbackBufferMode,
Brandon Jones43a53e22014-08-28 16:23:22 -0700856 std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings,
857 const Caps &caps) const
Geoff Lang48dcae72014-02-05 16:28:24 -0500858{
859 size_t totalComponents = 0;
Geoff Lang05881a02014-07-10 14:05:30 -0400860
Geoff Lang48dcae72014-02-05 16:28:24 -0500861 // Gather the linked varyings that are used for transform feedback, they should all exist.
862 outTransformFeedbackLinkedVaryings->clear();
863 for (size_t i = 0; i < transformFeedbackVaryingNames.size(); i++)
864 {
865 bool found = false;
866 for (size_t j = 0; j < linkedVaryings.size(); j++)
867 {
868 if (transformFeedbackVaryingNames[i] == linkedVaryings[j].name)
869 {
870 for (size_t k = 0; k < outTransformFeedbackLinkedVaryings->size(); k++)
871 {
872 if (outTransformFeedbackLinkedVaryings->at(k).name == linkedVaryings[j].name)
873 {
874 infoLog.append("Two transform feedback varyings specify the same output variable (%s).", linkedVaryings[j].name.c_str());
875 return false;
876 }
877 }
878
879 size_t componentCount = linkedVaryings[j].semanticIndexCount * 4;
880 if (transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS &&
Geoff Lang05881a02014-07-10 14:05:30 -0400881 componentCount > caps.maxTransformFeedbackSeparateComponents)
Geoff Lang48dcae72014-02-05 16:28:24 -0500882 {
883 infoLog.append("Transform feedback varying's %s components (%u) exceed the maximum separate components (%u).",
Geoff Lang05881a02014-07-10 14:05:30 -0400884 linkedVaryings[j].name.c_str(), componentCount, caps.maxTransformFeedbackSeparateComponents);
Geoff Lang48dcae72014-02-05 16:28:24 -0500885 return false;
886 }
887
888 totalComponents += componentCount;
889
890 outTransformFeedbackLinkedVaryings->push_back(linkedVaryings[j]);
891 found = true;
892 break;
893 }
894 }
895
896 // All transform feedback varyings are expected to exist since packVaryings checks for them.
897 ASSERT(found);
898 }
899
Geoff Lang05881a02014-07-10 14:05:30 -0400900 if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > caps.maxTransformFeedbackInterleavedComponents)
Geoff Lang48dcae72014-02-05 16:28:24 -0500901 {
902 infoLog.append("Transform feedback varying total components (%u) exceed the maximum interleaved components (%u).",
Geoff Lang05881a02014-07-10 14:05:30 -0400903 totalComponents, caps.maxTransformFeedbackInterleavedComponents);
Geoff Lang48dcae72014-02-05 16:28:24 -0500904 return false;
905 }
906
907 return true;
908}
909
Jamie Madill1b2a8f92014-05-14 13:09:39 -0400910bool ProgramBinary::isValidated() const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000911{
912 return mValidated;
913}
914
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +0000915void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000916{
917 // Skip over inactive attributes
918 unsigned int activeAttribute = 0;
919 unsigned int attribute;
920 for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
921 {
922 if (mLinkedAttribute[attribute].name.empty())
923 {
924 continue;
925 }
926
927 if (activeAttribute == index)
928 {
929 break;
930 }
931
932 activeAttribute++;
933 }
934
935 if (bufsize > 0)
936 {
937 const char *string = mLinkedAttribute[attribute].name.c_str();
938
939 strncpy(name, string, bufsize);
940 name[bufsize - 1] = '\0';
941
942 if (length)
943 {
944 *length = strlen(name);
945 }
946 }
947
948 *size = 1; // Always a single 'type' instance
949
950 *type = mLinkedAttribute[attribute].type;
951}
952
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +0000953GLint ProgramBinary::getActiveAttributeCount() const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000954{
955 int count = 0;
956
957 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
958 {
959 if (!mLinkedAttribute[attributeIndex].name.empty())
960 {
961 count++;
962 }
963 }
964
965 return count;
966}
967
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +0000968GLint ProgramBinary::getActiveAttributeMaxLength() const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000969{
970 int maxLength = 0;
971
972 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
973 {
974 if (!mLinkedAttribute[attributeIndex].name.empty())
975 {
976 maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength);
977 }
978 }
979
980 return maxLength;
981}
982
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +0000983void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000984{
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700985 ASSERT(index < mProgram->getUniforms().size()); // index must be smaller than getActiveUniformCount()
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000986
987 if (bufsize > 0)
988 {
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700989 std::string string = mProgram->getUniforms()[index]->name;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000990
Brandon Jones1a8a7e32014-10-01 12:49:30 -0700991 if (mProgram->getUniforms()[index]->isArray())
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +0000992 {
993 string += "[0]";
994 }
995
996 strncpy(name, string.c_str(), bufsize);
997 name[bufsize - 1] = '\0';
998
999 if (length)
1000 {
1001 *length = strlen(name);
1002 }
1003 }
1004
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001005 *size = mProgram->getUniforms()[index]->elementCount();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001006
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001007 *type = mProgram->getUniforms()[index]->type;
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001008}
1009
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +00001010GLint ProgramBinary::getActiveUniformCount() const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001011{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001012 return mProgram->getUniforms().size();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001013}
1014
shannon.woods@transgaming.com4f4215f2013-02-28 23:14:58 +00001015GLint ProgramBinary::getActiveUniformMaxLength() const
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001016{
1017 int maxLength = 0;
1018
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001019 unsigned int numUniforms = mProgram->getUniforms().size();
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001020 for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
1021 {
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001022 if (!mProgram->getUniforms()[uniformIndex]->name.empty())
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001023 {
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001024 int length = (int)(mProgram->getUniforms()[uniformIndex]->name.length() + 1);
1025 if (mProgram->getUniforms()[uniformIndex]->isArray())
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001026 {
1027 length += 3; // Counting in "[0]".
1028 }
1029 maxLength = std::max(length, maxLength);
1030 }
1031 }
1032
1033 return maxLength;
1034}
1035
shannonwoods@chromium.org2a9a9d22013-05-30 00:05:40 +00001036GLint ProgramBinary::getActiveUniformi(GLuint index, GLenum pname) const
1037{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001038 const gl::LinkedUniform& uniform = *mProgram->getUniforms()[index];
shannonwoods@chromium.org2a9a9d22013-05-30 00:05:40 +00001039
1040 switch (pname)
1041 {
1042 case GL_UNIFORM_TYPE: return static_cast<GLint>(uniform.type);
1043 case GL_UNIFORM_SIZE: return static_cast<GLint>(uniform.elementCount());
shannonwoods@chromium.orgb1dc1b62013-05-30 00:15:43 +00001044 case GL_UNIFORM_NAME_LENGTH: return static_cast<GLint>(uniform.name.size() + 1 + (uniform.isArray() ? 3 : 0));
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001045 case GL_UNIFORM_BLOCK_INDEX: return uniform.blockIndex;
shannonwoods@chromium.org2a9a9d22013-05-30 00:05:40 +00001046
shannonwoods@chromium.orgd7784172013-05-30 00:07:03 +00001047 case GL_UNIFORM_OFFSET: return uniform.blockInfo.offset;
1048 case GL_UNIFORM_ARRAY_STRIDE: return uniform.blockInfo.arrayStride;
1049 case GL_UNIFORM_MATRIX_STRIDE: return uniform.blockInfo.matrixStride;
1050 case GL_UNIFORM_IS_ROW_MAJOR: return static_cast<GLint>(uniform.blockInfo.isRowMajorMatrix);
shannonwoods@chromium.org2a9a9d22013-05-30 00:05:40 +00001051
1052 default:
1053 UNREACHABLE();
1054 break;
1055 }
1056 return 0;
1057}
1058
Jamie Madill36398922014-05-20 14:51:53 -04001059bool ProgramBinary::isValidUniformLocation(GLint location) const
1060{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001061 ASSERT(rx::IsIntegerCastSafe<GLint>(mProgram->getUniformIndices().size()));
1062 return (location >= 0 && location < static_cast<GLint>(mProgram->getUniformIndices().size()));
Jamie Madill36398922014-05-20 14:51:53 -04001063}
1064
1065LinkedUniform *ProgramBinary::getUniformByLocation(GLint location) const
1066{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001067 return mProgram->getUniformByLocation(location);
Jamie Madill36398922014-05-20 14:51:53 -04001068}
1069
Jamie Madill66d43d22014-07-11 17:02:03 -04001070LinkedUniform *ProgramBinary::getUniformByName(const std::string &name) const
1071{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001072 return mProgram->getUniformByName(name);
Jamie Madill66d43d22014-07-11 17:02:03 -04001073}
1074
shannonwoods@chromium.orgbeb02782013-05-30 00:07:28 +00001075void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
1076{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001077 ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount()
shannonwoods@chromium.orgbeb02782013-05-30 00:07:28 +00001078
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001079 const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
shannonwoods@chromium.orgbeb02782013-05-30 00:07:28 +00001080
1081 if (bufSize > 0)
1082 {
1083 std::string string = uniformBlock.name;
1084
1085 if (uniformBlock.isArrayElement())
1086 {
Jamie Madill5f562732014-02-14 16:41:24 -05001087 string += ArrayString(uniformBlock.elementIndex);
shannonwoods@chromium.orgbeb02782013-05-30 00:07:28 +00001088 }
1089
1090 strncpy(uniformBlockName, string.c_str(), bufSize);
1091 uniformBlockName[bufSize - 1] = '\0';
1092
1093 if (length)
1094 {
1095 *length = strlen(uniformBlockName);
1096 }
1097 }
1098}
1099
shannonwoods@chromium.orge7317ca2013-05-30 00:07:35 +00001100void ProgramBinary::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const
1101{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001102 ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount()
shannonwoods@chromium.orge7317ca2013-05-30 00:07:35 +00001103
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001104 const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
shannonwoods@chromium.orge7317ca2013-05-30 00:07:35 +00001105
1106 switch (pname)
1107 {
1108 case GL_UNIFORM_BLOCK_DATA_SIZE:
1109 *params = static_cast<GLint>(uniformBlock.dataSize);
1110 break;
1111 case GL_UNIFORM_BLOCK_NAME_LENGTH:
shannonwoods@chromium.org932cc6b2013-05-30 00:15:37 +00001112 *params = static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0));
shannonwoods@chromium.orge7317ca2013-05-30 00:07:35 +00001113 break;
1114 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
1115 *params = static_cast<GLint>(uniformBlock.memberUniformIndexes.size());
1116 break;
1117 case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
1118 {
1119 for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
1120 {
1121 params[blockMemberIndex] = static_cast<GLint>(uniformBlock.memberUniformIndexes[blockMemberIndex]);
1122 }
1123 }
1124 break;
1125 case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
1126 *params = static_cast<GLint>(uniformBlock.isReferencedByVertexShader());
1127 break;
1128 case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
1129 *params = static_cast<GLint>(uniformBlock.isReferencedByFragmentShader());
1130 break;
1131 default: UNREACHABLE();
1132 }
1133}
1134
shannonwoods@chromium.org70eb1ea2013-05-30 00:07:20 +00001135GLuint ProgramBinary::getActiveUniformBlockCount() const
1136{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001137 return mProgram->getUniformBlocks().size();
shannonwoods@chromium.org70eb1ea2013-05-30 00:07:20 +00001138}
1139
shannonwoods@chromium.orge684b582013-05-30 00:07:42 +00001140GLuint ProgramBinary::getActiveUniformBlockMaxLength() const
1141{
1142 unsigned int maxLength = 0;
1143
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001144 unsigned int numUniformBlocks = mProgram->getUniformBlocks().size();
shannonwoods@chromium.orge684b582013-05-30 00:07:42 +00001145 for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
1146 {
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001147 const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
shannonwoods@chromium.orge684b582013-05-30 00:07:42 +00001148 if (!uniformBlock.name.empty())
1149 {
1150 const unsigned int length = uniformBlock.name.length() + 1;
1151
1152 // Counting in "[0]".
1153 const unsigned int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0);
1154
1155 maxLength = std::max(length + arrayLength, maxLength);
1156 }
1157 }
1158
1159 return maxLength;
1160}
1161
Brandon Jones43a53e22014-08-28 16:23:22 -07001162void ProgramBinary::validate(InfoLog &infoLog, const Caps &caps)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001163{
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001164 applyUniforms();
Brandon Jones43a53e22014-08-28 16:23:22 -07001165 if (!validateSamplers(&infoLog, caps))
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001166 {
1167 mValidated = false;
1168 }
1169 else
1170 {
1171 mValidated = true;
1172 }
1173}
1174
Brandon Jones43a53e22014-08-28 16:23:22 -07001175bool ProgramBinary::validateSamplers(InfoLog *infoLog, const Caps &caps)
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001176{
Brandon Jones1a8a7e32014-10-01 12:49:30 -07001177 return mProgram->validateSamplers(infoLog, caps);
apatrick@chromium.org90080e32012-07-09 22:15:33 +00001178}
1179
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00001180struct AttributeSorter
1181{
1182 AttributeSorter(const int (&semanticIndices)[MAX_VERTEX_ATTRIBS])
1183 : originalIndices(semanticIndices)
1184 {
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00001185 }
1186
1187 bool operator()(int a, int b)
1188 {
Jamie Madill03181ab2013-12-18 12:56:06 -05001189 if (originalIndices[a] == -1) return false;
1190 if (originalIndices[b] == -1) return true;
1191 return (originalIndices[a] < originalIndices[b]);
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00001192 }
1193
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00001194 const int (&originalIndices)[MAX_VERTEX_ATTRIBS];
1195};
1196
Al Patrick3f2daa82013-08-07 12:58:57 -07001197void ProgramBinary::initAttributesByLayout()
1198{
1199 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
1200 {
1201 mAttributesByLayout[i] = i;
1202 }
1203
1204 std::sort(&mAttributesByLayout[0], &mAttributesByLayout[MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex));
1205}
1206
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00001207void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const
1208{
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00001209 rx::TranslatedAttribute oldTranslatedAttributes[MAX_VERTEX_ATTRIBS];
1210
1211 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
1212 {
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00001213 oldTranslatedAttributes[i] = attributes[i];
1214 }
1215
1216 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
1217 {
Al Patrick3f2daa82013-08-07 12:58:57 -07001218 int oldIndex = mAttributesByLayout[i];
1219 sortedSemanticIndices[i] = mSemanticIndex[oldIndex];
shannon.woods@transgaming.com0b600142013-02-28 23:15:04 +00001220 attributes[i] = oldTranslatedAttributes[oldIndex];
1221 }
1222}
1223
Geoff Lang04fb89a2014-06-09 15:05:36 -04001224void ProgramBinary::reset()
1225{
Geoff Lang04fb89a2014-06-09 15:05:36 -04001226 mOutputVariables.clear();
Brandon Jonesc9610c52014-08-25 17:02:59 -07001227
1228 mProgram->reset();
Geoff Lang04fb89a2014-06-09 15:05:36 -04001229
1230 mValidated = false;
1231}
1232
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +00001233}