blob: acbed580d590a14a8a8226630ced7a96e09d21b5 [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
Jamie Madilla7d12dc2016-12-13 15:08:19 -050011#include "common/BitSetIterator.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030012#include "common/angleutils.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050013#include "common/debug.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030014#include "common/string_utils.h"
Geoff Lang5ed74cf2015-04-14 13:57:07 -040015#include "common/utilities.h"
Jamie Madilla7d12dc2016-12-13 15:08:19 -050016#include "libANGLE/renderer/gl/ContextGL.h"
Geoff Langb1f435e2015-02-20 10:01:01 -050017#include "libANGLE/renderer/gl/FunctionsGL.h"
18#include "libANGLE/renderer/gl/ShaderGL.h"
19#include "libANGLE/renderer/gl/StateManagerGL.h"
Philippe Hamel40911192016-04-07 16:45:50 -040020#include "libANGLE/renderer/gl/WorkaroundsGL.h"
Jamie Madill53ea9cc2016-05-17 10:12:52 -040021#include "libANGLE/Uniform.h"
unknownb4a3af22015-11-25 15:02:51 -050022#include "platform/Platform.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050023
24namespace rx
25{
26
Jamie Madill48ef11b2016-04-27 15:21:52 -040027ProgramGL::ProgramGL(const gl::ProgramState &data,
Jamie Madill5c6b7bf2015-08-17 12:53:35 -040028 const FunctionsGL *functions,
Philippe Hamel40911192016-04-07 16:45:50 -040029 const WorkaroundsGL &workarounds,
Sami Väisänen46eaa942016-06-29 10:26:37 +030030 StateManagerGL *stateManager,
31 bool enablePathRendering)
Philippe Hamel40911192016-04-07 16:45:50 -040032 : ProgramImpl(data),
33 mFunctions(functions),
34 mWorkarounds(workarounds),
35 mStateManager(stateManager),
Sami Väisänen46eaa942016-06-29 10:26:37 +030036 mEnablePathRendering(enablePathRendering),
Philippe Hamel40911192016-04-07 16:45:50 -040037 mProgramID(0)
Geoff Langb1f435e2015-02-20 10:01:01 -050038{
39 ASSERT(mFunctions);
40 ASSERT(mStateManager);
Geoff Lang0ca53782015-05-07 13:49:39 -040041
42 mProgramID = mFunctions->createProgram();
Geoff Langb1f435e2015-02-20 10:01:01 -050043}
Geoff Langf9a6f082015-01-22 13:32:49 -050044
45ProgramGL::~ProgramGL()
Geoff Langb1f435e2015-02-20 10:01:01 -050046{
Geoff Lang0ca53782015-05-07 13:49:39 -040047 mFunctions->deleteProgram(mProgramID);
48 mProgramID = 0;
Geoff Langb1f435e2015-02-20 10:01:01 -050049}
Geoff Langf9a6f082015-01-22 13:32:49 -050050
Jamie Madilla7d12dc2016-12-13 15:08:19 -050051LinkResult ProgramGL::load(const ContextImpl *contextImpl,
52 gl::InfoLog &infoLog,
53 gl::BinaryInputStream *stream)
Geoff Langf9a6f082015-01-22 13:32:49 -050054{
Geoff Lang65a0be92015-10-02 09:57:30 -040055 preLink();
56
57 // Read the binary format, size and blob
58 GLenum binaryFormat = stream->readInt<GLenum>();
59 GLint binaryLength = stream->readInt<GLint>();
60 const uint8_t *binary = stream->data() + stream->offset();
61 stream->skip(binaryLength);
62
63 // Load the binary
64 mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength);
65
66 // Verify that the program linked
67 if (!checkLinkStatus(infoLog))
68 {
Jamie Madillb0a838b2016-11-13 20:02:12 -050069 return false;
Geoff Lang65a0be92015-10-02 09:57:30 -040070 }
71
72 postLink();
73
Jamie Madilla7d12dc2016-12-13 15:08:19 -050074 // Re-apply UBO bindings to work around driver bugs.
75 const WorkaroundsGL &workaroundsGL = GetAs<ContextGL>(contextImpl)->getWorkaroundsGL();
76 if (workaroundsGL.reapplyUBOBindingsAfterLoadingBinaryProgram)
77 {
78 for (GLuint bindingIndex : angle::IterateBitSet(mState.getActiveUniformBlockBindingsMask()))
79 {
80 setUniformBlockBinding(bindingIndex, mState.getUniformBlockBinding(bindingIndex));
81 }
82 }
83
Jamie Madillb0a838b2016-11-13 20:02:12 -050084 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -050085}
86
87gl::Error ProgramGL::save(gl::BinaryOutputStream *stream)
88{
Geoff Lang65a0be92015-10-02 09:57:30 -040089 GLint binaryLength = 0;
90 mFunctions->getProgramiv(mProgramID, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
91
92 std::vector<uint8_t> binary(binaryLength);
93 GLenum binaryFormat = GL_NONE;
94 mFunctions->getProgramBinary(mProgramID, binaryLength, &binaryLength, &binaryFormat,
95 &binary[0]);
96
97 stream->writeInt(binaryFormat);
98 stream->writeInt(binaryLength);
99 stream->writeBytes(&binary[0], binaryLength);
100
He Yunchaoacd18982017-01-04 10:46:42 +0800101 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500102}
103
Geoff Langc5629752015-12-07 16:29:04 -0500104void ProgramGL::setBinaryRetrievableHint(bool retrievable)
105{
Geoff Lang65a0be92015-10-02 09:57:30 -0400106 // glProgramParameteri isn't always available on ES backends.
107 if (mFunctions->programParameteri)
108 {
109 mFunctions->programParameteri(mProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT,
110 retrievable ? GL_TRUE : GL_FALSE);
111 }
Geoff Langc5629752015-12-07 16:29:04 -0500112}
113
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500114LinkResult ProgramGL::link(ContextImpl *contextImpl,
Jamie Madill192745a2016-12-22 15:58:21 -0500115 const gl::VaryingPacking &packing,
116 gl::InfoLog &infoLog)
Geoff Langf9a6f082015-01-22 13:32:49 -0500117{
Geoff Lang65a0be92015-10-02 09:57:30 -0400118 preLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500119
Martin Radev4c4c8e72016-08-04 12:25:34 +0300120 if (mState.getAttachedComputeShader())
Geoff Lang1a683462015-09-29 15:09:59 -0400121 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300122 const ShaderGL *computeShaderGL = GetImplAs<ShaderGL>(mState.getAttachedComputeShader());
Geoff Lang1a683462015-09-29 15:09:59 -0400123
Martin Radev4c4c8e72016-08-04 12:25:34 +0300124 mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID());
125
126 // Link and verify
127 mFunctions->linkProgram(mProgramID);
128
129 // Detach the shaders
130 mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID());
Geoff Lang1a683462015-09-29 15:09:59 -0400131 }
132 else
133 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300134 // Set the transform feedback state
135 std::vector<const GLchar *> transformFeedbackVaryings;
136 for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
Geoff Lang1528e562015-08-24 15:10:58 -0400137 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300138 transformFeedbackVaryings.push_back(tfVarying.c_str());
Geoff Lang1528e562015-08-24 15:10:58 -0400139 }
140
Martin Radev4c4c8e72016-08-04 12:25:34 +0300141 if (transformFeedbackVaryings.empty())
142 {
143 if (mFunctions->transformFeedbackVaryings)
144 {
145 mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
146 mState.getTransformFeedbackBufferMode());
147 }
148 }
149 else
150 {
151 ASSERT(mFunctions->transformFeedbackVaryings);
152 mFunctions->transformFeedbackVaryings(
153 mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()),
154 &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
155 }
156
157 const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mState.getAttachedVertexShader());
158 const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader());
159
160 // Attach the shaders
161 mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
162 mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
163
164 // Bind attribute locations to match the GL layer.
165 for (const sh::Attribute &attribute : mState.getAttributes())
166 {
Corentin Wallez6c1cbf52016-11-23 12:44:35 -0500167 if (!attribute.staticUse || attribute.isBuiltIn())
Martin Radev4c4c8e72016-08-04 12:25:34 +0300168 {
169 continue;
170 }
171
172 mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.name.c_str());
173 }
174
175 // Link and verify
176 mFunctions->linkProgram(mProgramID);
177
178 // Detach the shaders
179 mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
180 mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
Geoff Lang1528e562015-08-24 15:10:58 -0400181 }
182
Geoff Lang0ca53782015-05-07 13:49:39 -0400183 // Verify the link
Geoff Lang65a0be92015-10-02 09:57:30 -0400184 if (!checkLinkStatus(infoLog))
Geoff Langb1f435e2015-02-20 10:01:01 -0500185 {
Jamie Madillb0a838b2016-11-13 20:02:12 -0500186 return false;
Geoff Langb1f435e2015-02-20 10:01:01 -0500187 }
188
Philippe Hamel40911192016-04-07 16:45:50 -0400189 if (mWorkarounds.alwaysCallUseProgramAfterLink)
190 {
191 mStateManager->forceUseProgram(mProgramID);
192 }
193
Geoff Lang65a0be92015-10-02 09:57:30 -0400194 postLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500195
Jamie Madillb0a838b2016-11-13 20:02:12 -0500196 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -0500197}
198
Jamie Madill36cfd6a2015-08-18 10:46:20 -0400199GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
200{
201 // TODO(jmadill): implement validate
202 return true;
203}
204
Geoff Langf9a6f082015-01-22 13:32:49 -0500205void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
206{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800207 if (mFunctions->programUniform1fv != nullptr)
208 {
209 mFunctions->programUniform1fv(mProgramID, uniLoc(location), count, v);
210 }
211 else
212 {
213 mStateManager->useProgram(mProgramID);
214 mFunctions->uniform1fv(uniLoc(location), count, v);
215 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500216}
217
218void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
219{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800220 if (mFunctions->programUniform2fv != nullptr)
221 {
222 mFunctions->programUniform2fv(mProgramID, uniLoc(location), count, v);
223 }
224 else
225 {
226 mStateManager->useProgram(mProgramID);
227 mFunctions->uniform2fv(uniLoc(location), count, v);
228 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500229}
230
231void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
232{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800233 if (mFunctions->programUniform3fv != nullptr)
234 {
235 mFunctions->programUniform3fv(mProgramID, uniLoc(location), count, v);
236 }
237 else
238 {
239 mStateManager->useProgram(mProgramID);
240 mFunctions->uniform3fv(uniLoc(location), count, v);
241 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500242}
243
244void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
245{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800246 if (mFunctions->programUniform4fv != nullptr)
247 {
248 mFunctions->programUniform4fv(mProgramID, uniLoc(location), count, v);
249 }
250 else
251 {
252 mStateManager->useProgram(mProgramID);
253 mFunctions->uniform4fv(uniLoc(location), count, v);
254 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500255}
256
257void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
258{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800259 if (mFunctions->programUniform1iv != nullptr)
260 {
261 mFunctions->programUniform1iv(mProgramID, uniLoc(location), count, v);
262 }
263 else
264 {
265 mStateManager->useProgram(mProgramID);
266 mFunctions->uniform1iv(uniLoc(location), count, v);
267 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500268}
269
270void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
271{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800272 if (mFunctions->programUniform2iv != nullptr)
273 {
274 mFunctions->programUniform2iv(mProgramID, uniLoc(location), count, v);
275 }
276 else
277 {
278 mStateManager->useProgram(mProgramID);
279 mFunctions->uniform2iv(uniLoc(location), count, v);
280 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500281}
282
283void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
284{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800285 if (mFunctions->programUniform3iv != nullptr)
286 {
287 mFunctions->programUniform3iv(mProgramID, uniLoc(location), count, v);
288 }
289 else
290 {
291 mStateManager->useProgram(mProgramID);
292 mFunctions->uniform3iv(uniLoc(location), count, v);
293 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500294}
295
296void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
297{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800298 if (mFunctions->programUniform4iv != nullptr)
299 {
300 mFunctions->programUniform4iv(mProgramID, uniLoc(location), count, v);
301 }
302 else
303 {
304 mStateManager->useProgram(mProgramID);
305 mFunctions->uniform4iv(uniLoc(location), count, v);
306 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500307}
308
309void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
310{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800311 if (mFunctions->programUniform1uiv != nullptr)
312 {
313 mFunctions->programUniform1uiv(mProgramID, uniLoc(location), count, v);
314 }
315 else
316 {
317 mStateManager->useProgram(mProgramID);
318 mFunctions->uniform1uiv(uniLoc(location), count, v);
319 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500320}
321
322void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
323{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800324 if (mFunctions->programUniform2uiv != nullptr)
325 {
326 mFunctions->programUniform2uiv(mProgramID, uniLoc(location), count, v);
327 }
328 else
329 {
330 mStateManager->useProgram(mProgramID);
331 mFunctions->uniform2uiv(uniLoc(location), count, v);
332 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500333}
334
335void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
336{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800337 if (mFunctions->programUniform3uiv != nullptr)
338 {
339 mFunctions->programUniform3uiv(mProgramID, uniLoc(location), count, v);
340 }
341 else
342 {
343 mStateManager->useProgram(mProgramID);
344 mFunctions->uniform3uiv(uniLoc(location), count, v);
345 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500346}
347
348void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
349{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800350 if (mFunctions->programUniform4uiv != nullptr)
351 {
352 mFunctions->programUniform4uiv(mProgramID, uniLoc(location), count, v);
353 }
354 else
355 {
356 mStateManager->useProgram(mProgramID);
357 mFunctions->uniform4uiv(uniLoc(location), count, v);
358 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500359}
360
361void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
362{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800363 if (mFunctions->programUniformMatrix2fv != nullptr)
364 {
365 mFunctions->programUniformMatrix2fv(mProgramID, uniLoc(location), count, transpose, value);
366 }
367 else
368 {
369 mStateManager->useProgram(mProgramID);
370 mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
371 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500372}
373
374void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
375{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800376 if (mFunctions->programUniformMatrix3fv != nullptr)
377 {
378 mFunctions->programUniformMatrix3fv(mProgramID, uniLoc(location), count, transpose, value);
379 }
380 else
381 {
382 mStateManager->useProgram(mProgramID);
383 mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
384 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500385}
386
387void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
388{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800389 if (mFunctions->programUniformMatrix4fv != nullptr)
390 {
391 mFunctions->programUniformMatrix4fv(mProgramID, uniLoc(location), count, transpose, value);
392 }
393 else
394 {
395 mStateManager->useProgram(mProgramID);
396 mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
397 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500398}
399
400void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
401{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800402 if (mFunctions->programUniformMatrix2x3fv != nullptr)
403 {
404 mFunctions->programUniformMatrix2x3fv(mProgramID, uniLoc(location), count, transpose,
405 value);
406 }
407 else
408 {
409 mStateManager->useProgram(mProgramID);
410 mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
411 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500412}
413
414void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
415{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800416 if (mFunctions->programUniformMatrix3x2fv != nullptr)
417 {
418 mFunctions->programUniformMatrix3x2fv(mProgramID, uniLoc(location), count, transpose,
419 value);
420 }
421 else
422 {
423 mStateManager->useProgram(mProgramID);
424 mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
425 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500426}
427
428void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
429{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800430 if (mFunctions->programUniformMatrix2x4fv != nullptr)
431 {
432 mFunctions->programUniformMatrix2x4fv(mProgramID, uniLoc(location), count, transpose,
433 value);
434 }
435 else
436 {
437 mStateManager->useProgram(mProgramID);
438 mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
439 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500440}
441
442void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
443{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800444 if (mFunctions->programUniformMatrix4x2fv != nullptr)
445 {
446 mFunctions->programUniformMatrix4x2fv(mProgramID, uniLoc(location), count, transpose,
447 value);
448 }
449 else
450 {
451 mStateManager->useProgram(mProgramID);
452 mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
453 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500454}
455
456void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
457{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800458 if (mFunctions->programUniformMatrix3x4fv != nullptr)
459 {
460 mFunctions->programUniformMatrix3x4fv(mProgramID, uniLoc(location), count, transpose,
461 value);
462 }
463 else
464 {
465 mStateManager->useProgram(mProgramID);
466 mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
467 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500468}
469
470void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
471{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800472 if (mFunctions->programUniformMatrix4x3fv != nullptr)
473 {
474 mFunctions->programUniformMatrix4x3fv(mProgramID, uniLoc(location), count, transpose,
475 value);
476 }
477 else
478 {
479 mStateManager->useProgram(mProgramID);
480 mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
481 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500482}
483
Geoff Lang5d124a62015-09-15 13:03:27 -0400484void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
485{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400486 // Lazy init
487 if (mUniformBlockRealLocationMap.empty())
488 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400489 mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
490 for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill4a3c2342015-10-08 12:58:45 -0400491 {
492 const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex();
493 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str());
494 mUniformBlockRealLocationMap.push_back(blockIndex);
495 }
496 }
497
498 GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
499 if (realBlockIndex != GL_INVALID_INDEX)
500 {
501 mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
502 }
Geoff Lang5d124a62015-09-15 13:03:27 -0400503}
504
Geoff Langb1f435e2015-02-20 10:01:01 -0500505GLuint ProgramGL::getProgramID() const
506{
507 return mProgramID;
508}
509
Jamie Madill4a3c2342015-10-08 12:58:45 -0400510bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400511{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400512 ASSERT(mProgramID != 0u);
Geoff Lang5d124a62015-09-15 13:03:27 -0400513
Jamie Madill4a3c2342015-10-08 12:58:45 -0400514 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str());
515 if (blockIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400516 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400517 *sizeOut = 0;
518 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400519 }
520
Jamie Madill4a3c2342015-10-08 12:58:45 -0400521 GLint dataSize = 0;
522 mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
523 &dataSize);
524 *sizeOut = static_cast<size_t>(dataSize);
525 return true;
526}
527
528bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName,
529 sh::BlockMemberInfo *memberInfoOut) const
530{
531 GLuint uniformIndex;
532 const GLchar *memberNameGLStr = memberUniformName.c_str();
533 mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
534
535 if (uniformIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400536 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400537 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
538 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400539 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400540
541 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
542 &memberInfoOut->offset);
543 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
544 &memberInfoOut->arrayStride);
545 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
546 &memberInfoOut->matrixStride);
547
548 // TODO(jmadill): possibly determine this at the gl::Program level.
549 GLint isRowMajorMatrix = 0;
550 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
551 &isRowMajorMatrix);
552 memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
553 return true;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400554}
Jamie Madill4a3c2342015-10-08 12:58:45 -0400555
Sami Väisänen46eaa942016-06-29 10:26:37 +0300556void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
557 GLenum genMode,
558 GLint components,
559 const GLfloat *coeffs)
560{
561 ASSERT(mEnablePathRendering);
562
563 for (const auto &input : mPathRenderingFragmentInputs)
564 {
565 if (input.name == inputName)
566 {
567 mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
568 components, coeffs);
569 ASSERT(mFunctions->getError() == GL_NO_ERROR);
570 return;
571 }
572 }
573
574}
575
Geoff Lang65a0be92015-10-02 09:57:30 -0400576void ProgramGL::preLink()
577{
578 // Reset the program state
579 mUniformRealLocationMap.clear();
580 mUniformBlockRealLocationMap.clear();
Sami Väisänen46eaa942016-06-29 10:26:37 +0300581 mPathRenderingFragmentInputs.clear();
Geoff Lang65a0be92015-10-02 09:57:30 -0400582}
583
584bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
585{
586 GLint linkStatus = GL_FALSE;
587 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
588 if (linkStatus == GL_FALSE)
589 {
590 // Linking failed, put the error into the info log
591 GLint infoLogLength = 0;
592 mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
593
Geoff Lang65a0be92015-10-02 09:57:30 -0400594 // Info log length includes the null terminator, so 1 means that the info log is an empty
595 // string.
596 if (infoLogLength > 1)
597 {
598 std::vector<char> buf(infoLogLength);
599 mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
600
601 mFunctions->deleteProgram(mProgramID);
602 mProgramID = 0;
603
604 infoLog << buf.data();
605
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500606 WARN() << "Program link failed unexpectedly: " << buf.data();
Geoff Lang65a0be92015-10-02 09:57:30 -0400607 }
608 else
609 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500610 WARN() << "Program link failed unexpectedly with no info log.";
Geoff Lang65a0be92015-10-02 09:57:30 -0400611 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400612
613 // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
614 return false;
615 }
616
617 return true;
618}
619
620void ProgramGL::postLink()
621{
622 // Query the uniform information
623 ASSERT(mUniformRealLocationMap.empty());
Jamie Madill48ef11b2016-04-27 15:21:52 -0400624 const auto &uniformLocations = mState.getUniformLocations();
625 const auto &uniforms = mState.getUniforms();
Geoff Lang65a0be92015-10-02 09:57:30 -0400626 mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
627 for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
628 {
629 const auto &entry = uniformLocations[uniformLocation];
630 if (!entry.used)
631 {
632 continue;
633 }
634
635 // From the spec:
636 // "Locations for sequential array indices are not required to be sequential."
637 const gl::LinkedUniform &uniform = uniforms[entry.index];
638 std::stringstream fullNameStr;
639 fullNameStr << uniform.name;
640 if (uniform.isArray())
641 {
642 fullNameStr << "[" << entry.element << "]";
643 }
644 const std::string &fullName = fullNameStr.str();
645
646 GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
647 mUniformRealLocationMap[uniformLocation] = realLocation;
648 }
649
Sami Väisänen46eaa942016-06-29 10:26:37 +0300650 // Discover CHROMIUM_path_rendering fragment inputs if enabled.
651 if (!mEnablePathRendering)
652 return;
653
654 GLint numFragmentInputs = 0;
655 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
656 &numFragmentInputs);
657 if (numFragmentInputs <= 0)
658 return;
659
660 GLint maxNameLength = 0;
661 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
662 &maxNameLength);
663 ASSERT(maxNameLength);
664
665 for (GLint i = 0; i < numFragmentInputs; ++i)
666 {
667 std::string name;
668 name.resize(maxNameLength);
669
670 GLsizei nameLen = 0;
671 mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
672 &nameLen, &name[0]);
673 name.resize(nameLen);
674
675 // Ignore built-ins
676 if (angle::BeginsWith(name, "gl_"))
677 continue;
678
679 const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
680 GLint queryResults[ArraySize(kQueryProperties)];
681 GLsizei queryLength = 0;
682
Geoff Lang3f6a3982016-07-15 15:20:45 -0400683 mFunctions->getProgramResourceiv(
684 mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
685 kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
686 queryResults);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300687
Olli Etuahoe3191712016-07-18 16:01:10 +0300688 ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300689
Geoff Lang3f6a3982016-07-15 15:20:45 -0400690 PathRenderingFragmentInput baseElementInput;
691 baseElementInput.name = name;
692 baseElementInput.location = queryResults[0];
693 mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300694
695 // If the input is an array it's denoted by [0] suffix on the variable
696 // name. We'll then create an entry per each array index where index > 0
697 if (angle::EndsWith(name, "[0]"))
698 {
699 // drop the suffix
700 name.resize(name.size() - 3);
701
702 const auto arraySize = queryResults[1];
703 const auto baseLocation = queryResults[0];
704
Geoff Lang3f6a3982016-07-15 15:20:45 -0400705 for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300706 {
Geoff Lang3f6a3982016-07-15 15:20:45 -0400707 PathRenderingFragmentInput arrayElementInput;
Corentin Wallez054f7ed2016-09-20 17:15:59 -0400708 arrayElementInput.name = name + "[" + ToString(arrayIndex) + "]";
Geoff Lang3f6a3982016-07-15 15:20:45 -0400709 arrayElementInput.location = baseLocation + arrayIndex;
710 mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300711 }
712 }
713 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400714}
715
Jamie Madill4a3c2342015-10-08 12:58:45 -0400716} // namespace rx