blob: 3c1fe40db8650b2ea49cb5051dc1cd8135e7a682 [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
Sami Väisänen46eaa942016-06-29 10:26:37 +030011#include "common/angleutils.h"
Jamie Madillc564c072017-06-01 12:45:42 -040012#include "common/bitset_utils.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 Madillc564c072017-06-01 12:45:42 -040016#include "libANGLE/Context.h"
17#include "libANGLE/Uniform.h"
Jamie Madilla7d12dc2016-12-13 15:08:19 -050018#include "libANGLE/renderer/gl/ContextGL.h"
Geoff Langb1f435e2015-02-20 10:01:01 -050019#include "libANGLE/renderer/gl/FunctionsGL.h"
20#include "libANGLE/renderer/gl/ShaderGL.h"
21#include "libANGLE/renderer/gl/StateManagerGL.h"
Philippe Hamel40911192016-04-07 16:45:50 -040022#include "libANGLE/renderer/gl/WorkaroundsGL.h"
unknownb4a3af22015-11-25 15:02:51 -050023#include "platform/Platform.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050024
25namespace rx
26{
27
Jamie Madill48ef11b2016-04-27 15:21:52 -040028ProgramGL::ProgramGL(const gl::ProgramState &data,
Jamie Madill5c6b7bf2015-08-17 12:53:35 -040029 const FunctionsGL *functions,
Philippe Hamel40911192016-04-07 16:45:50 -040030 const WorkaroundsGL &workarounds,
Sami Väisänen46eaa942016-06-29 10:26:37 +030031 StateManagerGL *stateManager,
32 bool enablePathRendering)
Philippe Hamel40911192016-04-07 16:45:50 -040033 : ProgramImpl(data),
34 mFunctions(functions),
35 mWorkarounds(workarounds),
36 mStateManager(stateManager),
Sami Väisänen46eaa942016-06-29 10:26:37 +030037 mEnablePathRendering(enablePathRendering),
Martin Radev4e619f52017-08-09 11:50:06 +030038 mMultiviewBaseViewLayerIndexUniformLocation(-1),
Philippe Hamel40911192016-04-07 16:45:50 -040039 mProgramID(0)
Geoff Langb1f435e2015-02-20 10:01:01 -050040{
41 ASSERT(mFunctions);
42 ASSERT(mStateManager);
Geoff Lang0ca53782015-05-07 13:49:39 -040043
44 mProgramID = mFunctions->createProgram();
Geoff Langb1f435e2015-02-20 10:01:01 -050045}
Geoff Langf9a6f082015-01-22 13:32:49 -050046
47ProgramGL::~ProgramGL()
Geoff Langb1f435e2015-02-20 10:01:01 -050048{
Geoff Lang0ca53782015-05-07 13:49:39 -040049 mFunctions->deleteProgram(mProgramID);
50 mProgramID = 0;
Geoff Langb1f435e2015-02-20 10:01:01 -050051}
Geoff Langf9a6f082015-01-22 13:32:49 -050052
Jamie Madill9cf9e872017-06-05 12:59:25 -040053gl::LinkResult ProgramGL::load(const gl::Context *context,
54 gl::InfoLog &infoLog,
55 gl::BinaryInputStream *stream)
Geoff Langf9a6f082015-01-22 13:32:49 -050056{
Geoff Lang65a0be92015-10-02 09:57:30 -040057 preLink();
58
59 // Read the binary format, size and blob
60 GLenum binaryFormat = stream->readInt<GLenum>();
61 GLint binaryLength = stream->readInt<GLint>();
62 const uint8_t *binary = stream->data() + stream->offset();
63 stream->skip(binaryLength);
64
65 // Load the binary
66 mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength);
67
68 // Verify that the program linked
69 if (!checkLinkStatus(infoLog))
70 {
Jamie Madillb0a838b2016-11-13 20:02:12 -050071 return false;
Geoff Lang65a0be92015-10-02 09:57:30 -040072 }
73
74 postLink();
Jamie Madill27a60632017-06-30 15:12:01 -040075 reapplyUBOBindingsIfNeeded(context);
Jamie Madilla7d12dc2016-12-13 15:08:19 -050076
Jamie Madillb0a838b2016-11-13 20:02:12 -050077 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -050078}
79
Jamie Madill27a60632017-06-30 15:12:01 -040080void ProgramGL::save(const gl::Context *context, gl::BinaryOutputStream *stream)
Geoff Langf9a6f082015-01-22 13:32:49 -050081{
Geoff Lang65a0be92015-10-02 09:57:30 -040082 GLint binaryLength = 0;
83 mFunctions->getProgramiv(mProgramID, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
84
85 std::vector<uint8_t> binary(binaryLength);
86 GLenum binaryFormat = GL_NONE;
87 mFunctions->getProgramBinary(mProgramID, binaryLength, &binaryLength, &binaryFormat,
88 &binary[0]);
89
90 stream->writeInt(binaryFormat);
91 stream->writeInt(binaryLength);
92 stream->writeBytes(&binary[0], binaryLength);
Jamie Madill27a60632017-06-30 15:12:01 -040093
94 reapplyUBOBindingsIfNeeded(context);
95}
96
97void ProgramGL::reapplyUBOBindingsIfNeeded(const gl::Context *context)
98{
99 // Re-apply UBO bindings to work around driver bugs.
100 const WorkaroundsGL &workaroundsGL = GetImplAs<ContextGL>(context)->getWorkaroundsGL();
101 if (workaroundsGL.reapplyUBOBindingsAfterUsingBinaryProgram)
102 {
103 const auto &blocks = mState.getUniformBlocks();
104 for (size_t blockIndex : mState.getActiveUniformBlockBindingsMask())
105 {
106 setUniformBlockBinding(static_cast<GLuint>(blockIndex), blocks[blockIndex].binding);
107 }
108 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500109}
110
Geoff Langc5629752015-12-07 16:29:04 -0500111void ProgramGL::setBinaryRetrievableHint(bool retrievable)
112{
Geoff Lang65a0be92015-10-02 09:57:30 -0400113 // glProgramParameteri isn't always available on ES backends.
114 if (mFunctions->programParameteri)
115 {
116 mFunctions->programParameteri(mProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT,
117 retrievable ? GL_TRUE : GL_FALSE);
118 }
Geoff Langc5629752015-12-07 16:29:04 -0500119}
120
Yunchao He61afff12017-03-14 15:34:03 +0800121void ProgramGL::setSeparable(bool separable)
122{
123 mFunctions->programParameteri(mProgramID, GL_PROGRAM_SEPARABLE, separable ? GL_TRUE : GL_FALSE);
124}
125
Jamie Madill9cf9e872017-06-05 12:59:25 -0400126gl::LinkResult ProgramGL::link(const gl::Context *context,
127 const gl::VaryingPacking &packing,
128 gl::InfoLog &infoLog)
Geoff Langf9a6f082015-01-22 13:32:49 -0500129{
Geoff Lang65a0be92015-10-02 09:57:30 -0400130 preLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500131
Martin Radev4c4c8e72016-08-04 12:25:34 +0300132 if (mState.getAttachedComputeShader())
Geoff Lang1a683462015-09-29 15:09:59 -0400133 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300134 const ShaderGL *computeShaderGL = GetImplAs<ShaderGL>(mState.getAttachedComputeShader());
Geoff Lang1a683462015-09-29 15:09:59 -0400135
Martin Radev4c4c8e72016-08-04 12:25:34 +0300136 mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID());
137
138 // Link and verify
139 mFunctions->linkProgram(mProgramID);
140
141 // Detach the shaders
142 mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID());
Geoff Lang1a683462015-09-29 15:09:59 -0400143 }
144 else
145 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300146 // Set the transform feedback state
147 std::vector<const GLchar *> transformFeedbackVaryings;
148 for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
Geoff Lang1528e562015-08-24 15:10:58 -0400149 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300150 transformFeedbackVaryings.push_back(tfVarying.c_str());
Geoff Lang1528e562015-08-24 15:10:58 -0400151 }
152
Martin Radev4c4c8e72016-08-04 12:25:34 +0300153 if (transformFeedbackVaryings.empty())
154 {
155 if (mFunctions->transformFeedbackVaryings)
156 {
157 mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
158 mState.getTransformFeedbackBufferMode());
159 }
160 }
161 else
162 {
163 ASSERT(mFunctions->transformFeedbackVaryings);
164 mFunctions->transformFeedbackVaryings(
165 mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()),
166 &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
167 }
168
169 const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mState.getAttachedVertexShader());
170 const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader());
171
172 // Attach the shaders
173 mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
174 mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
175
176 // Bind attribute locations to match the GL layer.
177 for (const sh::Attribute &attribute : mState.getAttributes())
178 {
Corentin Wallez6c1cbf52016-11-23 12:44:35 -0500179 if (!attribute.staticUse || attribute.isBuiltIn())
Martin Radev4c4c8e72016-08-04 12:25:34 +0300180 {
181 continue;
182 }
183
184 mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.name.c_str());
185 }
186
187 // Link and verify
188 mFunctions->linkProgram(mProgramID);
189
190 // Detach the shaders
191 mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
192 mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
Geoff Lang1528e562015-08-24 15:10:58 -0400193 }
194
Geoff Lang0ca53782015-05-07 13:49:39 -0400195 // Verify the link
Geoff Lang65a0be92015-10-02 09:57:30 -0400196 if (!checkLinkStatus(infoLog))
Geoff Langb1f435e2015-02-20 10:01:01 -0500197 {
Jamie Madillb0a838b2016-11-13 20:02:12 -0500198 return false;
Geoff Langb1f435e2015-02-20 10:01:01 -0500199 }
200
Philippe Hamel40911192016-04-07 16:45:50 -0400201 if (mWorkarounds.alwaysCallUseProgramAfterLink)
202 {
203 mStateManager->forceUseProgram(mProgramID);
204 }
205
Geoff Lang65a0be92015-10-02 09:57:30 -0400206 postLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500207
Jamie Madillb0a838b2016-11-13 20:02:12 -0500208 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -0500209}
210
Jamie Madill36cfd6a2015-08-18 10:46:20 -0400211GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
212{
213 // TODO(jmadill): implement validate
214 return true;
215}
216
Geoff Langf9a6f082015-01-22 13:32:49 -0500217void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
218{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800219 if (mFunctions->programUniform1fv != nullptr)
220 {
221 mFunctions->programUniform1fv(mProgramID, uniLoc(location), count, v);
222 }
223 else
224 {
225 mStateManager->useProgram(mProgramID);
226 mFunctions->uniform1fv(uniLoc(location), count, v);
227 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500228}
229
230void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
231{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800232 if (mFunctions->programUniform2fv != nullptr)
233 {
234 mFunctions->programUniform2fv(mProgramID, uniLoc(location), count, v);
235 }
236 else
237 {
238 mStateManager->useProgram(mProgramID);
239 mFunctions->uniform2fv(uniLoc(location), count, v);
240 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500241}
242
243void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
244{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800245 if (mFunctions->programUniform3fv != nullptr)
246 {
247 mFunctions->programUniform3fv(mProgramID, uniLoc(location), count, v);
248 }
249 else
250 {
251 mStateManager->useProgram(mProgramID);
252 mFunctions->uniform3fv(uniLoc(location), count, v);
253 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500254}
255
256void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
257{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800258 if (mFunctions->programUniform4fv != nullptr)
259 {
260 mFunctions->programUniform4fv(mProgramID, uniLoc(location), count, v);
261 }
262 else
263 {
264 mStateManager->useProgram(mProgramID);
265 mFunctions->uniform4fv(uniLoc(location), count, v);
266 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500267}
268
269void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
270{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800271 if (mFunctions->programUniform1iv != nullptr)
272 {
273 mFunctions->programUniform1iv(mProgramID, uniLoc(location), count, v);
274 }
275 else
276 {
277 mStateManager->useProgram(mProgramID);
278 mFunctions->uniform1iv(uniLoc(location), count, v);
279 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500280}
281
282void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
283{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800284 if (mFunctions->programUniform2iv != nullptr)
285 {
286 mFunctions->programUniform2iv(mProgramID, uniLoc(location), count, v);
287 }
288 else
289 {
290 mStateManager->useProgram(mProgramID);
291 mFunctions->uniform2iv(uniLoc(location), count, v);
292 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500293}
294
295void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
296{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800297 if (mFunctions->programUniform3iv != nullptr)
298 {
299 mFunctions->programUniform3iv(mProgramID, uniLoc(location), count, v);
300 }
301 else
302 {
303 mStateManager->useProgram(mProgramID);
304 mFunctions->uniform3iv(uniLoc(location), count, v);
305 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500306}
307
308void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
309{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800310 if (mFunctions->programUniform4iv != nullptr)
311 {
312 mFunctions->programUniform4iv(mProgramID, uniLoc(location), count, v);
313 }
314 else
315 {
316 mStateManager->useProgram(mProgramID);
317 mFunctions->uniform4iv(uniLoc(location), count, v);
318 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500319}
320
321void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
322{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800323 if (mFunctions->programUniform1uiv != nullptr)
324 {
325 mFunctions->programUniform1uiv(mProgramID, uniLoc(location), count, v);
326 }
327 else
328 {
329 mStateManager->useProgram(mProgramID);
330 mFunctions->uniform1uiv(uniLoc(location), count, v);
331 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500332}
333
334void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
335{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800336 if (mFunctions->programUniform2uiv != nullptr)
337 {
338 mFunctions->programUniform2uiv(mProgramID, uniLoc(location), count, v);
339 }
340 else
341 {
342 mStateManager->useProgram(mProgramID);
343 mFunctions->uniform2uiv(uniLoc(location), count, v);
344 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500345}
346
347void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
348{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800349 if (mFunctions->programUniform3uiv != nullptr)
350 {
351 mFunctions->programUniform3uiv(mProgramID, uniLoc(location), count, v);
352 }
353 else
354 {
355 mStateManager->useProgram(mProgramID);
356 mFunctions->uniform3uiv(uniLoc(location), count, v);
357 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500358}
359
360void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
361{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800362 if (mFunctions->programUniform4uiv != nullptr)
363 {
364 mFunctions->programUniform4uiv(mProgramID, uniLoc(location), count, v);
365 }
366 else
367 {
368 mStateManager->useProgram(mProgramID);
369 mFunctions->uniform4uiv(uniLoc(location), count, v);
370 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500371}
372
373void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
374{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800375 if (mFunctions->programUniformMatrix2fv != nullptr)
376 {
377 mFunctions->programUniformMatrix2fv(mProgramID, uniLoc(location), count, transpose, value);
378 }
379 else
380 {
381 mStateManager->useProgram(mProgramID);
382 mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
383 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500384}
385
386void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
387{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800388 if (mFunctions->programUniformMatrix3fv != nullptr)
389 {
390 mFunctions->programUniformMatrix3fv(mProgramID, uniLoc(location), count, transpose, value);
391 }
392 else
393 {
394 mStateManager->useProgram(mProgramID);
395 mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
396 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500397}
398
399void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
400{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800401 if (mFunctions->programUniformMatrix4fv != nullptr)
402 {
403 mFunctions->programUniformMatrix4fv(mProgramID, uniLoc(location), count, transpose, value);
404 }
405 else
406 {
407 mStateManager->useProgram(mProgramID);
408 mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
409 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500410}
411
412void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
413{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800414 if (mFunctions->programUniformMatrix2x3fv != nullptr)
415 {
416 mFunctions->programUniformMatrix2x3fv(mProgramID, uniLoc(location), count, transpose,
417 value);
418 }
419 else
420 {
421 mStateManager->useProgram(mProgramID);
422 mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
423 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500424}
425
426void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
427{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800428 if (mFunctions->programUniformMatrix3x2fv != nullptr)
429 {
430 mFunctions->programUniformMatrix3x2fv(mProgramID, uniLoc(location), count, transpose,
431 value);
432 }
433 else
434 {
435 mStateManager->useProgram(mProgramID);
436 mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
437 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500438}
439
440void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
441{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800442 if (mFunctions->programUniformMatrix2x4fv != nullptr)
443 {
444 mFunctions->programUniformMatrix2x4fv(mProgramID, uniLoc(location), count, transpose,
445 value);
446 }
447 else
448 {
449 mStateManager->useProgram(mProgramID);
450 mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
451 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500452}
453
454void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
455{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800456 if (mFunctions->programUniformMatrix4x2fv != nullptr)
457 {
458 mFunctions->programUniformMatrix4x2fv(mProgramID, uniLoc(location), count, transpose,
459 value);
460 }
461 else
462 {
463 mStateManager->useProgram(mProgramID);
464 mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
465 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500466}
467
468void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
469{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800470 if (mFunctions->programUniformMatrix3x4fv != nullptr)
471 {
472 mFunctions->programUniformMatrix3x4fv(mProgramID, uniLoc(location), count, transpose,
473 value);
474 }
475 else
476 {
477 mStateManager->useProgram(mProgramID);
478 mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
479 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500480}
481
482void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
483{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800484 if (mFunctions->programUniformMatrix4x3fv != nullptr)
485 {
486 mFunctions->programUniformMatrix4x3fv(mProgramID, uniLoc(location), count, transpose,
487 value);
488 }
489 else
490 {
491 mStateManager->useProgram(mProgramID);
492 mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
493 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500494}
495
Geoff Lang5d124a62015-09-15 13:03:27 -0400496void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
497{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400498 // Lazy init
499 if (mUniformBlockRealLocationMap.empty())
500 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400501 mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
502 for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill4a3c2342015-10-08 12:58:45 -0400503 {
504 const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex();
505 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str());
506 mUniformBlockRealLocationMap.push_back(blockIndex);
507 }
508 }
509
510 GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
511 if (realBlockIndex != GL_INVALID_INDEX)
512 {
513 mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
514 }
Geoff Lang5d124a62015-09-15 13:03:27 -0400515}
516
Geoff Langb1f435e2015-02-20 10:01:01 -0500517GLuint ProgramGL::getProgramID() const
518{
519 return mProgramID;
520}
521
Jamie Madill4a3c2342015-10-08 12:58:45 -0400522bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400523{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400524 ASSERT(mProgramID != 0u);
Geoff Lang5d124a62015-09-15 13:03:27 -0400525
Jamie Madill4a3c2342015-10-08 12:58:45 -0400526 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str());
527 if (blockIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400528 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400529 *sizeOut = 0;
530 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400531 }
532
Jamie Madill4a3c2342015-10-08 12:58:45 -0400533 GLint dataSize = 0;
534 mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
535 &dataSize);
536 *sizeOut = static_cast<size_t>(dataSize);
537 return true;
538}
539
540bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName,
541 sh::BlockMemberInfo *memberInfoOut) const
542{
543 GLuint uniformIndex;
544 const GLchar *memberNameGLStr = memberUniformName.c_str();
545 mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
546
547 if (uniformIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400548 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400549 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
550 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400551 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400552
553 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
554 &memberInfoOut->offset);
555 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
556 &memberInfoOut->arrayStride);
557 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
558 &memberInfoOut->matrixStride);
559
560 // TODO(jmadill): possibly determine this at the gl::Program level.
561 GLint isRowMajorMatrix = 0;
562 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
563 &isRowMajorMatrix);
564 memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
565 return true;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400566}
Jamie Madill4a3c2342015-10-08 12:58:45 -0400567
Sami Väisänen46eaa942016-06-29 10:26:37 +0300568void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
569 GLenum genMode,
570 GLint components,
571 const GLfloat *coeffs)
572{
573 ASSERT(mEnablePathRendering);
574
575 for (const auto &input : mPathRenderingFragmentInputs)
576 {
577 if (input.name == inputName)
578 {
579 mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
580 components, coeffs);
581 ASSERT(mFunctions->getError() == GL_NO_ERROR);
582 return;
583 }
584 }
585
586}
587
Geoff Lang65a0be92015-10-02 09:57:30 -0400588void ProgramGL::preLink()
589{
590 // Reset the program state
591 mUniformRealLocationMap.clear();
592 mUniformBlockRealLocationMap.clear();
Sami Väisänen46eaa942016-06-29 10:26:37 +0300593 mPathRenderingFragmentInputs.clear();
Martin Radev4e619f52017-08-09 11:50:06 +0300594
595 mMultiviewBaseViewLayerIndexUniformLocation = -1;
Geoff Lang65a0be92015-10-02 09:57:30 -0400596}
597
598bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
599{
600 GLint linkStatus = GL_FALSE;
601 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
602 if (linkStatus == GL_FALSE)
603 {
604 // Linking failed, put the error into the info log
605 GLint infoLogLength = 0;
606 mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
607
Geoff Lang65a0be92015-10-02 09:57:30 -0400608 // Info log length includes the null terminator, so 1 means that the info log is an empty
609 // string.
610 if (infoLogLength > 1)
611 {
612 std::vector<char> buf(infoLogLength);
613 mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
614
615 mFunctions->deleteProgram(mProgramID);
616 mProgramID = 0;
617
618 infoLog << buf.data();
619
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500620 WARN() << "Program link failed unexpectedly: " << buf.data();
Geoff Lang65a0be92015-10-02 09:57:30 -0400621 }
622 else
623 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500624 WARN() << "Program link failed unexpectedly with no info log.";
Geoff Lang65a0be92015-10-02 09:57:30 -0400625 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400626
627 // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
628 return false;
629 }
630
631 return true;
632}
633
634void ProgramGL::postLink()
635{
636 // Query the uniform information
637 ASSERT(mUniformRealLocationMap.empty());
Jamie Madill48ef11b2016-04-27 15:21:52 -0400638 const auto &uniformLocations = mState.getUniformLocations();
639 const auto &uniforms = mState.getUniforms();
Geoff Lang65a0be92015-10-02 09:57:30 -0400640 mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
641 for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
642 {
643 const auto &entry = uniformLocations[uniformLocation];
644 if (!entry.used)
645 {
646 continue;
647 }
648
649 // From the spec:
650 // "Locations for sequential array indices are not required to be sequential."
651 const gl::LinkedUniform &uniform = uniforms[entry.index];
652 std::stringstream fullNameStr;
653 fullNameStr << uniform.name;
654 if (uniform.isArray())
655 {
656 fullNameStr << "[" << entry.element << "]";
657 }
658 const std::string &fullName = fullNameStr.str();
659
660 GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
661 mUniformRealLocationMap[uniformLocation] = realLocation;
662 }
663
Martin Radev4e619f52017-08-09 11:50:06 +0300664 if (mState.usesMultiview())
665 {
666 mMultiviewBaseViewLayerIndexUniformLocation =
667 mFunctions->getUniformLocation(mProgramID, "webgl_angle_multiviewBaseViewLayerIndex");
668 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
669 }
670
Sami Väisänen46eaa942016-06-29 10:26:37 +0300671 // Discover CHROMIUM_path_rendering fragment inputs if enabled.
672 if (!mEnablePathRendering)
673 return;
674
675 GLint numFragmentInputs = 0;
676 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
677 &numFragmentInputs);
678 if (numFragmentInputs <= 0)
679 return;
680
681 GLint maxNameLength = 0;
682 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
683 &maxNameLength);
684 ASSERT(maxNameLength);
685
686 for (GLint i = 0; i < numFragmentInputs; ++i)
687 {
688 std::string name;
689 name.resize(maxNameLength);
690
691 GLsizei nameLen = 0;
692 mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
693 &nameLen, &name[0]);
694 name.resize(nameLen);
695
696 // Ignore built-ins
697 if (angle::BeginsWith(name, "gl_"))
698 continue;
699
700 const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
701 GLint queryResults[ArraySize(kQueryProperties)];
702 GLsizei queryLength = 0;
703
Geoff Lang3f6a3982016-07-15 15:20:45 -0400704 mFunctions->getProgramResourceiv(
705 mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
706 kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
707 queryResults);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300708
Olli Etuahoe3191712016-07-18 16:01:10 +0300709 ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300710
Geoff Lang3f6a3982016-07-15 15:20:45 -0400711 PathRenderingFragmentInput baseElementInput;
712 baseElementInput.name = name;
713 baseElementInput.location = queryResults[0];
714 mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300715
716 // If the input is an array it's denoted by [0] suffix on the variable
717 // name. We'll then create an entry per each array index where index > 0
718 if (angle::EndsWith(name, "[0]"))
719 {
720 // drop the suffix
721 name.resize(name.size() - 3);
722
723 const auto arraySize = queryResults[1];
724 const auto baseLocation = queryResults[0];
725
Geoff Lang3f6a3982016-07-15 15:20:45 -0400726 for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300727 {
Geoff Lang3f6a3982016-07-15 15:20:45 -0400728 PathRenderingFragmentInput arrayElementInput;
Corentin Wallez054f7ed2016-09-20 17:15:59 -0400729 arrayElementInput.name = name + "[" + ToString(arrayIndex) + "]";
Geoff Lang3f6a3982016-07-15 15:20:45 -0400730 arrayElementInput.location = baseLocation + arrayIndex;
731 mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300732 }
733 }
734 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400735}
736
Martin Radev4e619f52017-08-09 11:50:06 +0300737void ProgramGL::enableSideBySideRenderingPath() const
738{
739 ASSERT(mState.usesMultiview());
740 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
741
742 ASSERT(mFunctions->programUniform1i != nullptr);
743 mFunctions->programUniform1i(mProgramID, mMultiviewBaseViewLayerIndexUniformLocation, -1);
744}
745
746void ProgramGL::enableLayeredRenderingPath(int baseViewIndex) const
747{
748 ASSERT(mState.usesMultiview());
749 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
750
751 ASSERT(mFunctions->programUniform1i != nullptr);
752 mFunctions->programUniform1i(mProgramID, mMultiviewBaseViewLayerIndexUniformLocation,
753 baseViewIndex);
754}
755
Jamie Madill4a3c2342015-10-08 12:58:45 -0400756} // namespace rx