blob: b3e55462bb65c4a66b3b6cb172442da64317f996 [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 Madill20e005b2017-04-07 14:19:22 -040011#include "common/bitset_utils.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 {
Jamie Madill6de51852017-04-12 09:53:01 -040078 for (size_t bindingIndex : mState.getActiveUniformBlockBindingsMask())
Jamie Madilla7d12dc2016-12-13 15:08:19 -050079 {
Jamie Madill6de51852017-04-12 09:53:01 -040080 GLuint uintIndex = static_cast<GLuint>(bindingIndex);
81 setUniformBlockBinding(uintIndex, mState.getUniformBlockBinding(uintIndex));
Jamie Madilla7d12dc2016-12-13 15:08:19 -050082 }
83 }
84
Jamie Madillb0a838b2016-11-13 20:02:12 -050085 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -050086}
87
88gl::Error ProgramGL::save(gl::BinaryOutputStream *stream)
89{
Geoff Lang65a0be92015-10-02 09:57:30 -040090 GLint binaryLength = 0;
91 mFunctions->getProgramiv(mProgramID, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
92
93 std::vector<uint8_t> binary(binaryLength);
94 GLenum binaryFormat = GL_NONE;
95 mFunctions->getProgramBinary(mProgramID, binaryLength, &binaryLength, &binaryFormat,
96 &binary[0]);
97
98 stream->writeInt(binaryFormat);
99 stream->writeInt(binaryLength);
100 stream->writeBytes(&binary[0], binaryLength);
101
He Yunchaoacd18982017-01-04 10:46:42 +0800102 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500103}
104
Geoff Langc5629752015-12-07 16:29:04 -0500105void ProgramGL::setBinaryRetrievableHint(bool retrievable)
106{
Geoff Lang65a0be92015-10-02 09:57:30 -0400107 // glProgramParameteri isn't always available on ES backends.
108 if (mFunctions->programParameteri)
109 {
110 mFunctions->programParameteri(mProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT,
111 retrievable ? GL_TRUE : GL_FALSE);
112 }
Geoff Langc5629752015-12-07 16:29:04 -0500113}
114
Yunchao He61afff12017-03-14 15:34:03 +0800115void ProgramGL::setSeparable(bool separable)
116{
117 mFunctions->programParameteri(mProgramID, GL_PROGRAM_SEPARABLE, separable ? GL_TRUE : GL_FALSE);
118}
119
Jamie Madill8ecf7f92017-01-13 17:29:52 -0500120LinkResult ProgramGL::link(ContextImpl *contextImpl,
Jamie Madill192745a2016-12-22 15:58:21 -0500121 const gl::VaryingPacking &packing,
122 gl::InfoLog &infoLog)
Geoff Langf9a6f082015-01-22 13:32:49 -0500123{
Geoff Lang65a0be92015-10-02 09:57:30 -0400124 preLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500125
Martin Radev4c4c8e72016-08-04 12:25:34 +0300126 if (mState.getAttachedComputeShader())
Geoff Lang1a683462015-09-29 15:09:59 -0400127 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300128 const ShaderGL *computeShaderGL = GetImplAs<ShaderGL>(mState.getAttachedComputeShader());
Geoff Lang1a683462015-09-29 15:09:59 -0400129
Martin Radev4c4c8e72016-08-04 12:25:34 +0300130 mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID());
131
132 // Link and verify
133 mFunctions->linkProgram(mProgramID);
134
135 // Detach the shaders
136 mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID());
Geoff Lang1a683462015-09-29 15:09:59 -0400137 }
138 else
139 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300140 // Set the transform feedback state
141 std::vector<const GLchar *> transformFeedbackVaryings;
142 for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
Geoff Lang1528e562015-08-24 15:10:58 -0400143 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300144 transformFeedbackVaryings.push_back(tfVarying.c_str());
Geoff Lang1528e562015-08-24 15:10:58 -0400145 }
146
Martin Radev4c4c8e72016-08-04 12:25:34 +0300147 if (transformFeedbackVaryings.empty())
148 {
149 if (mFunctions->transformFeedbackVaryings)
150 {
151 mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
152 mState.getTransformFeedbackBufferMode());
153 }
154 }
155 else
156 {
157 ASSERT(mFunctions->transformFeedbackVaryings);
158 mFunctions->transformFeedbackVaryings(
159 mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()),
160 &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
161 }
162
163 const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mState.getAttachedVertexShader());
164 const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader());
165
166 // Attach the shaders
167 mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
168 mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
169
170 // Bind attribute locations to match the GL layer.
171 for (const sh::Attribute &attribute : mState.getAttributes())
172 {
Corentin Wallez6c1cbf52016-11-23 12:44:35 -0500173 if (!attribute.staticUse || attribute.isBuiltIn())
Martin Radev4c4c8e72016-08-04 12:25:34 +0300174 {
175 continue;
176 }
177
178 mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.name.c_str());
179 }
180
181 // Link and verify
182 mFunctions->linkProgram(mProgramID);
183
184 // Detach the shaders
185 mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
186 mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
Geoff Lang1528e562015-08-24 15:10:58 -0400187 }
188
Geoff Lang0ca53782015-05-07 13:49:39 -0400189 // Verify the link
Geoff Lang65a0be92015-10-02 09:57:30 -0400190 if (!checkLinkStatus(infoLog))
Geoff Langb1f435e2015-02-20 10:01:01 -0500191 {
Jamie Madillb0a838b2016-11-13 20:02:12 -0500192 return false;
Geoff Langb1f435e2015-02-20 10:01:01 -0500193 }
194
Philippe Hamel40911192016-04-07 16:45:50 -0400195 if (mWorkarounds.alwaysCallUseProgramAfterLink)
196 {
197 mStateManager->forceUseProgram(mProgramID);
198 }
199
Geoff Lang65a0be92015-10-02 09:57:30 -0400200 postLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500201
Jamie Madillb0a838b2016-11-13 20:02:12 -0500202 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -0500203}
204
Jamie Madill36cfd6a2015-08-18 10:46:20 -0400205GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
206{
207 // TODO(jmadill): implement validate
208 return true;
209}
210
Geoff Langf9a6f082015-01-22 13:32:49 -0500211void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
212{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800213 if (mFunctions->programUniform1fv != nullptr)
214 {
215 mFunctions->programUniform1fv(mProgramID, uniLoc(location), count, v);
216 }
217 else
218 {
219 mStateManager->useProgram(mProgramID);
220 mFunctions->uniform1fv(uniLoc(location), count, v);
221 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500222}
223
224void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
225{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800226 if (mFunctions->programUniform2fv != nullptr)
227 {
228 mFunctions->programUniform2fv(mProgramID, uniLoc(location), count, v);
229 }
230 else
231 {
232 mStateManager->useProgram(mProgramID);
233 mFunctions->uniform2fv(uniLoc(location), count, v);
234 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500235}
236
237void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
238{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800239 if (mFunctions->programUniform3fv != nullptr)
240 {
241 mFunctions->programUniform3fv(mProgramID, uniLoc(location), count, v);
242 }
243 else
244 {
245 mStateManager->useProgram(mProgramID);
246 mFunctions->uniform3fv(uniLoc(location), count, v);
247 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500248}
249
250void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
251{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800252 if (mFunctions->programUniform4fv != nullptr)
253 {
254 mFunctions->programUniform4fv(mProgramID, uniLoc(location), count, v);
255 }
256 else
257 {
258 mStateManager->useProgram(mProgramID);
259 mFunctions->uniform4fv(uniLoc(location), count, v);
260 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500261}
262
263void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
264{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800265 if (mFunctions->programUniform1iv != nullptr)
266 {
267 mFunctions->programUniform1iv(mProgramID, uniLoc(location), count, v);
268 }
269 else
270 {
271 mStateManager->useProgram(mProgramID);
272 mFunctions->uniform1iv(uniLoc(location), count, v);
273 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500274}
275
276void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
277{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800278 if (mFunctions->programUniform2iv != nullptr)
279 {
280 mFunctions->programUniform2iv(mProgramID, uniLoc(location), count, v);
281 }
282 else
283 {
284 mStateManager->useProgram(mProgramID);
285 mFunctions->uniform2iv(uniLoc(location), count, v);
286 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500287}
288
289void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
290{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800291 if (mFunctions->programUniform3iv != nullptr)
292 {
293 mFunctions->programUniform3iv(mProgramID, uniLoc(location), count, v);
294 }
295 else
296 {
297 mStateManager->useProgram(mProgramID);
298 mFunctions->uniform3iv(uniLoc(location), count, v);
299 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500300}
301
302void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
303{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800304 if (mFunctions->programUniform4iv != nullptr)
305 {
306 mFunctions->programUniform4iv(mProgramID, uniLoc(location), count, v);
307 }
308 else
309 {
310 mStateManager->useProgram(mProgramID);
311 mFunctions->uniform4iv(uniLoc(location), count, v);
312 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500313}
314
315void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
316{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800317 if (mFunctions->programUniform1uiv != nullptr)
318 {
319 mFunctions->programUniform1uiv(mProgramID, uniLoc(location), count, v);
320 }
321 else
322 {
323 mStateManager->useProgram(mProgramID);
324 mFunctions->uniform1uiv(uniLoc(location), count, v);
325 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500326}
327
328void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
329{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800330 if (mFunctions->programUniform2uiv != nullptr)
331 {
332 mFunctions->programUniform2uiv(mProgramID, uniLoc(location), count, v);
333 }
334 else
335 {
336 mStateManager->useProgram(mProgramID);
337 mFunctions->uniform2uiv(uniLoc(location), count, v);
338 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500339}
340
341void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
342{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800343 if (mFunctions->programUniform3uiv != nullptr)
344 {
345 mFunctions->programUniform3uiv(mProgramID, uniLoc(location), count, v);
346 }
347 else
348 {
349 mStateManager->useProgram(mProgramID);
350 mFunctions->uniform3uiv(uniLoc(location), count, v);
351 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500352}
353
354void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
355{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800356 if (mFunctions->programUniform4uiv != nullptr)
357 {
358 mFunctions->programUniform4uiv(mProgramID, uniLoc(location), count, v);
359 }
360 else
361 {
362 mStateManager->useProgram(mProgramID);
363 mFunctions->uniform4uiv(uniLoc(location), count, v);
364 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500365}
366
367void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
368{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800369 if (mFunctions->programUniformMatrix2fv != nullptr)
370 {
371 mFunctions->programUniformMatrix2fv(mProgramID, uniLoc(location), count, transpose, value);
372 }
373 else
374 {
375 mStateManager->useProgram(mProgramID);
376 mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
377 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500378}
379
380void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
381{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800382 if (mFunctions->programUniformMatrix3fv != nullptr)
383 {
384 mFunctions->programUniformMatrix3fv(mProgramID, uniLoc(location), count, transpose, value);
385 }
386 else
387 {
388 mStateManager->useProgram(mProgramID);
389 mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
390 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500391}
392
393void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
394{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800395 if (mFunctions->programUniformMatrix4fv != nullptr)
396 {
397 mFunctions->programUniformMatrix4fv(mProgramID, uniLoc(location), count, transpose, value);
398 }
399 else
400 {
401 mStateManager->useProgram(mProgramID);
402 mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
403 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500404}
405
406void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
407{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800408 if (mFunctions->programUniformMatrix2x3fv != nullptr)
409 {
410 mFunctions->programUniformMatrix2x3fv(mProgramID, uniLoc(location), count, transpose,
411 value);
412 }
413 else
414 {
415 mStateManager->useProgram(mProgramID);
416 mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
417 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500418}
419
420void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
421{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800422 if (mFunctions->programUniformMatrix3x2fv != nullptr)
423 {
424 mFunctions->programUniformMatrix3x2fv(mProgramID, uniLoc(location), count, transpose,
425 value);
426 }
427 else
428 {
429 mStateManager->useProgram(mProgramID);
430 mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
431 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500432}
433
434void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
435{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800436 if (mFunctions->programUniformMatrix2x4fv != nullptr)
437 {
438 mFunctions->programUniformMatrix2x4fv(mProgramID, uniLoc(location), count, transpose,
439 value);
440 }
441 else
442 {
443 mStateManager->useProgram(mProgramID);
444 mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
445 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500446}
447
448void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
449{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800450 if (mFunctions->programUniformMatrix4x2fv != nullptr)
451 {
452 mFunctions->programUniformMatrix4x2fv(mProgramID, uniLoc(location), count, transpose,
453 value);
454 }
455 else
456 {
457 mStateManager->useProgram(mProgramID);
458 mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
459 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500460}
461
462void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
463{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800464 if (mFunctions->programUniformMatrix3x4fv != nullptr)
465 {
466 mFunctions->programUniformMatrix3x4fv(mProgramID, uniLoc(location), count, transpose,
467 value);
468 }
469 else
470 {
471 mStateManager->useProgram(mProgramID);
472 mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
473 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500474}
475
476void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
477{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800478 if (mFunctions->programUniformMatrix4x3fv != nullptr)
479 {
480 mFunctions->programUniformMatrix4x3fv(mProgramID, uniLoc(location), count, transpose,
481 value);
482 }
483 else
484 {
485 mStateManager->useProgram(mProgramID);
486 mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
487 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500488}
489
Geoff Lang5d124a62015-09-15 13:03:27 -0400490void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
491{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400492 // Lazy init
493 if (mUniformBlockRealLocationMap.empty())
494 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400495 mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
496 for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill4a3c2342015-10-08 12:58:45 -0400497 {
498 const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex();
499 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str());
500 mUniformBlockRealLocationMap.push_back(blockIndex);
501 }
502 }
503
504 GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
505 if (realBlockIndex != GL_INVALID_INDEX)
506 {
507 mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
508 }
Geoff Lang5d124a62015-09-15 13:03:27 -0400509}
510
Geoff Langb1f435e2015-02-20 10:01:01 -0500511GLuint ProgramGL::getProgramID() const
512{
513 return mProgramID;
514}
515
Jamie Madill4a3c2342015-10-08 12:58:45 -0400516bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400517{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400518 ASSERT(mProgramID != 0u);
Geoff Lang5d124a62015-09-15 13:03:27 -0400519
Jamie Madill4a3c2342015-10-08 12:58:45 -0400520 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str());
521 if (blockIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400522 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400523 *sizeOut = 0;
524 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400525 }
526
Jamie Madill4a3c2342015-10-08 12:58:45 -0400527 GLint dataSize = 0;
528 mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
529 &dataSize);
530 *sizeOut = static_cast<size_t>(dataSize);
531 return true;
532}
533
534bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName,
535 sh::BlockMemberInfo *memberInfoOut) const
536{
537 GLuint uniformIndex;
538 const GLchar *memberNameGLStr = memberUniformName.c_str();
539 mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
540
541 if (uniformIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400542 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400543 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
544 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400545 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400546
547 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
548 &memberInfoOut->offset);
549 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
550 &memberInfoOut->arrayStride);
551 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
552 &memberInfoOut->matrixStride);
553
554 // TODO(jmadill): possibly determine this at the gl::Program level.
555 GLint isRowMajorMatrix = 0;
556 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
557 &isRowMajorMatrix);
558 memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
559 return true;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400560}
Jamie Madill4a3c2342015-10-08 12:58:45 -0400561
Sami Väisänen46eaa942016-06-29 10:26:37 +0300562void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
563 GLenum genMode,
564 GLint components,
565 const GLfloat *coeffs)
566{
567 ASSERT(mEnablePathRendering);
568
569 for (const auto &input : mPathRenderingFragmentInputs)
570 {
571 if (input.name == inputName)
572 {
573 mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
574 components, coeffs);
575 ASSERT(mFunctions->getError() == GL_NO_ERROR);
576 return;
577 }
578 }
579
580}
581
Geoff Lang65a0be92015-10-02 09:57:30 -0400582void ProgramGL::preLink()
583{
584 // Reset the program state
585 mUniformRealLocationMap.clear();
586 mUniformBlockRealLocationMap.clear();
Sami Väisänen46eaa942016-06-29 10:26:37 +0300587 mPathRenderingFragmentInputs.clear();
Geoff Lang65a0be92015-10-02 09:57:30 -0400588}
589
590bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
591{
592 GLint linkStatus = GL_FALSE;
593 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
594 if (linkStatus == GL_FALSE)
595 {
596 // Linking failed, put the error into the info log
597 GLint infoLogLength = 0;
598 mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
599
Geoff Lang65a0be92015-10-02 09:57:30 -0400600 // Info log length includes the null terminator, so 1 means that the info log is an empty
601 // string.
602 if (infoLogLength > 1)
603 {
604 std::vector<char> buf(infoLogLength);
605 mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
606
607 mFunctions->deleteProgram(mProgramID);
608 mProgramID = 0;
609
610 infoLog << buf.data();
611
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500612 WARN() << "Program link failed unexpectedly: " << buf.data();
Geoff Lang65a0be92015-10-02 09:57:30 -0400613 }
614 else
615 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500616 WARN() << "Program link failed unexpectedly with no info log.";
Geoff Lang65a0be92015-10-02 09:57:30 -0400617 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400618
619 // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
620 return false;
621 }
622
623 return true;
624}
625
626void ProgramGL::postLink()
627{
628 // Query the uniform information
629 ASSERT(mUniformRealLocationMap.empty());
Jamie Madill48ef11b2016-04-27 15:21:52 -0400630 const auto &uniformLocations = mState.getUniformLocations();
631 const auto &uniforms = mState.getUniforms();
Geoff Lang65a0be92015-10-02 09:57:30 -0400632 mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
633 for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
634 {
635 const auto &entry = uniformLocations[uniformLocation];
636 if (!entry.used)
637 {
638 continue;
639 }
640
641 // From the spec:
642 // "Locations for sequential array indices are not required to be sequential."
643 const gl::LinkedUniform &uniform = uniforms[entry.index];
644 std::stringstream fullNameStr;
645 fullNameStr << uniform.name;
646 if (uniform.isArray())
647 {
648 fullNameStr << "[" << entry.element << "]";
649 }
650 const std::string &fullName = fullNameStr.str();
651
652 GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
653 mUniformRealLocationMap[uniformLocation] = realLocation;
654 }
655
Sami Väisänen46eaa942016-06-29 10:26:37 +0300656 // Discover CHROMIUM_path_rendering fragment inputs if enabled.
657 if (!mEnablePathRendering)
658 return;
659
660 GLint numFragmentInputs = 0;
661 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
662 &numFragmentInputs);
663 if (numFragmentInputs <= 0)
664 return;
665
666 GLint maxNameLength = 0;
667 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
668 &maxNameLength);
669 ASSERT(maxNameLength);
670
671 for (GLint i = 0; i < numFragmentInputs; ++i)
672 {
673 std::string name;
674 name.resize(maxNameLength);
675
676 GLsizei nameLen = 0;
677 mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
678 &nameLen, &name[0]);
679 name.resize(nameLen);
680
681 // Ignore built-ins
682 if (angle::BeginsWith(name, "gl_"))
683 continue;
684
685 const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
686 GLint queryResults[ArraySize(kQueryProperties)];
687 GLsizei queryLength = 0;
688
Geoff Lang3f6a3982016-07-15 15:20:45 -0400689 mFunctions->getProgramResourceiv(
690 mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
691 kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
692 queryResults);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300693
Olli Etuahoe3191712016-07-18 16:01:10 +0300694 ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300695
Geoff Lang3f6a3982016-07-15 15:20:45 -0400696 PathRenderingFragmentInput baseElementInput;
697 baseElementInput.name = name;
698 baseElementInput.location = queryResults[0];
699 mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300700
701 // If the input is an array it's denoted by [0] suffix on the variable
702 // name. We'll then create an entry per each array index where index > 0
703 if (angle::EndsWith(name, "[0]"))
704 {
705 // drop the suffix
706 name.resize(name.size() - 3);
707
708 const auto arraySize = queryResults[1];
709 const auto baseLocation = queryResults[0];
710
Geoff Lang3f6a3982016-07-15 15:20:45 -0400711 for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300712 {
Geoff Lang3f6a3982016-07-15 15:20:45 -0400713 PathRenderingFragmentInput arrayElementInput;
Corentin Wallez054f7ed2016-09-20 17:15:59 -0400714 arrayElementInput.name = name + "[" + ToString(arrayIndex) + "]";
Geoff Lang3f6a3982016-07-15 15:20:45 -0400715 arrayElementInput.location = baseLocation + arrayIndex;
716 mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300717 }
718 }
719 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400720}
721
Jamie Madill4a3c2342015-10-08 12:58:45 -0400722} // namespace rx