blob: d04c1e76a99dd5b30183f2d1313e5366bb6a6e7f [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
101 return gl::Error(GL_NO_ERROR);
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 Madill9082b982016-04-27 15:21:51 -0400114LinkResult ProgramGL::link(const gl::ContextState &data, gl::InfoLog &infoLog)
Geoff Langf9a6f082015-01-22 13:32:49 -0500115{
Geoff Lang65a0be92015-10-02 09:57:30 -0400116 preLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500117
Martin Radev4c4c8e72016-08-04 12:25:34 +0300118 if (mState.getAttachedComputeShader())
Geoff Lang1a683462015-09-29 15:09:59 -0400119 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300120 const ShaderGL *computeShaderGL = GetImplAs<ShaderGL>(mState.getAttachedComputeShader());
Geoff Lang1a683462015-09-29 15:09:59 -0400121
Martin Radev4c4c8e72016-08-04 12:25:34 +0300122 mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID());
123
124 // Link and verify
125 mFunctions->linkProgram(mProgramID);
126
127 // Detach the shaders
128 mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID());
Geoff Lang1a683462015-09-29 15:09:59 -0400129 }
130 else
131 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300132 // Set the transform feedback state
133 std::vector<const GLchar *> transformFeedbackVaryings;
134 for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
Geoff Lang1528e562015-08-24 15:10:58 -0400135 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300136 transformFeedbackVaryings.push_back(tfVarying.c_str());
Geoff Lang1528e562015-08-24 15:10:58 -0400137 }
138
Martin Radev4c4c8e72016-08-04 12:25:34 +0300139 if (transformFeedbackVaryings.empty())
140 {
141 if (mFunctions->transformFeedbackVaryings)
142 {
143 mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
144 mState.getTransformFeedbackBufferMode());
145 }
146 }
147 else
148 {
149 ASSERT(mFunctions->transformFeedbackVaryings);
150 mFunctions->transformFeedbackVaryings(
151 mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()),
152 &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
153 }
154
155 const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mState.getAttachedVertexShader());
156 const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader());
157
158 // Attach the shaders
159 mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
160 mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
161
162 // Bind attribute locations to match the GL layer.
163 for (const sh::Attribute &attribute : mState.getAttributes())
164 {
Corentin Wallez6c1cbf52016-11-23 12:44:35 -0500165 if (!attribute.staticUse || attribute.isBuiltIn())
Martin Radev4c4c8e72016-08-04 12:25:34 +0300166 {
167 continue;
168 }
169
170 mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.name.c_str());
171 }
172
173 // Link and verify
174 mFunctions->linkProgram(mProgramID);
175
176 // Detach the shaders
177 mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
178 mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
Geoff Lang1528e562015-08-24 15:10:58 -0400179 }
180
Geoff Lang0ca53782015-05-07 13:49:39 -0400181 // Verify the link
Geoff Lang65a0be92015-10-02 09:57:30 -0400182 if (!checkLinkStatus(infoLog))
Geoff Langb1f435e2015-02-20 10:01:01 -0500183 {
Jamie Madillb0a838b2016-11-13 20:02:12 -0500184 return false;
Geoff Langb1f435e2015-02-20 10:01:01 -0500185 }
186
Philippe Hamel40911192016-04-07 16:45:50 -0400187 if (mWorkarounds.alwaysCallUseProgramAfterLink)
188 {
189 mStateManager->forceUseProgram(mProgramID);
190 }
191
Geoff Lang65a0be92015-10-02 09:57:30 -0400192 postLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500193
Jamie Madillb0a838b2016-11-13 20:02:12 -0500194 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -0500195}
196
Jamie Madill36cfd6a2015-08-18 10:46:20 -0400197GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
198{
199 // TODO(jmadill): implement validate
200 return true;
201}
202
Geoff Langf9a6f082015-01-22 13:32:49 -0500203void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
204{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800205 if (mFunctions->programUniform1fv != nullptr)
206 {
207 mFunctions->programUniform1fv(mProgramID, uniLoc(location), count, v);
208 }
209 else
210 {
211 mStateManager->useProgram(mProgramID);
212 mFunctions->uniform1fv(uniLoc(location), count, v);
213 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500214}
215
216void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
217{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800218 if (mFunctions->programUniform2fv != nullptr)
219 {
220 mFunctions->programUniform2fv(mProgramID, uniLoc(location), count, v);
221 }
222 else
223 {
224 mStateManager->useProgram(mProgramID);
225 mFunctions->uniform2fv(uniLoc(location), count, v);
226 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500227}
228
229void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
230{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800231 if (mFunctions->programUniform3fv != nullptr)
232 {
233 mFunctions->programUniform3fv(mProgramID, uniLoc(location), count, v);
234 }
235 else
236 {
237 mStateManager->useProgram(mProgramID);
238 mFunctions->uniform3fv(uniLoc(location), count, v);
239 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500240}
241
242void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
243{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800244 if (mFunctions->programUniform4fv != nullptr)
245 {
246 mFunctions->programUniform4fv(mProgramID, uniLoc(location), count, v);
247 }
248 else
249 {
250 mStateManager->useProgram(mProgramID);
251 mFunctions->uniform4fv(uniLoc(location), count, v);
252 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500253}
254
255void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
256{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800257 if (mFunctions->programUniform1iv != nullptr)
258 {
259 mFunctions->programUniform1iv(mProgramID, uniLoc(location), count, v);
260 }
261 else
262 {
263 mStateManager->useProgram(mProgramID);
264 mFunctions->uniform1iv(uniLoc(location), count, v);
265 }
Geoff Langf51bc792015-05-04 14:57:03 -0400266
Jamie Madill48ef11b2016-04-27 15:21:52 -0400267 const gl::VariableLocation &locationEntry = mState.getUniformLocations()[location];
Jamie Madill62d31cb2015-09-11 13:25:51 -0400268
269 size_t samplerIndex = mUniformIndexToSamplerIndex[locationEntry.index];
270 if (samplerIndex != GL_INVALID_INDEX)
Geoff Langf51bc792015-05-04 14:57:03 -0400271 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400272 std::vector<GLuint> &boundTextureUnits = mSamplerBindings[samplerIndex].boundTextureUnits;
Geoff Langf51bc792015-05-04 14:57:03 -0400273
Jamie Madill62d31cb2015-09-11 13:25:51 -0400274 size_t copyCount =
Corentin Wallez4c5ff002016-10-25 09:32:17 -0400275 std::min<size_t>(count, boundTextureUnits.size() - locationEntry.element);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400276 std::copy(v, v + copyCount, boundTextureUnits.begin() + locationEntry.element);
Geoff Langf51bc792015-05-04 14:57:03 -0400277 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500278}
279
280void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
281{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800282 if (mFunctions->programUniform2iv != nullptr)
283 {
284 mFunctions->programUniform2iv(mProgramID, uniLoc(location), count, v);
285 }
286 else
287 {
288 mStateManager->useProgram(mProgramID);
289 mFunctions->uniform2iv(uniLoc(location), count, v);
290 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500291}
292
293void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
294{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800295 if (mFunctions->programUniform3iv != nullptr)
296 {
297 mFunctions->programUniform3iv(mProgramID, uniLoc(location), count, v);
298 }
299 else
300 {
301 mStateManager->useProgram(mProgramID);
302 mFunctions->uniform3iv(uniLoc(location), count, v);
303 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500304}
305
306void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
307{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800308 if (mFunctions->programUniform4iv != nullptr)
309 {
310 mFunctions->programUniform4iv(mProgramID, uniLoc(location), count, v);
311 }
312 else
313 {
314 mStateManager->useProgram(mProgramID);
315 mFunctions->uniform4iv(uniLoc(location), count, v);
316 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500317}
318
319void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
320{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800321 if (mFunctions->programUniform1uiv != nullptr)
322 {
323 mFunctions->programUniform1uiv(mProgramID, uniLoc(location), count, v);
324 }
325 else
326 {
327 mStateManager->useProgram(mProgramID);
328 mFunctions->uniform1uiv(uniLoc(location), count, v);
329 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500330}
331
332void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
333{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800334 if (mFunctions->programUniform2uiv != nullptr)
335 {
336 mFunctions->programUniform2uiv(mProgramID, uniLoc(location), count, v);
337 }
338 else
339 {
340 mStateManager->useProgram(mProgramID);
341 mFunctions->uniform2uiv(uniLoc(location), count, v);
342 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500343}
344
345void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
346{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800347 if (mFunctions->programUniform3uiv != nullptr)
348 {
349 mFunctions->programUniform3uiv(mProgramID, uniLoc(location), count, v);
350 }
351 else
352 {
353 mStateManager->useProgram(mProgramID);
354 mFunctions->uniform3uiv(uniLoc(location), count, v);
355 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500356}
357
358void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
359{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800360 if (mFunctions->programUniform4uiv != nullptr)
361 {
362 mFunctions->programUniform4uiv(mProgramID, uniLoc(location), count, v);
363 }
364 else
365 {
366 mStateManager->useProgram(mProgramID);
367 mFunctions->uniform4uiv(uniLoc(location), count, v);
368 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500369}
370
371void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
372{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800373 if (mFunctions->programUniformMatrix2fv != nullptr)
374 {
375 mFunctions->programUniformMatrix2fv(mProgramID, uniLoc(location), count, transpose, value);
376 }
377 else
378 {
379 mStateManager->useProgram(mProgramID);
380 mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
381 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500382}
383
384void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
385{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800386 if (mFunctions->programUniformMatrix3fv != nullptr)
387 {
388 mFunctions->programUniformMatrix3fv(mProgramID, uniLoc(location), count, transpose, value);
389 }
390 else
391 {
392 mStateManager->useProgram(mProgramID);
393 mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
394 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500395}
396
397void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
398{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800399 if (mFunctions->programUniformMatrix4fv != nullptr)
400 {
401 mFunctions->programUniformMatrix4fv(mProgramID, uniLoc(location), count, transpose, value);
402 }
403 else
404 {
405 mStateManager->useProgram(mProgramID);
406 mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
407 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500408}
409
410void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
411{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800412 if (mFunctions->programUniformMatrix2x3fv != nullptr)
413 {
414 mFunctions->programUniformMatrix2x3fv(mProgramID, uniLoc(location), count, transpose,
415 value);
416 }
417 else
418 {
419 mStateManager->useProgram(mProgramID);
420 mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
421 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500422}
423
424void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
425{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800426 if (mFunctions->programUniformMatrix3x2fv != nullptr)
427 {
428 mFunctions->programUniformMatrix3x2fv(mProgramID, uniLoc(location), count, transpose,
429 value);
430 }
431 else
432 {
433 mStateManager->useProgram(mProgramID);
434 mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
435 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500436}
437
438void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
439{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800440 if (mFunctions->programUniformMatrix2x4fv != nullptr)
441 {
442 mFunctions->programUniformMatrix2x4fv(mProgramID, uniLoc(location), count, transpose,
443 value);
444 }
445 else
446 {
447 mStateManager->useProgram(mProgramID);
448 mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
449 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500450}
451
452void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
453{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800454 if (mFunctions->programUniformMatrix4x2fv != nullptr)
455 {
456 mFunctions->programUniformMatrix4x2fv(mProgramID, uniLoc(location), count, transpose,
457 value);
458 }
459 else
460 {
461 mStateManager->useProgram(mProgramID);
462 mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
463 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500464}
465
466void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
467{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800468 if (mFunctions->programUniformMatrix3x4fv != nullptr)
469 {
470 mFunctions->programUniformMatrix3x4fv(mProgramID, uniLoc(location), count, transpose,
471 value);
472 }
473 else
474 {
475 mStateManager->useProgram(mProgramID);
476 mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
477 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500478}
479
480void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
481{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800482 if (mFunctions->programUniformMatrix4x3fv != nullptr)
483 {
484 mFunctions->programUniformMatrix4x3fv(mProgramID, uniLoc(location), count, transpose,
485 value);
486 }
487 else
488 {
489 mStateManager->useProgram(mProgramID);
490 mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
491 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500492}
493
Geoff Lang5d124a62015-09-15 13:03:27 -0400494void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
495{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400496 // Lazy init
497 if (mUniformBlockRealLocationMap.empty())
498 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400499 mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
500 for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill4a3c2342015-10-08 12:58:45 -0400501 {
502 const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex();
503 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str());
504 mUniformBlockRealLocationMap.push_back(blockIndex);
505 }
506 }
507
508 GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
509 if (realBlockIndex != GL_INVALID_INDEX)
510 {
511 mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
512 }
Geoff Lang5d124a62015-09-15 13:03:27 -0400513}
514
Geoff Langb1f435e2015-02-20 10:01:01 -0500515GLuint ProgramGL::getProgramID() const
516{
517 return mProgramID;
518}
519
Geoff Langf51bc792015-05-04 14:57:03 -0400520const std::vector<SamplerBindingGL> &ProgramGL::getAppliedSamplerUniforms() const
521{
522 return mSamplerBindings;
523}
524
Jamie Madill4a3c2342015-10-08 12:58:45 -0400525bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400526{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400527 ASSERT(mProgramID != 0u);
Geoff Lang5d124a62015-09-15 13:03:27 -0400528
Jamie Madill4a3c2342015-10-08 12:58:45 -0400529 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str());
530 if (blockIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400531 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400532 *sizeOut = 0;
533 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400534 }
535
Jamie Madill4a3c2342015-10-08 12:58:45 -0400536 GLint dataSize = 0;
537 mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
538 &dataSize);
539 *sizeOut = static_cast<size_t>(dataSize);
540 return true;
541}
542
543bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName,
544 sh::BlockMemberInfo *memberInfoOut) const
545{
546 GLuint uniformIndex;
547 const GLchar *memberNameGLStr = memberUniformName.c_str();
548 mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
549
550 if (uniformIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400551 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400552 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
553 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400554 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400555
556 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
557 &memberInfoOut->offset);
558 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
559 &memberInfoOut->arrayStride);
560 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
561 &memberInfoOut->matrixStride);
562
563 // TODO(jmadill): possibly determine this at the gl::Program level.
564 GLint isRowMajorMatrix = 0;
565 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
566 &isRowMajorMatrix);
567 memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
568 return true;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400569}
Jamie Madill4a3c2342015-10-08 12:58:45 -0400570
Sami Väisänen46eaa942016-06-29 10:26:37 +0300571void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
572 GLenum genMode,
573 GLint components,
574 const GLfloat *coeffs)
575{
576 ASSERT(mEnablePathRendering);
577
578 for (const auto &input : mPathRenderingFragmentInputs)
579 {
580 if (input.name == inputName)
581 {
582 mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
583 components, coeffs);
584 ASSERT(mFunctions->getError() == GL_NO_ERROR);
585 return;
586 }
587 }
588
589}
590
Geoff Lang65a0be92015-10-02 09:57:30 -0400591void ProgramGL::preLink()
592{
593 // Reset the program state
594 mUniformRealLocationMap.clear();
595 mUniformBlockRealLocationMap.clear();
596 mSamplerBindings.clear();
597 mUniformIndexToSamplerIndex.clear();
Sami Väisänen46eaa942016-06-29 10:26:37 +0300598 mPathRenderingFragmentInputs.clear();
Geoff Lang65a0be92015-10-02 09:57:30 -0400599}
600
601bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
602{
603 GLint linkStatus = GL_FALSE;
604 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
605 if (linkStatus == GL_FALSE)
606 {
607 // Linking failed, put the error into the info log
608 GLint infoLogLength = 0;
609 mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
610
611 std::string warning;
612
613 // Info log length includes the null terminator, so 1 means that the info log is an empty
614 // string.
615 if (infoLogLength > 1)
616 {
617 std::vector<char> buf(infoLogLength);
618 mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
619
620 mFunctions->deleteProgram(mProgramID);
621 mProgramID = 0;
622
623 infoLog << buf.data();
624
625 warning = FormatString("Program link failed unexpectedly: %s", buf.data());
626 }
627 else
628 {
629 warning = "Program link failed unexpectedly with no info log.";
630 }
631 ANGLEPlatformCurrent()->logWarning(warning.c_str());
632 TRACE("\n%s", warning.c_str());
633
634 // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
635 return false;
636 }
637
638 return true;
639}
640
641void ProgramGL::postLink()
642{
643 // Query the uniform information
644 ASSERT(mUniformRealLocationMap.empty());
Jamie Madill48ef11b2016-04-27 15:21:52 -0400645 const auto &uniformLocations = mState.getUniformLocations();
646 const auto &uniforms = mState.getUniforms();
Geoff Lang65a0be92015-10-02 09:57:30 -0400647 mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
648 for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
649 {
650 const auto &entry = uniformLocations[uniformLocation];
651 if (!entry.used)
652 {
653 continue;
654 }
655
656 // From the spec:
657 // "Locations for sequential array indices are not required to be sequential."
658 const gl::LinkedUniform &uniform = uniforms[entry.index];
659 std::stringstream fullNameStr;
660 fullNameStr << uniform.name;
661 if (uniform.isArray())
662 {
663 fullNameStr << "[" << entry.element << "]";
664 }
665 const std::string &fullName = fullNameStr.str();
666
667 GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
668 mUniformRealLocationMap[uniformLocation] = realLocation;
669 }
670
Jamie Madill48ef11b2016-04-27 15:21:52 -0400671 mUniformIndexToSamplerIndex.resize(mState.getUniforms().size(), GL_INVALID_INDEX);
Geoff Lang65a0be92015-10-02 09:57:30 -0400672
673 for (size_t uniformId = 0; uniformId < uniforms.size(); ++uniformId)
674 {
675 const gl::LinkedUniform &linkedUniform = uniforms[uniformId];
676
677 if (!linkedUniform.isSampler() || !linkedUniform.staticUse)
678 continue;
679
680 mUniformIndexToSamplerIndex[uniformId] = mSamplerBindings.size();
681
682 // If uniform is a sampler type, insert it into the mSamplerBindings array
683 SamplerBindingGL samplerBinding;
684 samplerBinding.textureType = gl::SamplerTypeToTextureType(linkedUniform.type);
685 samplerBinding.boundTextureUnits.resize(linkedUniform.elementCount(), 0);
686 mSamplerBindings.push_back(samplerBinding);
687 }
Sami Väisänen46eaa942016-06-29 10:26:37 +0300688
689 // Discover CHROMIUM_path_rendering fragment inputs if enabled.
690 if (!mEnablePathRendering)
691 return;
692
693 GLint numFragmentInputs = 0;
694 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
695 &numFragmentInputs);
696 if (numFragmentInputs <= 0)
697 return;
698
699 GLint maxNameLength = 0;
700 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
701 &maxNameLength);
702 ASSERT(maxNameLength);
703
704 for (GLint i = 0; i < numFragmentInputs; ++i)
705 {
706 std::string name;
707 name.resize(maxNameLength);
708
709 GLsizei nameLen = 0;
710 mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
711 &nameLen, &name[0]);
712 name.resize(nameLen);
713
714 // Ignore built-ins
715 if (angle::BeginsWith(name, "gl_"))
716 continue;
717
718 const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
719 GLint queryResults[ArraySize(kQueryProperties)];
720 GLsizei queryLength = 0;
721
Geoff Lang3f6a3982016-07-15 15:20:45 -0400722 mFunctions->getProgramResourceiv(
723 mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
724 kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
725 queryResults);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300726
Olli Etuahoe3191712016-07-18 16:01:10 +0300727 ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300728
Geoff Lang3f6a3982016-07-15 15:20:45 -0400729 PathRenderingFragmentInput baseElementInput;
730 baseElementInput.name = name;
731 baseElementInput.location = queryResults[0];
732 mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300733
734 // If the input is an array it's denoted by [0] suffix on the variable
735 // name. We'll then create an entry per each array index where index > 0
736 if (angle::EndsWith(name, "[0]"))
737 {
738 // drop the suffix
739 name.resize(name.size() - 3);
740
741 const auto arraySize = queryResults[1];
742 const auto baseLocation = queryResults[0];
743
Geoff Lang3f6a3982016-07-15 15:20:45 -0400744 for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300745 {
Geoff Lang3f6a3982016-07-15 15:20:45 -0400746 PathRenderingFragmentInput arrayElementInput;
Corentin Wallez054f7ed2016-09-20 17:15:59 -0400747 arrayElementInput.name = name + "[" + ToString(arrayIndex) + "]";
Geoff Lang3f6a3982016-07-15 15:20:45 -0400748 arrayElementInput.location = baseLocation + arrayIndex;
749 mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300750 }
751 }
752 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400753}
754
Jamie Madill4a3c2342015-10-08 12:58:45 -0400755} // namespace rx