blob: 9aaae63e40d903d0b17c4bec8595c17f32d20870 [file] [log] [blame]
Geoff Langf9a6f082015-01-22 13:32:49 -05001//
2// Copyright 2015 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// ProgramGL.cpp: Implements the class methods for ProgramGL.
8
9#include "libANGLE/renderer/gl/ProgramGL.h"
10
11#include "common/debug.h"
Geoff Lang5ed74cf2015-04-14 13:57:07 -040012#include "common/utilities.h"
Geoff Langb1f435e2015-02-20 10:01:01 -050013#include "libANGLE/renderer/gl/FunctionsGL.h"
14#include "libANGLE/renderer/gl/ShaderGL.h"
15#include "libANGLE/renderer/gl/StateManagerGL.h"
Philippe Hamel40911192016-04-07 16:45:50 -040016#include "libANGLE/renderer/gl/WorkaroundsGL.h"
unknownb4a3af22015-11-25 15:02:51 -050017#include "platform/Platform.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050018
19namespace rx
20{
21
Jamie Madill5c6b7bf2015-08-17 12:53:35 -040022ProgramGL::ProgramGL(const gl::Program::Data &data,
23 const FunctionsGL *functions,
Philippe Hamel40911192016-04-07 16:45:50 -040024 const WorkaroundsGL &workarounds,
Jamie Madill5c6b7bf2015-08-17 12:53:35 -040025 StateManagerGL *stateManager)
Philippe Hamel40911192016-04-07 16:45:50 -040026 : ProgramImpl(data),
27 mFunctions(functions),
28 mWorkarounds(workarounds),
29 mStateManager(stateManager),
30 mProgramID(0)
Geoff Langb1f435e2015-02-20 10:01:01 -050031{
32 ASSERT(mFunctions);
33 ASSERT(mStateManager);
Geoff Lang0ca53782015-05-07 13:49:39 -040034
35 mProgramID = mFunctions->createProgram();
Geoff Langb1f435e2015-02-20 10:01:01 -050036}
Geoff Langf9a6f082015-01-22 13:32:49 -050037
38ProgramGL::~ProgramGL()
Geoff Langb1f435e2015-02-20 10:01:01 -050039{
Geoff Lang0ca53782015-05-07 13:49:39 -040040 mFunctions->deleteProgram(mProgramID);
41 mProgramID = 0;
Geoff Langb1f435e2015-02-20 10:01:01 -050042}
Geoff Langf9a6f082015-01-22 13:32:49 -050043
Geoff Langf9a6f082015-01-22 13:32:49 -050044LinkResult ProgramGL::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
45{
Geoff Lang65a0be92015-10-02 09:57:30 -040046 preLink();
47
48 // Read the binary format, size and blob
49 GLenum binaryFormat = stream->readInt<GLenum>();
50 GLint binaryLength = stream->readInt<GLint>();
51 const uint8_t *binary = stream->data() + stream->offset();
52 stream->skip(binaryLength);
53
54 // Load the binary
55 mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength);
56
57 // Verify that the program linked
58 if (!checkLinkStatus(infoLog))
59 {
60 return LinkResult(false, gl::Error(GL_NO_ERROR));
61 }
62
63 postLink();
64
65 return LinkResult(true, gl::Error(GL_NO_ERROR));
Geoff Langf9a6f082015-01-22 13:32:49 -050066}
67
68gl::Error ProgramGL::save(gl::BinaryOutputStream *stream)
69{
Geoff Lang65a0be92015-10-02 09:57:30 -040070 GLint binaryLength = 0;
71 mFunctions->getProgramiv(mProgramID, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
72
73 std::vector<uint8_t> binary(binaryLength);
74 GLenum binaryFormat = GL_NONE;
75 mFunctions->getProgramBinary(mProgramID, binaryLength, &binaryLength, &binaryFormat,
76 &binary[0]);
77
78 stream->writeInt(binaryFormat);
79 stream->writeInt(binaryLength);
80 stream->writeBytes(&binary[0], binaryLength);
81
82 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -050083}
84
Geoff Langc5629752015-12-07 16:29:04 -050085void ProgramGL::setBinaryRetrievableHint(bool retrievable)
86{
Geoff Lang65a0be92015-10-02 09:57:30 -040087 // glProgramParameteri isn't always available on ES backends.
88 if (mFunctions->programParameteri)
89 {
90 mFunctions->programParameteri(mProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT,
91 retrievable ? GL_TRUE : GL_FALSE);
92 }
Geoff Langc5629752015-12-07 16:29:04 -050093}
94
Jamie Madill9082b982016-04-27 15:21:51 -040095LinkResult ProgramGL::link(const gl::ContextState &data, gl::InfoLog &infoLog)
Geoff Langf9a6f082015-01-22 13:32:49 -050096{
Geoff Lang65a0be92015-10-02 09:57:30 -040097 preLink();
Geoff Langb1f435e2015-02-20 10:01:01 -050098
Geoff Lang1a683462015-09-29 15:09:59 -040099 // Set the transform feedback state
100 std::vector<const GLchar *> transformFeedbackVaryings;
101 for (const auto &tfVarying : mData.getTransformFeedbackVaryingNames())
102 {
103 transformFeedbackVaryings.push_back(tfVarying.c_str());
104 }
105
106 if (transformFeedbackVaryings.empty())
107 {
108 if (mFunctions->transformFeedbackVaryings)
109 {
110 mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
111 mData.getTransformFeedbackBufferMode());
112 }
113 }
114 else
115 {
116 ASSERT(mFunctions->transformFeedbackVaryings);
117 mFunctions->transformFeedbackVaryings(
118 mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()),
119 &transformFeedbackVaryings[0], mData.getTransformFeedbackBufferMode());
120 }
121
Geoff Lang65a0be92015-10-02 09:57:30 -0400122 const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mData.getAttachedVertexShader());
123 const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mData.getAttachedFragmentShader());
Geoff Langb1f435e2015-02-20 10:01:01 -0500124
Geoff Langb1f435e2015-02-20 10:01:01 -0500125 // Attach the shaders
126 mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
127 mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
128
Geoff Lang1528e562015-08-24 15:10:58 -0400129 // Bind attribute locations to match the GL layer.
130 for (const sh::Attribute &attribute : mData.getAttributes())
131 {
132 if (!attribute.staticUse)
133 {
134 continue;
135 }
136
137 mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.name.c_str());
Geoff Lang1528e562015-08-24 15:10:58 -0400138 }
139
Geoff Langb1f435e2015-02-20 10:01:01 -0500140 // Link and verify
141 mFunctions->linkProgram(mProgramID);
142
Geoff Lang0ca53782015-05-07 13:49:39 -0400143 // Detach the shaders
144 mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
145 mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
146
147 // Verify the link
Geoff Lang65a0be92015-10-02 09:57:30 -0400148 if (!checkLinkStatus(infoLog))
Geoff Langb1f435e2015-02-20 10:01:01 -0500149 {
Geoff Langb1f435e2015-02-20 10:01:01 -0500150 return LinkResult(false, gl::Error(GL_NO_ERROR));
151 }
152
Philippe Hamel40911192016-04-07 16:45:50 -0400153 if (mWorkarounds.alwaysCallUseProgramAfterLink)
154 {
155 mStateManager->forceUseProgram(mProgramID);
156 }
157
Geoff Lang65a0be92015-10-02 09:57:30 -0400158 postLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500159
Geoff Langb1f435e2015-02-20 10:01:01 -0500160 return LinkResult(true, gl::Error(GL_NO_ERROR));
Geoff Langf9a6f082015-01-22 13:32:49 -0500161}
162
Jamie Madill36cfd6a2015-08-18 10:46:20 -0400163GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
164{
165 // TODO(jmadill): implement validate
166 return true;
167}
168
Geoff Langf9a6f082015-01-22 13:32:49 -0500169void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
170{
Geoff Lang63cbace2015-02-26 10:03:12 -0500171 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400172 mFunctions->uniform1fv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500173}
174
175void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
176{
Geoff Lang63cbace2015-02-26 10:03:12 -0500177 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400178 mFunctions->uniform2fv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500179}
180
181void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
182{
Geoff Lang63cbace2015-02-26 10:03:12 -0500183 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400184 mFunctions->uniform3fv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500185}
186
187void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
188{
Geoff Lang63cbace2015-02-26 10:03:12 -0500189 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400190 mFunctions->uniform4fv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500191}
192
193void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
194{
Geoff Lang63cbace2015-02-26 10:03:12 -0500195 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400196 mFunctions->uniform1iv(uniLoc(location), count, v);
Geoff Langf51bc792015-05-04 14:57:03 -0400197
Jamie Madill62d31cb2015-09-11 13:25:51 -0400198 const gl::VariableLocation &locationEntry = mData.getUniformLocations()[location];
199
200 size_t samplerIndex = mUniformIndexToSamplerIndex[locationEntry.index];
201 if (samplerIndex != GL_INVALID_INDEX)
Geoff Langf51bc792015-05-04 14:57:03 -0400202 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400203 std::vector<GLuint> &boundTextureUnits = mSamplerBindings[samplerIndex].boundTextureUnits;
Geoff Langf51bc792015-05-04 14:57:03 -0400204
Jamie Madill62d31cb2015-09-11 13:25:51 -0400205 size_t copyCount =
206 std::max<size_t>(count, boundTextureUnits.size() - locationEntry.element);
207 std::copy(v, v + copyCount, boundTextureUnits.begin() + locationEntry.element);
Geoff Langf51bc792015-05-04 14:57:03 -0400208 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500209}
210
211void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
212{
Geoff Lang63cbace2015-02-26 10:03:12 -0500213 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400214 mFunctions->uniform2iv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500215}
216
217void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
218{
Geoff Lang63cbace2015-02-26 10:03:12 -0500219 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400220 mFunctions->uniform3iv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500221}
222
223void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
224{
Geoff Lang63cbace2015-02-26 10:03:12 -0500225 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400226 mFunctions->uniform4iv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500227}
228
229void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
230{
Geoff Lang63cbace2015-02-26 10:03:12 -0500231 mStateManager->useProgram(mProgramID);
Geoff Langb1f435e2015-02-20 10:01:01 -0500232 mFunctions->uniform1uiv(location, count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500233}
234
235void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
236{
Geoff Lang63cbace2015-02-26 10:03:12 -0500237 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400238 mFunctions->uniform2uiv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500239}
240
241void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
242{
Geoff Lang63cbace2015-02-26 10:03:12 -0500243 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400244 mFunctions->uniform3uiv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500245}
246
247void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
248{
Geoff Lang63cbace2015-02-26 10:03:12 -0500249 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400250 mFunctions->uniform4uiv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500251}
252
253void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
254{
Geoff Lang63cbace2015-02-26 10:03:12 -0500255 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400256 mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500257}
258
259void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
260{
Geoff Lang63cbace2015-02-26 10:03:12 -0500261 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400262 mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500263}
264
265void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
266{
Geoff Lang63cbace2015-02-26 10:03:12 -0500267 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400268 mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500269}
270
271void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
272{
Geoff Lang63cbace2015-02-26 10:03:12 -0500273 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400274 mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500275}
276
277void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
278{
Geoff Lang63cbace2015-02-26 10:03:12 -0500279 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400280 mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500281}
282
283void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
284{
Geoff Lang63cbace2015-02-26 10:03:12 -0500285 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400286 mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500287}
288
289void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
290{
Geoff Lang63cbace2015-02-26 10:03:12 -0500291 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400292 mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500293}
294
295void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
296{
Geoff Lang63cbace2015-02-26 10:03:12 -0500297 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400298 mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500299}
300
301void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
302{
Geoff Lang63cbace2015-02-26 10:03:12 -0500303 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400304 mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500305}
306
Geoff Lang5d124a62015-09-15 13:03:27 -0400307void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
308{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400309 // Lazy init
310 if (mUniformBlockRealLocationMap.empty())
311 {
312 mUniformBlockRealLocationMap.reserve(mData.getUniformBlocks().size());
313 for (const gl::UniformBlock &uniformBlock : mData.getUniformBlocks())
314 {
315 const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex();
316 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str());
317 mUniformBlockRealLocationMap.push_back(blockIndex);
318 }
319 }
320
321 GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
322 if (realBlockIndex != GL_INVALID_INDEX)
323 {
324 mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
325 }
Geoff Lang5d124a62015-09-15 13:03:27 -0400326}
327
Geoff Langb1f435e2015-02-20 10:01:01 -0500328GLuint ProgramGL::getProgramID() const
329{
330 return mProgramID;
331}
332
Geoff Langf51bc792015-05-04 14:57:03 -0400333const std::vector<SamplerBindingGL> &ProgramGL::getAppliedSamplerUniforms() const
334{
335 return mSamplerBindings;
336}
337
Jamie Madill4a3c2342015-10-08 12:58:45 -0400338bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400339{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400340 ASSERT(mProgramID != 0u);
Geoff Lang5d124a62015-09-15 13:03:27 -0400341
Jamie Madill4a3c2342015-10-08 12:58:45 -0400342 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str());
343 if (blockIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400344 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400345 *sizeOut = 0;
346 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400347 }
348
Jamie Madill4a3c2342015-10-08 12:58:45 -0400349 GLint dataSize = 0;
350 mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
351 &dataSize);
352 *sizeOut = static_cast<size_t>(dataSize);
353 return true;
354}
355
356bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName,
357 sh::BlockMemberInfo *memberInfoOut) const
358{
359 GLuint uniformIndex;
360 const GLchar *memberNameGLStr = memberUniformName.c_str();
361 mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
362
363 if (uniformIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400364 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400365 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
366 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400367 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400368
369 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
370 &memberInfoOut->offset);
371 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
372 &memberInfoOut->arrayStride);
373 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
374 &memberInfoOut->matrixStride);
375
376 // TODO(jmadill): possibly determine this at the gl::Program level.
377 GLint isRowMajorMatrix = 0;
378 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
379 &isRowMajorMatrix);
380 memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
381 return true;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400382}
Jamie Madill4a3c2342015-10-08 12:58:45 -0400383
Geoff Lang65a0be92015-10-02 09:57:30 -0400384void ProgramGL::preLink()
385{
386 // Reset the program state
387 mUniformRealLocationMap.clear();
388 mUniformBlockRealLocationMap.clear();
389 mSamplerBindings.clear();
390 mUniformIndexToSamplerIndex.clear();
391}
392
393bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
394{
395 GLint linkStatus = GL_FALSE;
396 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
397 if (linkStatus == GL_FALSE)
398 {
399 // Linking failed, put the error into the info log
400 GLint infoLogLength = 0;
401 mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
402
403 std::string warning;
404
405 // Info log length includes the null terminator, so 1 means that the info log is an empty
406 // string.
407 if (infoLogLength > 1)
408 {
409 std::vector<char> buf(infoLogLength);
410 mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
411
412 mFunctions->deleteProgram(mProgramID);
413 mProgramID = 0;
414
415 infoLog << buf.data();
416
417 warning = FormatString("Program link failed unexpectedly: %s", buf.data());
418 }
419 else
420 {
421 warning = "Program link failed unexpectedly with no info log.";
422 }
423 ANGLEPlatformCurrent()->logWarning(warning.c_str());
424 TRACE("\n%s", warning.c_str());
425
426 // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
427 return false;
428 }
429
430 return true;
431}
432
433void ProgramGL::postLink()
434{
435 // Query the uniform information
436 ASSERT(mUniformRealLocationMap.empty());
437 const auto &uniformLocations = mData.getUniformLocations();
438 const auto &uniforms = mData.getUniforms();
439 mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
440 for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
441 {
442 const auto &entry = uniformLocations[uniformLocation];
443 if (!entry.used)
444 {
445 continue;
446 }
447
448 // From the spec:
449 // "Locations for sequential array indices are not required to be sequential."
450 const gl::LinkedUniform &uniform = uniforms[entry.index];
451 std::stringstream fullNameStr;
452 fullNameStr << uniform.name;
453 if (uniform.isArray())
454 {
455 fullNameStr << "[" << entry.element << "]";
456 }
457 const std::string &fullName = fullNameStr.str();
458
459 GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
460 mUniformRealLocationMap[uniformLocation] = realLocation;
461 }
462
463 mUniformIndexToSamplerIndex.resize(mData.getUniforms().size(), GL_INVALID_INDEX);
464
465 for (size_t uniformId = 0; uniformId < uniforms.size(); ++uniformId)
466 {
467 const gl::LinkedUniform &linkedUniform = uniforms[uniformId];
468
469 if (!linkedUniform.isSampler() || !linkedUniform.staticUse)
470 continue;
471
472 mUniformIndexToSamplerIndex[uniformId] = mSamplerBindings.size();
473
474 // If uniform is a sampler type, insert it into the mSamplerBindings array
475 SamplerBindingGL samplerBinding;
476 samplerBinding.textureType = gl::SamplerTypeToTextureType(linkedUniform.type);
477 samplerBinding.boundTextureUnits.resize(linkedUniform.elementCount(), 0);
478 mSamplerBindings.push_back(samplerBinding);
479 }
480}
481
Jamie Madill4a3c2342015-10-08 12:58:45 -0400482} // namespace rx