blob: ccdcd5d48005498a25f2161110bc8d47dca526aa [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),
Philippe Hamel40911192016-04-07 16:45:50 -040038 mProgramID(0)
Geoff Langb1f435e2015-02-20 10:01:01 -050039{
40 ASSERT(mFunctions);
41 ASSERT(mStateManager);
Geoff Lang0ca53782015-05-07 13:49:39 -040042
43 mProgramID = mFunctions->createProgram();
Geoff Langb1f435e2015-02-20 10:01:01 -050044}
Geoff Langf9a6f082015-01-22 13:32:49 -050045
46ProgramGL::~ProgramGL()
Geoff Langb1f435e2015-02-20 10:01:01 -050047{
Geoff Lang0ca53782015-05-07 13:49:39 -040048 mFunctions->deleteProgram(mProgramID);
49 mProgramID = 0;
Geoff Langb1f435e2015-02-20 10:01:01 -050050}
Geoff Langf9a6f082015-01-22 13:32:49 -050051
Jamie Madillc564c072017-06-01 12:45:42 -040052LinkResult ProgramGL::load(const gl::Context *context,
Jamie Madilla7d12dc2016-12-13 15:08:19 -050053 gl::InfoLog &infoLog,
54 gl::BinaryInputStream *stream)
Geoff Langf9a6f082015-01-22 13:32:49 -050055{
Geoff Lang65a0be92015-10-02 09:57:30 -040056 preLink();
57
58 // Read the binary format, size and blob
59 GLenum binaryFormat = stream->readInt<GLenum>();
60 GLint binaryLength = stream->readInt<GLint>();
61 const uint8_t *binary = stream->data() + stream->offset();
62 stream->skip(binaryLength);
63
64 // Load the binary
65 mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength);
66
67 // Verify that the program linked
68 if (!checkLinkStatus(infoLog))
69 {
Jamie Madillb0a838b2016-11-13 20:02:12 -050070 return false;
Geoff Lang65a0be92015-10-02 09:57:30 -040071 }
72
73 postLink();
74
Jamie Madilla7d12dc2016-12-13 15:08:19 -050075 // Re-apply UBO bindings to work around driver bugs.
Jamie Madillc564c072017-06-01 12:45:42 -040076 const WorkaroundsGL &workaroundsGL = GetImplAs<ContextGL>(context)->getWorkaroundsGL();
Jamie Madilla7d12dc2016-12-13 15:08:19 -050077 if (workaroundsGL.reapplyUBOBindingsAfterLoadingBinaryProgram)
78 {
Jamie Madill6de51852017-04-12 09:53:01 -040079 for (size_t bindingIndex : mState.getActiveUniformBlockBindingsMask())
Jamie Madilla7d12dc2016-12-13 15:08:19 -050080 {
Jamie Madill6de51852017-04-12 09:53:01 -040081 GLuint uintIndex = static_cast<GLuint>(bindingIndex);
82 setUniformBlockBinding(uintIndex, mState.getUniformBlockBinding(uintIndex));
Jamie Madilla7d12dc2016-12-13 15:08:19 -050083 }
84 }
85
Jamie Madillb0a838b2016-11-13 20:02:12 -050086 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -050087}
88
89gl::Error ProgramGL::save(gl::BinaryOutputStream *stream)
90{
Geoff Lang65a0be92015-10-02 09:57:30 -040091 GLint binaryLength = 0;
92 mFunctions->getProgramiv(mProgramID, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
93
94 std::vector<uint8_t> binary(binaryLength);
95 GLenum binaryFormat = GL_NONE;
96 mFunctions->getProgramBinary(mProgramID, binaryLength, &binaryLength, &binaryFormat,
97 &binary[0]);
98
99 stream->writeInt(binaryFormat);
100 stream->writeInt(binaryLength);
101 stream->writeBytes(&binary[0], binaryLength);
102
He Yunchaoacd18982017-01-04 10:46:42 +0800103 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500104}
105
Geoff Langc5629752015-12-07 16:29:04 -0500106void ProgramGL::setBinaryRetrievableHint(bool retrievable)
107{
Geoff Lang65a0be92015-10-02 09:57:30 -0400108 // glProgramParameteri isn't always available on ES backends.
109 if (mFunctions->programParameteri)
110 {
111 mFunctions->programParameteri(mProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT,
112 retrievable ? GL_TRUE : GL_FALSE);
113 }
Geoff Langc5629752015-12-07 16:29:04 -0500114}
115
Yunchao He61afff12017-03-14 15:34:03 +0800116void ProgramGL::setSeparable(bool separable)
117{
118 mFunctions->programParameteri(mProgramID, GL_PROGRAM_SEPARABLE, separable ? GL_TRUE : GL_FALSE);
119}
120
Jamie Madillc564c072017-06-01 12:45:42 -0400121LinkResult ProgramGL::link(const gl::Context *context,
Jamie Madill192745a2016-12-22 15:58:21 -0500122 const gl::VaryingPacking &packing,
123 gl::InfoLog &infoLog)
Geoff Langf9a6f082015-01-22 13:32:49 -0500124{
Geoff Lang65a0be92015-10-02 09:57:30 -0400125 preLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500126
Martin Radev4c4c8e72016-08-04 12:25:34 +0300127 if (mState.getAttachedComputeShader())
Geoff Lang1a683462015-09-29 15:09:59 -0400128 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300129 const ShaderGL *computeShaderGL = GetImplAs<ShaderGL>(mState.getAttachedComputeShader());
Geoff Lang1a683462015-09-29 15:09:59 -0400130
Martin Radev4c4c8e72016-08-04 12:25:34 +0300131 mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID());
132
133 // Link and verify
134 mFunctions->linkProgram(mProgramID);
135
136 // Detach the shaders
137 mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID());
Geoff Lang1a683462015-09-29 15:09:59 -0400138 }
139 else
140 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300141 // Set the transform feedback state
142 std::vector<const GLchar *> transformFeedbackVaryings;
143 for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
Geoff Lang1528e562015-08-24 15:10:58 -0400144 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300145 transformFeedbackVaryings.push_back(tfVarying.c_str());
Geoff Lang1528e562015-08-24 15:10:58 -0400146 }
147
Martin Radev4c4c8e72016-08-04 12:25:34 +0300148 if (transformFeedbackVaryings.empty())
149 {
150 if (mFunctions->transformFeedbackVaryings)
151 {
152 mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
153 mState.getTransformFeedbackBufferMode());
154 }
155 }
156 else
157 {
158 ASSERT(mFunctions->transformFeedbackVaryings);
159 mFunctions->transformFeedbackVaryings(
160 mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()),
161 &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
162 }
163
164 const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mState.getAttachedVertexShader());
165 const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader());
166
167 // Attach the shaders
168 mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
169 mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
170
171 // Bind attribute locations to match the GL layer.
172 for (const sh::Attribute &attribute : mState.getAttributes())
173 {
Corentin Wallez6c1cbf52016-11-23 12:44:35 -0500174 if (!attribute.staticUse || attribute.isBuiltIn())
Martin Radev4c4c8e72016-08-04 12:25:34 +0300175 {
176 continue;
177 }
178
179 mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.name.c_str());
180 }
181
182 // Link and verify
183 mFunctions->linkProgram(mProgramID);
184
185 // Detach the shaders
186 mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
187 mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
Geoff Lang1528e562015-08-24 15:10:58 -0400188 }
189
Geoff Lang0ca53782015-05-07 13:49:39 -0400190 // Verify the link
Geoff Lang65a0be92015-10-02 09:57:30 -0400191 if (!checkLinkStatus(infoLog))
Geoff Langb1f435e2015-02-20 10:01:01 -0500192 {
Jamie Madillb0a838b2016-11-13 20:02:12 -0500193 return false;
Geoff Langb1f435e2015-02-20 10:01:01 -0500194 }
195
Philippe Hamel40911192016-04-07 16:45:50 -0400196 if (mWorkarounds.alwaysCallUseProgramAfterLink)
197 {
198 mStateManager->forceUseProgram(mProgramID);
199 }
200
Geoff Lang65a0be92015-10-02 09:57:30 -0400201 postLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500202
Jamie Madillb0a838b2016-11-13 20:02:12 -0500203 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -0500204}
205
Jamie Madill36cfd6a2015-08-18 10:46:20 -0400206GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
207{
208 // TODO(jmadill): implement validate
209 return true;
210}
211
Geoff Langf9a6f082015-01-22 13:32:49 -0500212void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
213{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800214 if (mFunctions->programUniform1fv != nullptr)
215 {
216 mFunctions->programUniform1fv(mProgramID, uniLoc(location), count, v);
217 }
218 else
219 {
220 mStateManager->useProgram(mProgramID);
221 mFunctions->uniform1fv(uniLoc(location), count, v);
222 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500223}
224
225void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
226{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800227 if (mFunctions->programUniform2fv != nullptr)
228 {
229 mFunctions->programUniform2fv(mProgramID, uniLoc(location), count, v);
230 }
231 else
232 {
233 mStateManager->useProgram(mProgramID);
234 mFunctions->uniform2fv(uniLoc(location), count, v);
235 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500236}
237
238void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
239{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800240 if (mFunctions->programUniform3fv != nullptr)
241 {
242 mFunctions->programUniform3fv(mProgramID, uniLoc(location), count, v);
243 }
244 else
245 {
246 mStateManager->useProgram(mProgramID);
247 mFunctions->uniform3fv(uniLoc(location), count, v);
248 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500249}
250
251void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
252{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800253 if (mFunctions->programUniform4fv != nullptr)
254 {
255 mFunctions->programUniform4fv(mProgramID, uniLoc(location), count, v);
256 }
257 else
258 {
259 mStateManager->useProgram(mProgramID);
260 mFunctions->uniform4fv(uniLoc(location), count, v);
261 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500262}
263
264void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
265{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800266 if (mFunctions->programUniform1iv != nullptr)
267 {
268 mFunctions->programUniform1iv(mProgramID, uniLoc(location), count, v);
269 }
270 else
271 {
272 mStateManager->useProgram(mProgramID);
273 mFunctions->uniform1iv(uniLoc(location), count, v);
274 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500275}
276
277void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
278{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800279 if (mFunctions->programUniform2iv != nullptr)
280 {
281 mFunctions->programUniform2iv(mProgramID, uniLoc(location), count, v);
282 }
283 else
284 {
285 mStateManager->useProgram(mProgramID);
286 mFunctions->uniform2iv(uniLoc(location), count, v);
287 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500288}
289
290void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
291{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800292 if (mFunctions->programUniform3iv != nullptr)
293 {
294 mFunctions->programUniform3iv(mProgramID, uniLoc(location), count, v);
295 }
296 else
297 {
298 mStateManager->useProgram(mProgramID);
299 mFunctions->uniform3iv(uniLoc(location), count, v);
300 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500301}
302
303void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
304{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800305 if (mFunctions->programUniform4iv != nullptr)
306 {
307 mFunctions->programUniform4iv(mProgramID, uniLoc(location), count, v);
308 }
309 else
310 {
311 mStateManager->useProgram(mProgramID);
312 mFunctions->uniform4iv(uniLoc(location), count, v);
313 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500314}
315
316void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
317{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800318 if (mFunctions->programUniform1uiv != nullptr)
319 {
320 mFunctions->programUniform1uiv(mProgramID, uniLoc(location), count, v);
321 }
322 else
323 {
324 mStateManager->useProgram(mProgramID);
325 mFunctions->uniform1uiv(uniLoc(location), count, v);
326 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500327}
328
329void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
330{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800331 if (mFunctions->programUniform2uiv != nullptr)
332 {
333 mFunctions->programUniform2uiv(mProgramID, uniLoc(location), count, v);
334 }
335 else
336 {
337 mStateManager->useProgram(mProgramID);
338 mFunctions->uniform2uiv(uniLoc(location), count, v);
339 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500340}
341
342void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
343{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800344 if (mFunctions->programUniform3uiv != nullptr)
345 {
346 mFunctions->programUniform3uiv(mProgramID, uniLoc(location), count, v);
347 }
348 else
349 {
350 mStateManager->useProgram(mProgramID);
351 mFunctions->uniform3uiv(uniLoc(location), count, v);
352 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500353}
354
355void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
356{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800357 if (mFunctions->programUniform4uiv != nullptr)
358 {
359 mFunctions->programUniform4uiv(mProgramID, uniLoc(location), count, v);
360 }
361 else
362 {
363 mStateManager->useProgram(mProgramID);
364 mFunctions->uniform4uiv(uniLoc(location), count, v);
365 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500366}
367
368void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
369{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800370 if (mFunctions->programUniformMatrix2fv != nullptr)
371 {
372 mFunctions->programUniformMatrix2fv(mProgramID, uniLoc(location), count, transpose, value);
373 }
374 else
375 {
376 mStateManager->useProgram(mProgramID);
377 mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
378 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500379}
380
381void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
382{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800383 if (mFunctions->programUniformMatrix3fv != nullptr)
384 {
385 mFunctions->programUniformMatrix3fv(mProgramID, uniLoc(location), count, transpose, value);
386 }
387 else
388 {
389 mStateManager->useProgram(mProgramID);
390 mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
391 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500392}
393
394void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
395{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800396 if (mFunctions->programUniformMatrix4fv != nullptr)
397 {
398 mFunctions->programUniformMatrix4fv(mProgramID, uniLoc(location), count, transpose, value);
399 }
400 else
401 {
402 mStateManager->useProgram(mProgramID);
403 mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
404 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500405}
406
407void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
408{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800409 if (mFunctions->programUniformMatrix2x3fv != nullptr)
410 {
411 mFunctions->programUniformMatrix2x3fv(mProgramID, uniLoc(location), count, transpose,
412 value);
413 }
414 else
415 {
416 mStateManager->useProgram(mProgramID);
417 mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
418 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500419}
420
421void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
422{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800423 if (mFunctions->programUniformMatrix3x2fv != nullptr)
424 {
425 mFunctions->programUniformMatrix3x2fv(mProgramID, uniLoc(location), count, transpose,
426 value);
427 }
428 else
429 {
430 mStateManager->useProgram(mProgramID);
431 mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
432 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500433}
434
435void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
436{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800437 if (mFunctions->programUniformMatrix2x4fv != nullptr)
438 {
439 mFunctions->programUniformMatrix2x4fv(mProgramID, uniLoc(location), count, transpose,
440 value);
441 }
442 else
443 {
444 mStateManager->useProgram(mProgramID);
445 mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
446 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500447}
448
449void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
450{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800451 if (mFunctions->programUniformMatrix4x2fv != nullptr)
452 {
453 mFunctions->programUniformMatrix4x2fv(mProgramID, uniLoc(location), count, transpose,
454 value);
455 }
456 else
457 {
458 mStateManager->useProgram(mProgramID);
459 mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
460 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500461}
462
463void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
464{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800465 if (mFunctions->programUniformMatrix3x4fv != nullptr)
466 {
467 mFunctions->programUniformMatrix3x4fv(mProgramID, uniLoc(location), count, transpose,
468 value);
469 }
470 else
471 {
472 mStateManager->useProgram(mProgramID);
473 mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
474 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500475}
476
477void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
478{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800479 if (mFunctions->programUniformMatrix4x3fv != nullptr)
480 {
481 mFunctions->programUniformMatrix4x3fv(mProgramID, uniLoc(location), count, transpose,
482 value);
483 }
484 else
485 {
486 mStateManager->useProgram(mProgramID);
487 mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
488 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500489}
490
Geoff Lang5d124a62015-09-15 13:03:27 -0400491void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
492{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400493 // Lazy init
494 if (mUniformBlockRealLocationMap.empty())
495 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400496 mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
497 for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill4a3c2342015-10-08 12:58:45 -0400498 {
499 const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex();
500 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str());
501 mUniformBlockRealLocationMap.push_back(blockIndex);
502 }
503 }
504
505 GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
506 if (realBlockIndex != GL_INVALID_INDEX)
507 {
508 mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
509 }
Geoff Lang5d124a62015-09-15 13:03:27 -0400510}
511
Geoff Langb1f435e2015-02-20 10:01:01 -0500512GLuint ProgramGL::getProgramID() const
513{
514 return mProgramID;
515}
516
Jamie Madill4a3c2342015-10-08 12:58:45 -0400517bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400518{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400519 ASSERT(mProgramID != 0u);
Geoff Lang5d124a62015-09-15 13:03:27 -0400520
Jamie Madill4a3c2342015-10-08 12:58:45 -0400521 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str());
522 if (blockIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400523 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400524 *sizeOut = 0;
525 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400526 }
527
Jamie Madill4a3c2342015-10-08 12:58:45 -0400528 GLint dataSize = 0;
529 mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
530 &dataSize);
531 *sizeOut = static_cast<size_t>(dataSize);
532 return true;
533}
534
535bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName,
536 sh::BlockMemberInfo *memberInfoOut) const
537{
538 GLuint uniformIndex;
539 const GLchar *memberNameGLStr = memberUniformName.c_str();
540 mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
541
542 if (uniformIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400543 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400544 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
545 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400546 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400547
548 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
549 &memberInfoOut->offset);
550 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
551 &memberInfoOut->arrayStride);
552 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
553 &memberInfoOut->matrixStride);
554
555 // TODO(jmadill): possibly determine this at the gl::Program level.
556 GLint isRowMajorMatrix = 0;
557 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
558 &isRowMajorMatrix);
559 memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
560 return true;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400561}
Jamie Madill4a3c2342015-10-08 12:58:45 -0400562
Sami Väisänen46eaa942016-06-29 10:26:37 +0300563void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
564 GLenum genMode,
565 GLint components,
566 const GLfloat *coeffs)
567{
568 ASSERT(mEnablePathRendering);
569
570 for (const auto &input : mPathRenderingFragmentInputs)
571 {
572 if (input.name == inputName)
573 {
574 mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
575 components, coeffs);
576 ASSERT(mFunctions->getError() == GL_NO_ERROR);
577 return;
578 }
579 }
580
581}
582
Geoff Lang65a0be92015-10-02 09:57:30 -0400583void ProgramGL::preLink()
584{
585 // Reset the program state
586 mUniformRealLocationMap.clear();
587 mUniformBlockRealLocationMap.clear();
Sami Väisänen46eaa942016-06-29 10:26:37 +0300588 mPathRenderingFragmentInputs.clear();
Geoff Lang65a0be92015-10-02 09:57:30 -0400589}
590
591bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
592{
593 GLint linkStatus = GL_FALSE;
594 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
595 if (linkStatus == GL_FALSE)
596 {
597 // Linking failed, put the error into the info log
598 GLint infoLogLength = 0;
599 mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
600
Geoff Lang65a0be92015-10-02 09:57:30 -0400601 // Info log length includes the null terminator, so 1 means that the info log is an empty
602 // string.
603 if (infoLogLength > 1)
604 {
605 std::vector<char> buf(infoLogLength);
606 mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
607
608 mFunctions->deleteProgram(mProgramID);
609 mProgramID = 0;
610
611 infoLog << buf.data();
612
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500613 WARN() << "Program link failed unexpectedly: " << buf.data();
Geoff Lang65a0be92015-10-02 09:57:30 -0400614 }
615 else
616 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500617 WARN() << "Program link failed unexpectedly with no info log.";
Geoff Lang65a0be92015-10-02 09:57:30 -0400618 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400619
620 // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
621 return false;
622 }
623
624 return true;
625}
626
627void ProgramGL::postLink()
628{
629 // Query the uniform information
630 ASSERT(mUniformRealLocationMap.empty());
Jamie Madill48ef11b2016-04-27 15:21:52 -0400631 const auto &uniformLocations = mState.getUniformLocations();
632 const auto &uniforms = mState.getUniforms();
Geoff Lang65a0be92015-10-02 09:57:30 -0400633 mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
634 for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
635 {
636 const auto &entry = uniformLocations[uniformLocation];
637 if (!entry.used)
638 {
639 continue;
640 }
641
642 // From the spec:
643 // "Locations for sequential array indices are not required to be sequential."
644 const gl::LinkedUniform &uniform = uniforms[entry.index];
645 std::stringstream fullNameStr;
646 fullNameStr << uniform.name;
647 if (uniform.isArray())
648 {
649 fullNameStr << "[" << entry.element << "]";
650 }
651 const std::string &fullName = fullNameStr.str();
652
653 GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
654 mUniformRealLocationMap[uniformLocation] = realLocation;
655 }
656
Sami Väisänen46eaa942016-06-29 10:26:37 +0300657 // Discover CHROMIUM_path_rendering fragment inputs if enabled.
658 if (!mEnablePathRendering)
659 return;
660
661 GLint numFragmentInputs = 0;
662 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
663 &numFragmentInputs);
664 if (numFragmentInputs <= 0)
665 return;
666
667 GLint maxNameLength = 0;
668 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
669 &maxNameLength);
670 ASSERT(maxNameLength);
671
672 for (GLint i = 0; i < numFragmentInputs; ++i)
673 {
674 std::string name;
675 name.resize(maxNameLength);
676
677 GLsizei nameLen = 0;
678 mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
679 &nameLen, &name[0]);
680 name.resize(nameLen);
681
682 // Ignore built-ins
683 if (angle::BeginsWith(name, "gl_"))
684 continue;
685
686 const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
687 GLint queryResults[ArraySize(kQueryProperties)];
688 GLsizei queryLength = 0;
689
Geoff Lang3f6a3982016-07-15 15:20:45 -0400690 mFunctions->getProgramResourceiv(
691 mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
692 kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
693 queryResults);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300694
Olli Etuahoe3191712016-07-18 16:01:10 +0300695 ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300696
Geoff Lang3f6a3982016-07-15 15:20:45 -0400697 PathRenderingFragmentInput baseElementInput;
698 baseElementInput.name = name;
699 baseElementInput.location = queryResults[0];
700 mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300701
702 // If the input is an array it's denoted by [0] suffix on the variable
703 // name. We'll then create an entry per each array index where index > 0
704 if (angle::EndsWith(name, "[0]"))
705 {
706 // drop the suffix
707 name.resize(name.size() - 3);
708
709 const auto arraySize = queryResults[1];
710 const auto baseLocation = queryResults[0];
711
Geoff Lang3f6a3982016-07-15 15:20:45 -0400712 for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300713 {
Geoff Lang3f6a3982016-07-15 15:20:45 -0400714 PathRenderingFragmentInput arrayElementInput;
Corentin Wallez054f7ed2016-09-20 17:15:59 -0400715 arrayElementInput.name = name + "[" + ToString(arrayIndex) + "]";
Geoff Lang3f6a3982016-07-15 15:20:45 -0400716 arrayElementInput.location = baseLocation + arrayIndex;
717 mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300718 }
719 }
720 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400721}
722
Jamie Madill4a3c2342015-10-08 12:58:45 -0400723} // namespace rx