blob: 6f81fd0b2cf6e9b3eb6f3ee8966ffde3e6d0266b [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
Olli Etuaho855d9642017-05-17 14:05:06 +0300147 std::vector<std::string> transformFeedbackVaryingMappedNames;
Martin Radev4c4c8e72016-08-04 12:25:34 +0300148 for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
Geoff Lang1528e562015-08-24 15:10:58 -0400149 {
Olli Etuaho855d9642017-05-17 14:05:06 +0300150 std::string tfVaryingMappedName =
151 mState.getAttachedVertexShader()->getTransformFeedbackVaryingMappedName(tfVarying,
152 context);
153 transformFeedbackVaryingMappedNames.push_back(tfVaryingMappedName);
Geoff Lang1528e562015-08-24 15:10:58 -0400154 }
155
Olli Etuaho855d9642017-05-17 14:05:06 +0300156 if (transformFeedbackVaryingMappedNames.empty())
Martin Radev4c4c8e72016-08-04 12:25:34 +0300157 {
158 if (mFunctions->transformFeedbackVaryings)
159 {
160 mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
161 mState.getTransformFeedbackBufferMode());
162 }
163 }
164 else
165 {
166 ASSERT(mFunctions->transformFeedbackVaryings);
Olli Etuaho855d9642017-05-17 14:05:06 +0300167 std::vector<const GLchar *> transformFeedbackVaryings;
168 for (const auto &varying : transformFeedbackVaryingMappedNames)
169 {
170 transformFeedbackVaryings.push_back(varying.c_str());
171 }
Martin Radev4c4c8e72016-08-04 12:25:34 +0300172 mFunctions->transformFeedbackVaryings(
Olli Etuaho855d9642017-05-17 14:05:06 +0300173 mProgramID, static_cast<GLsizei>(transformFeedbackVaryingMappedNames.size()),
Martin Radev4c4c8e72016-08-04 12:25:34 +0300174 &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
175 }
176
177 const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mState.getAttachedVertexShader());
178 const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader());
179
180 // Attach the shaders
181 mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
182 mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
183
184 // Bind attribute locations to match the GL layer.
185 for (const sh::Attribute &attribute : mState.getAttributes())
186 {
Corentin Wallez6c1cbf52016-11-23 12:44:35 -0500187 if (!attribute.staticUse || attribute.isBuiltIn())
Martin Radev4c4c8e72016-08-04 12:25:34 +0300188 {
189 continue;
190 }
191
Olli Etuaho855d9642017-05-17 14:05:06 +0300192 mFunctions->bindAttribLocation(mProgramID, attribute.location,
193 attribute.mappedName.c_str());
Martin Radev4c4c8e72016-08-04 12:25:34 +0300194 }
195
196 // Link and verify
197 mFunctions->linkProgram(mProgramID);
198
199 // Detach the shaders
200 mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
201 mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
Geoff Lang1528e562015-08-24 15:10:58 -0400202 }
203
Geoff Lang0ca53782015-05-07 13:49:39 -0400204 // Verify the link
Geoff Lang65a0be92015-10-02 09:57:30 -0400205 if (!checkLinkStatus(infoLog))
Geoff Langb1f435e2015-02-20 10:01:01 -0500206 {
Jamie Madillb0a838b2016-11-13 20:02:12 -0500207 return false;
Geoff Langb1f435e2015-02-20 10:01:01 -0500208 }
209
Philippe Hamel40911192016-04-07 16:45:50 -0400210 if (mWorkarounds.alwaysCallUseProgramAfterLink)
211 {
212 mStateManager->forceUseProgram(mProgramID);
213 }
214
Geoff Lang65a0be92015-10-02 09:57:30 -0400215 postLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500216
Jamie Madillb0a838b2016-11-13 20:02:12 -0500217 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -0500218}
219
Jamie Madill36cfd6a2015-08-18 10:46:20 -0400220GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
221{
222 // TODO(jmadill): implement validate
223 return true;
224}
225
Geoff Langf9a6f082015-01-22 13:32:49 -0500226void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
227{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800228 if (mFunctions->programUniform1fv != nullptr)
229 {
230 mFunctions->programUniform1fv(mProgramID, uniLoc(location), count, v);
231 }
232 else
233 {
234 mStateManager->useProgram(mProgramID);
235 mFunctions->uniform1fv(uniLoc(location), count, v);
236 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500237}
238
239void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
240{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800241 if (mFunctions->programUniform2fv != nullptr)
242 {
243 mFunctions->programUniform2fv(mProgramID, uniLoc(location), count, v);
244 }
245 else
246 {
247 mStateManager->useProgram(mProgramID);
248 mFunctions->uniform2fv(uniLoc(location), count, v);
249 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500250}
251
252void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
253{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800254 if (mFunctions->programUniform3fv != nullptr)
255 {
256 mFunctions->programUniform3fv(mProgramID, uniLoc(location), count, v);
257 }
258 else
259 {
260 mStateManager->useProgram(mProgramID);
261 mFunctions->uniform3fv(uniLoc(location), count, v);
262 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500263}
264
265void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
266{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800267 if (mFunctions->programUniform4fv != nullptr)
268 {
269 mFunctions->programUniform4fv(mProgramID, uniLoc(location), count, v);
270 }
271 else
272 {
273 mStateManager->useProgram(mProgramID);
274 mFunctions->uniform4fv(uniLoc(location), count, v);
275 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500276}
277
278void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
279{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800280 if (mFunctions->programUniform1iv != nullptr)
281 {
282 mFunctions->programUniform1iv(mProgramID, uniLoc(location), count, v);
283 }
284 else
285 {
286 mStateManager->useProgram(mProgramID);
287 mFunctions->uniform1iv(uniLoc(location), count, v);
288 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500289}
290
291void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
292{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800293 if (mFunctions->programUniform2iv != nullptr)
294 {
295 mFunctions->programUniform2iv(mProgramID, uniLoc(location), count, v);
296 }
297 else
298 {
299 mStateManager->useProgram(mProgramID);
300 mFunctions->uniform2iv(uniLoc(location), count, v);
301 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500302}
303
304void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
305{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800306 if (mFunctions->programUniform3iv != nullptr)
307 {
308 mFunctions->programUniform3iv(mProgramID, uniLoc(location), count, v);
309 }
310 else
311 {
312 mStateManager->useProgram(mProgramID);
313 mFunctions->uniform3iv(uniLoc(location), count, v);
314 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500315}
316
317void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
318{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800319 if (mFunctions->programUniform4iv != nullptr)
320 {
321 mFunctions->programUniform4iv(mProgramID, uniLoc(location), count, v);
322 }
323 else
324 {
325 mStateManager->useProgram(mProgramID);
326 mFunctions->uniform4iv(uniLoc(location), count, v);
327 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500328}
329
330void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
331{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800332 if (mFunctions->programUniform1uiv != nullptr)
333 {
334 mFunctions->programUniform1uiv(mProgramID, uniLoc(location), count, v);
335 }
336 else
337 {
338 mStateManager->useProgram(mProgramID);
339 mFunctions->uniform1uiv(uniLoc(location), count, v);
340 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500341}
342
343void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
344{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800345 if (mFunctions->programUniform2uiv != nullptr)
346 {
347 mFunctions->programUniform2uiv(mProgramID, uniLoc(location), count, v);
348 }
349 else
350 {
351 mStateManager->useProgram(mProgramID);
352 mFunctions->uniform2uiv(uniLoc(location), count, v);
353 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500354}
355
356void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
357{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800358 if (mFunctions->programUniform3uiv != nullptr)
359 {
360 mFunctions->programUniform3uiv(mProgramID, uniLoc(location), count, v);
361 }
362 else
363 {
364 mStateManager->useProgram(mProgramID);
365 mFunctions->uniform3uiv(uniLoc(location), count, v);
366 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500367}
368
369void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
370{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800371 if (mFunctions->programUniform4uiv != nullptr)
372 {
373 mFunctions->programUniform4uiv(mProgramID, uniLoc(location), count, v);
374 }
375 else
376 {
377 mStateManager->useProgram(mProgramID);
378 mFunctions->uniform4uiv(uniLoc(location), count, v);
379 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500380}
381
382void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
383{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800384 if (mFunctions->programUniformMatrix2fv != nullptr)
385 {
386 mFunctions->programUniformMatrix2fv(mProgramID, uniLoc(location), count, transpose, value);
387 }
388 else
389 {
390 mStateManager->useProgram(mProgramID);
391 mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
392 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500393}
394
395void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
396{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800397 if (mFunctions->programUniformMatrix3fv != nullptr)
398 {
399 mFunctions->programUniformMatrix3fv(mProgramID, uniLoc(location), count, transpose, value);
400 }
401 else
402 {
403 mStateManager->useProgram(mProgramID);
404 mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
405 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500406}
407
408void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
409{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800410 if (mFunctions->programUniformMatrix4fv != nullptr)
411 {
412 mFunctions->programUniformMatrix4fv(mProgramID, uniLoc(location), count, transpose, value);
413 }
414 else
415 {
416 mStateManager->useProgram(mProgramID);
417 mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
418 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500419}
420
421void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
422{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800423 if (mFunctions->programUniformMatrix2x3fv != nullptr)
424 {
425 mFunctions->programUniformMatrix2x3fv(mProgramID, uniLoc(location), count, transpose,
426 value);
427 }
428 else
429 {
430 mStateManager->useProgram(mProgramID);
431 mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
432 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500433}
434
435void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
436{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800437 if (mFunctions->programUniformMatrix3x2fv != nullptr)
438 {
439 mFunctions->programUniformMatrix3x2fv(mProgramID, uniLoc(location), count, transpose,
440 value);
441 }
442 else
443 {
444 mStateManager->useProgram(mProgramID);
445 mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
446 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500447}
448
449void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
450{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800451 if (mFunctions->programUniformMatrix2x4fv != nullptr)
452 {
453 mFunctions->programUniformMatrix2x4fv(mProgramID, uniLoc(location), count, transpose,
454 value);
455 }
456 else
457 {
458 mStateManager->useProgram(mProgramID);
459 mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
460 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500461}
462
463void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
464{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800465 if (mFunctions->programUniformMatrix4x2fv != nullptr)
466 {
467 mFunctions->programUniformMatrix4x2fv(mProgramID, uniLoc(location), count, transpose,
468 value);
469 }
470 else
471 {
472 mStateManager->useProgram(mProgramID);
473 mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
474 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500475}
476
477void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
478{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800479 if (mFunctions->programUniformMatrix3x4fv != nullptr)
480 {
481 mFunctions->programUniformMatrix3x4fv(mProgramID, uniLoc(location), count, transpose,
482 value);
483 }
484 else
485 {
486 mStateManager->useProgram(mProgramID);
487 mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
488 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500489}
490
491void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
492{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800493 if (mFunctions->programUniformMatrix4x3fv != nullptr)
494 {
495 mFunctions->programUniformMatrix4x3fv(mProgramID, uniLoc(location), count, transpose,
496 value);
497 }
498 else
499 {
500 mStateManager->useProgram(mProgramID);
501 mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
502 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500503}
504
Geoff Lang5d124a62015-09-15 13:03:27 -0400505void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
506{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400507 // Lazy init
508 if (mUniformBlockRealLocationMap.empty())
509 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400510 mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
Jiajia Qin729b2c62017-08-14 09:36:11 +0800511 for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill4a3c2342015-10-08 12:58:45 -0400512 {
Olli Etuaho855d9642017-05-17 14:05:06 +0300513 const std::string &mappedNameWithIndex = uniformBlock.mappedNameWithArrayIndex();
514 GLuint blockIndex =
515 mFunctions->getUniformBlockIndex(mProgramID, mappedNameWithIndex.c_str());
Jamie Madill4a3c2342015-10-08 12:58:45 -0400516 mUniformBlockRealLocationMap.push_back(blockIndex);
517 }
518 }
519
520 GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
521 if (realBlockIndex != GL_INVALID_INDEX)
522 {
523 mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
524 }
Geoff Lang5d124a62015-09-15 13:03:27 -0400525}
526
Geoff Langb1f435e2015-02-20 10:01:01 -0500527GLuint ProgramGL::getProgramID() const
528{
529 return mProgramID;
530}
531
Olli Etuaho855d9642017-05-17 14:05:06 +0300532bool ProgramGL::getUniformBlockSize(const std::string & /* blockName */,
533 const std::string &blockMappedName,
534 size_t *sizeOut) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400535{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400536 ASSERT(mProgramID != 0u);
Geoff Lang5d124a62015-09-15 13:03:27 -0400537
Olli Etuaho855d9642017-05-17 14:05:06 +0300538 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockMappedName.c_str());
Jamie Madill4a3c2342015-10-08 12:58:45 -0400539 if (blockIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400540 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400541 *sizeOut = 0;
542 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400543 }
544
Jamie Madill4a3c2342015-10-08 12:58:45 -0400545 GLint dataSize = 0;
546 mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
547 &dataSize);
548 *sizeOut = static_cast<size_t>(dataSize);
549 return true;
550}
551
Olli Etuaho855d9642017-05-17 14:05:06 +0300552bool ProgramGL::getUniformBlockMemberInfo(const std::string & /* memberUniformName */,
553 const std::string &memberUniformMappedName,
Jamie Madill4a3c2342015-10-08 12:58:45 -0400554 sh::BlockMemberInfo *memberInfoOut) const
555{
556 GLuint uniformIndex;
Olli Etuaho855d9642017-05-17 14:05:06 +0300557 const GLchar *memberNameGLStr = memberUniformMappedName.c_str();
Jamie Madill4a3c2342015-10-08 12:58:45 -0400558 mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
559
560 if (uniformIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400561 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400562 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
563 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400564 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400565
566 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
567 &memberInfoOut->offset);
568 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
569 &memberInfoOut->arrayStride);
570 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
571 &memberInfoOut->matrixStride);
572
573 // TODO(jmadill): possibly determine this at the gl::Program level.
574 GLint isRowMajorMatrix = 0;
575 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
576 &isRowMajorMatrix);
577 memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
578 return true;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400579}
Jamie Madill4a3c2342015-10-08 12:58:45 -0400580
Sami Väisänen46eaa942016-06-29 10:26:37 +0300581void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
582 GLenum genMode,
583 GLint components,
584 const GLfloat *coeffs)
585{
586 ASSERT(mEnablePathRendering);
587
588 for (const auto &input : mPathRenderingFragmentInputs)
589 {
Olli Etuaho855d9642017-05-17 14:05:06 +0300590 if (input.mappedName == inputName)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300591 {
592 mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
593 components, coeffs);
594 ASSERT(mFunctions->getError() == GL_NO_ERROR);
595 return;
596 }
597 }
598
599}
600
Geoff Lang65a0be92015-10-02 09:57:30 -0400601void ProgramGL::preLink()
602{
603 // Reset the program state
604 mUniformRealLocationMap.clear();
605 mUniformBlockRealLocationMap.clear();
Sami Väisänen46eaa942016-06-29 10:26:37 +0300606 mPathRenderingFragmentInputs.clear();
Martin Radev4e619f52017-08-09 11:50:06 +0300607
608 mMultiviewBaseViewLayerIndexUniformLocation = -1;
Geoff Lang65a0be92015-10-02 09:57:30 -0400609}
610
611bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
612{
613 GLint linkStatus = GL_FALSE;
614 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
615 if (linkStatus == GL_FALSE)
616 {
617 // Linking failed, put the error into the info log
618 GLint infoLogLength = 0;
619 mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
620
Geoff Lang65a0be92015-10-02 09:57:30 -0400621 // Info log length includes the null terminator, so 1 means that the info log is an empty
622 // string.
623 if (infoLogLength > 1)
624 {
625 std::vector<char> buf(infoLogLength);
626 mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
627
628 mFunctions->deleteProgram(mProgramID);
629 mProgramID = 0;
630
631 infoLog << buf.data();
632
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500633 WARN() << "Program link failed unexpectedly: " << buf.data();
Geoff Lang65a0be92015-10-02 09:57:30 -0400634 }
635 else
636 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500637 WARN() << "Program link failed unexpectedly with no info log.";
Geoff Lang65a0be92015-10-02 09:57:30 -0400638 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400639
640 // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
641 return false;
642 }
643
644 return true;
645}
646
647void ProgramGL::postLink()
648{
649 // Query the uniform information
650 ASSERT(mUniformRealLocationMap.empty());
Jamie Madill48ef11b2016-04-27 15:21:52 -0400651 const auto &uniformLocations = mState.getUniformLocations();
652 const auto &uniforms = mState.getUniforms();
Geoff Lang65a0be92015-10-02 09:57:30 -0400653 mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
654 for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
655 {
656 const auto &entry = uniformLocations[uniformLocation];
Jamie Madillfb997ec2017-09-20 15:44:27 -0400657 if (!entry.used())
Geoff Lang65a0be92015-10-02 09:57:30 -0400658 {
659 continue;
660 }
661
Olli Etuahoc8538042017-09-27 11:20:15 +0300662 // From the GLES 3.0.5 spec:
Geoff Lang65a0be92015-10-02 09:57:30 -0400663 // "Locations for sequential array indices are not required to be sequential."
664 const gl::LinkedUniform &uniform = uniforms[entry.index];
665 std::stringstream fullNameStr;
Olli Etuaho855d9642017-05-17 14:05:06 +0300666 fullNameStr << uniform.mappedName;
Geoff Lang65a0be92015-10-02 09:57:30 -0400667 if (uniform.isArray())
668 {
Olli Etuahoc8538042017-09-27 11:20:15 +0300669 for (auto arrayElementIndexIt = entry.arrayIndices.rbegin();
670 arrayElementIndexIt != entry.arrayIndices.rend(); ++arrayElementIndexIt)
671 {
672 fullNameStr << "[" << (*arrayElementIndexIt) << "]";
673 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400674 }
675 const std::string &fullName = fullNameStr.str();
676
677 GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
678 mUniformRealLocationMap[uniformLocation] = realLocation;
679 }
680
Martin Radev4e619f52017-08-09 11:50:06 +0300681 if (mState.usesMultiview())
682 {
683 mMultiviewBaseViewLayerIndexUniformLocation =
Olli Etuaho855d9642017-05-17 14:05:06 +0300684 mFunctions->getUniformLocation(mProgramID, "multiviewBaseViewLayerIndex");
Martin Radev4e619f52017-08-09 11:50:06 +0300685 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
686 }
687
Sami Väisänen46eaa942016-06-29 10:26:37 +0300688 // Discover CHROMIUM_path_rendering fragment inputs if enabled.
689 if (!mEnablePathRendering)
690 return;
691
692 GLint numFragmentInputs = 0;
693 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
694 &numFragmentInputs);
695 if (numFragmentInputs <= 0)
696 return;
697
698 GLint maxNameLength = 0;
699 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
700 &maxNameLength);
701 ASSERT(maxNameLength);
702
703 for (GLint i = 0; i < numFragmentInputs; ++i)
704 {
Olli Etuaho855d9642017-05-17 14:05:06 +0300705 std::string mappedName;
706 mappedName.resize(maxNameLength);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300707
708 GLsizei nameLen = 0;
709 mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
Olli Etuaho855d9642017-05-17 14:05:06 +0300710 &nameLen, &mappedName[0]);
711 mappedName.resize(nameLen);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300712
713 // Ignore built-ins
Olli Etuaho855d9642017-05-17 14:05:06 +0300714 if (angle::BeginsWith(mappedName, "gl_"))
Sami Väisänen46eaa942016-06-29 10:26:37 +0300715 continue;
716
717 const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
718 GLint queryResults[ArraySize(kQueryProperties)];
719 GLsizei queryLength = 0;
720
Geoff Lang3f6a3982016-07-15 15:20:45 -0400721 mFunctions->getProgramResourceiv(
722 mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
723 kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
724 queryResults);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300725
Olli Etuahoe3191712016-07-18 16:01:10 +0300726 ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300727
Geoff Lang3f6a3982016-07-15 15:20:45 -0400728 PathRenderingFragmentInput baseElementInput;
Olli Etuaho855d9642017-05-17 14:05:06 +0300729 baseElementInput.mappedName = mappedName;
Geoff Lang3f6a3982016-07-15 15:20:45 -0400730 baseElementInput.location = queryResults[0];
731 mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300732
733 // If the input is an array it's denoted by [0] suffix on the variable
734 // name. We'll then create an entry per each array index where index > 0
Olli Etuaho855d9642017-05-17 14:05:06 +0300735 if (angle::EndsWith(mappedName, "[0]"))
Sami Väisänen46eaa942016-06-29 10:26:37 +0300736 {
737 // drop the suffix
Olli Etuaho855d9642017-05-17 14:05:06 +0300738 mappedName.resize(mappedName.size() - 3);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300739
740 const auto arraySize = queryResults[1];
741 const auto baseLocation = queryResults[0];
742
Geoff Lang3f6a3982016-07-15 15:20:45 -0400743 for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300744 {
Geoff Lang3f6a3982016-07-15 15:20:45 -0400745 PathRenderingFragmentInput arrayElementInput;
Olli Etuaho855d9642017-05-17 14:05:06 +0300746 arrayElementInput.mappedName = mappedName + "[" + ToString(arrayIndex) + "]";
Geoff Lang3f6a3982016-07-15 15:20:45 -0400747 arrayElementInput.location = baseLocation + arrayIndex;
748 mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300749 }
750 }
751 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400752}
753
Martin Radev4e619f52017-08-09 11:50:06 +0300754void ProgramGL::enableSideBySideRenderingPath() const
755{
756 ASSERT(mState.usesMultiview());
757 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
758
759 ASSERT(mFunctions->programUniform1i != nullptr);
760 mFunctions->programUniform1i(mProgramID, mMultiviewBaseViewLayerIndexUniformLocation, -1);
761}
762
763void ProgramGL::enableLayeredRenderingPath(int baseViewIndex) const
764{
765 ASSERT(mState.usesMultiview());
766 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
767
768 ASSERT(mFunctions->programUniform1i != nullptr);
769 mFunctions->programUniform1i(mProgramID, mMultiviewBaseViewLayerIndexUniformLocation,
770 baseViewIndex);
771}
772
Jamie Madill54164b02017-08-28 15:17:37 -0400773void ProgramGL::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
774{
775 mFunctions->getUniformfv(mProgramID, uniLoc(location), params);
776}
777
778void ProgramGL::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
779{
780 mFunctions->getUniformiv(mProgramID, uniLoc(location), params);
781}
782
783void ProgramGL::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
784{
785 mFunctions->getUniformuiv(mProgramID, uniLoc(location), params);
786}
787
Jamie Madillfb997ec2017-09-20 15:44:27 -0400788void ProgramGL::markUnusedUniformLocations(std::vector<gl::VariableLocation> *uniformLocations,
789 std::vector<gl::SamplerBinding> *samplerBindings)
Jamie Madill54164b02017-08-28 15:17:37 -0400790{
791 GLint maxLocation = static_cast<GLint>(uniformLocations->size());
792 for (GLint location = 0; location < maxLocation; ++location)
793 {
794 if (uniLoc(location) == -1)
795 {
Jamie Madillfb997ec2017-09-20 15:44:27 -0400796 auto &locationRef = (*uniformLocations)[location];
797 if (mState.isSamplerUniformIndex(locationRef.index))
798 {
799 GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationRef.index);
800 (*samplerBindings)[samplerIndex].unreferenced = true;
801 }
802 locationRef.markUnused();
Jamie Madill54164b02017-08-28 15:17:37 -0400803 }
804 }
805}
806
Jamie Madill4a3c2342015-10-08 12:58:45 -0400807} // namespace rx