blob: 466f1fa8531481312e9618e4143a2e76da30c2d9 [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"
Jamie Madill6db1c2e2017-11-08 09:17:40 -050017#include "libANGLE/ProgramLinkedResources.h"
Jamie Madillc564c072017-06-01 12:45:42 -040018#include "libANGLE/Uniform.h"
Jamie Madilla7d12dc2016-12-13 15:08:19 -050019#include "libANGLE/renderer/gl/ContextGL.h"
Geoff Langb1f435e2015-02-20 10:01:01 -050020#include "libANGLE/renderer/gl/FunctionsGL.h"
21#include "libANGLE/renderer/gl/ShaderGL.h"
22#include "libANGLE/renderer/gl/StateManagerGL.h"
Philippe Hamel40911192016-04-07 16:45:50 -040023#include "libANGLE/renderer/gl/WorkaroundsGL.h"
unknownb4a3af22015-11-25 15:02:51 -050024#include "platform/Platform.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050025
26namespace rx
27{
28
Jamie Madill48ef11b2016-04-27 15:21:52 -040029ProgramGL::ProgramGL(const gl::ProgramState &data,
Jamie Madill5c6b7bf2015-08-17 12:53:35 -040030 const FunctionsGL *functions,
Philippe Hamel40911192016-04-07 16:45:50 -040031 const WorkaroundsGL &workarounds,
Sami Väisänen46eaa942016-06-29 10:26:37 +030032 StateManagerGL *stateManager,
33 bool enablePathRendering)
Philippe Hamel40911192016-04-07 16:45:50 -040034 : ProgramImpl(data),
35 mFunctions(functions),
36 mWorkarounds(workarounds),
37 mStateManager(stateManager),
Sami Väisänen46eaa942016-06-29 10:26:37 +030038 mEnablePathRendering(enablePathRendering),
Martin Radev4e619f52017-08-09 11:50:06 +030039 mMultiviewBaseViewLayerIndexUniformLocation(-1),
Philippe Hamel40911192016-04-07 16:45:50 -040040 mProgramID(0)
Geoff Langb1f435e2015-02-20 10:01:01 -050041{
42 ASSERT(mFunctions);
43 ASSERT(mStateManager);
Geoff Lang0ca53782015-05-07 13:49:39 -040044
45 mProgramID = mFunctions->createProgram();
Geoff Langb1f435e2015-02-20 10:01:01 -050046}
Geoff Langf9a6f082015-01-22 13:32:49 -050047
48ProgramGL::~ProgramGL()
Geoff Langb1f435e2015-02-20 10:01:01 -050049{
Geoff Lang0ca53782015-05-07 13:49:39 -040050 mFunctions->deleteProgram(mProgramID);
51 mProgramID = 0;
Geoff Langb1f435e2015-02-20 10:01:01 -050052}
Geoff Langf9a6f082015-01-22 13:32:49 -050053
Jamie Madill9cf9e872017-06-05 12:59:25 -040054gl::LinkResult ProgramGL::load(const gl::Context *context,
55 gl::InfoLog &infoLog,
56 gl::BinaryInputStream *stream)
Geoff Langf9a6f082015-01-22 13:32:49 -050057{
Geoff Lang65a0be92015-10-02 09:57:30 -040058 preLink();
59
60 // Read the binary format, size and blob
61 GLenum binaryFormat = stream->readInt<GLenum>();
62 GLint binaryLength = stream->readInt<GLint>();
63 const uint8_t *binary = stream->data() + stream->offset();
64 stream->skip(binaryLength);
65
66 // Load the binary
67 mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength);
68
69 // Verify that the program linked
70 if (!checkLinkStatus(infoLog))
71 {
Jamie Madillb0a838b2016-11-13 20:02:12 -050072 return false;
Geoff Lang65a0be92015-10-02 09:57:30 -040073 }
74
75 postLink();
Jamie Madill27a60632017-06-30 15:12:01 -040076 reapplyUBOBindingsIfNeeded(context);
Jamie Madilla7d12dc2016-12-13 15:08:19 -050077
Jamie Madillb0a838b2016-11-13 20:02:12 -050078 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -050079}
80
Jamie Madill27a60632017-06-30 15:12:01 -040081void ProgramGL::save(const gl::Context *context, gl::BinaryOutputStream *stream)
Geoff Langf9a6f082015-01-22 13:32:49 -050082{
Geoff Lang65a0be92015-10-02 09:57:30 -040083 GLint binaryLength = 0;
84 mFunctions->getProgramiv(mProgramID, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
85
86 std::vector<uint8_t> binary(binaryLength);
87 GLenum binaryFormat = GL_NONE;
88 mFunctions->getProgramBinary(mProgramID, binaryLength, &binaryLength, &binaryFormat,
89 &binary[0]);
90
91 stream->writeInt(binaryFormat);
92 stream->writeInt(binaryLength);
93 stream->writeBytes(&binary[0], binaryLength);
Jamie Madill27a60632017-06-30 15:12:01 -040094
95 reapplyUBOBindingsIfNeeded(context);
96}
97
98void ProgramGL::reapplyUBOBindingsIfNeeded(const gl::Context *context)
99{
100 // Re-apply UBO bindings to work around driver bugs.
101 const WorkaroundsGL &workaroundsGL = GetImplAs<ContextGL>(context)->getWorkaroundsGL();
102 if (workaroundsGL.reapplyUBOBindingsAfterUsingBinaryProgram)
103 {
104 const auto &blocks = mState.getUniformBlocks();
105 for (size_t blockIndex : mState.getActiveUniformBlockBindingsMask())
106 {
107 setUniformBlockBinding(static_cast<GLuint>(blockIndex), blocks[blockIndex].binding);
108 }
109 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500110}
111
Geoff Langc5629752015-12-07 16:29:04 -0500112void ProgramGL::setBinaryRetrievableHint(bool retrievable)
113{
Geoff Lang65a0be92015-10-02 09:57:30 -0400114 // glProgramParameteri isn't always available on ES backends.
115 if (mFunctions->programParameteri)
116 {
117 mFunctions->programParameteri(mProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT,
118 retrievable ? GL_TRUE : GL_FALSE);
119 }
Geoff Langc5629752015-12-07 16:29:04 -0500120}
121
Yunchao He61afff12017-03-14 15:34:03 +0800122void ProgramGL::setSeparable(bool separable)
123{
124 mFunctions->programParameteri(mProgramID, GL_PROGRAM_SEPARABLE, separable ? GL_TRUE : GL_FALSE);
125}
126
Jamie Madill9cf9e872017-06-05 12:59:25 -0400127gl::LinkResult ProgramGL::link(const gl::Context *context,
Jamie Madillc9727f32017-11-07 12:37:07 -0500128 const gl::ProgramLinkedResources &resources,
Jamie Madill9cf9e872017-06-05 12:59:25 -0400129 gl::InfoLog &infoLog)
Geoff Langf9a6f082015-01-22 13:32:49 -0500130{
Geoff Lang65a0be92015-10-02 09:57:30 -0400131 preLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500132
Martin Radev4c4c8e72016-08-04 12:25:34 +0300133 if (mState.getAttachedComputeShader())
Geoff Lang1a683462015-09-29 15:09:59 -0400134 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300135 const ShaderGL *computeShaderGL = GetImplAs<ShaderGL>(mState.getAttachedComputeShader());
Geoff Lang1a683462015-09-29 15:09:59 -0400136
Martin Radev4c4c8e72016-08-04 12:25:34 +0300137 mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID());
138
139 // Link and verify
140 mFunctions->linkProgram(mProgramID);
141
142 // Detach the shaders
143 mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID());
Geoff Lang1a683462015-09-29 15:09:59 -0400144 }
145 else
146 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300147 // Set the transform feedback state
Olli Etuaho855d9642017-05-17 14:05:06 +0300148 std::vector<std::string> transformFeedbackVaryingMappedNames;
Martin Radev4c4c8e72016-08-04 12:25:34 +0300149 for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
Geoff Lang1528e562015-08-24 15:10:58 -0400150 {
Olli Etuaho855d9642017-05-17 14:05:06 +0300151 std::string tfVaryingMappedName =
152 mState.getAttachedVertexShader()->getTransformFeedbackVaryingMappedName(tfVarying,
153 context);
154 transformFeedbackVaryingMappedNames.push_back(tfVaryingMappedName);
Geoff Lang1528e562015-08-24 15:10:58 -0400155 }
156
Olli Etuaho855d9642017-05-17 14:05:06 +0300157 if (transformFeedbackVaryingMappedNames.empty())
Martin Radev4c4c8e72016-08-04 12:25:34 +0300158 {
159 if (mFunctions->transformFeedbackVaryings)
160 {
161 mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
162 mState.getTransformFeedbackBufferMode());
163 }
164 }
165 else
166 {
167 ASSERT(mFunctions->transformFeedbackVaryings);
Olli Etuaho855d9642017-05-17 14:05:06 +0300168 std::vector<const GLchar *> transformFeedbackVaryings;
169 for (const auto &varying : transformFeedbackVaryingMappedNames)
170 {
171 transformFeedbackVaryings.push_back(varying.c_str());
172 }
Martin Radev4c4c8e72016-08-04 12:25:34 +0300173 mFunctions->transformFeedbackVaryings(
Olli Etuaho855d9642017-05-17 14:05:06 +0300174 mProgramID, static_cast<GLsizei>(transformFeedbackVaryingMappedNames.size()),
Martin Radev4c4c8e72016-08-04 12:25:34 +0300175 &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
176 }
177
178 const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mState.getAttachedVertexShader());
179 const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader());
180
181 // Attach the shaders
182 mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
183 mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
184
185 // Bind attribute locations to match the GL layer.
186 for (const sh::Attribute &attribute : mState.getAttributes())
187 {
Corentin Wallez6c1cbf52016-11-23 12:44:35 -0500188 if (!attribute.staticUse || attribute.isBuiltIn())
Martin Radev4c4c8e72016-08-04 12:25:34 +0300189 {
190 continue;
191 }
192
Olli Etuaho855d9642017-05-17 14:05:06 +0300193 mFunctions->bindAttribLocation(mProgramID, attribute.location,
194 attribute.mappedName.c_str());
Martin Radev4c4c8e72016-08-04 12:25:34 +0300195 }
196
197 // Link and verify
198 mFunctions->linkProgram(mProgramID);
199
200 // Detach the shaders
201 mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
202 mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
Geoff Lang1528e562015-08-24 15:10:58 -0400203 }
204
Geoff Lang0ca53782015-05-07 13:49:39 -0400205 // Verify the link
Geoff Lang65a0be92015-10-02 09:57:30 -0400206 if (!checkLinkStatus(infoLog))
Geoff Langb1f435e2015-02-20 10:01:01 -0500207 {
Jamie Madillb0a838b2016-11-13 20:02:12 -0500208 return false;
Geoff Langb1f435e2015-02-20 10:01:01 -0500209 }
210
Philippe Hamel40911192016-04-07 16:45:50 -0400211 if (mWorkarounds.alwaysCallUseProgramAfterLink)
212 {
213 mStateManager->forceUseProgram(mProgramID);
214 }
215
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500216 linkResources(resources);
Geoff Lang65a0be92015-10-02 09:57:30 -0400217 postLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500218
Jamie Madillb0a838b2016-11-13 20:02:12 -0500219 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -0500220}
221
Jamie Madill36cfd6a2015-08-18 10:46:20 -0400222GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
223{
224 // TODO(jmadill): implement validate
225 return true;
226}
227
Geoff Langf9a6f082015-01-22 13:32:49 -0500228void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
229{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800230 if (mFunctions->programUniform1fv != nullptr)
231 {
232 mFunctions->programUniform1fv(mProgramID, uniLoc(location), count, v);
233 }
234 else
235 {
236 mStateManager->useProgram(mProgramID);
237 mFunctions->uniform1fv(uniLoc(location), count, v);
238 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500239}
240
241void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
242{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800243 if (mFunctions->programUniform2fv != nullptr)
244 {
245 mFunctions->programUniform2fv(mProgramID, uniLoc(location), count, v);
246 }
247 else
248 {
249 mStateManager->useProgram(mProgramID);
250 mFunctions->uniform2fv(uniLoc(location), count, v);
251 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500252}
253
254void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
255{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800256 if (mFunctions->programUniform3fv != nullptr)
257 {
258 mFunctions->programUniform3fv(mProgramID, uniLoc(location), count, v);
259 }
260 else
261 {
262 mStateManager->useProgram(mProgramID);
263 mFunctions->uniform3fv(uniLoc(location), count, v);
264 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500265}
266
267void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
268{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800269 if (mFunctions->programUniform4fv != nullptr)
270 {
271 mFunctions->programUniform4fv(mProgramID, uniLoc(location), count, v);
272 }
273 else
274 {
275 mStateManager->useProgram(mProgramID);
276 mFunctions->uniform4fv(uniLoc(location), count, v);
277 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500278}
279
280void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
281{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800282 if (mFunctions->programUniform1iv != nullptr)
283 {
284 mFunctions->programUniform1iv(mProgramID, uniLoc(location), count, v);
285 }
286 else
287 {
288 mStateManager->useProgram(mProgramID);
289 mFunctions->uniform1iv(uniLoc(location), count, v);
290 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500291}
292
293void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
294{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800295 if (mFunctions->programUniform2iv != nullptr)
296 {
297 mFunctions->programUniform2iv(mProgramID, uniLoc(location), count, v);
298 }
299 else
300 {
301 mStateManager->useProgram(mProgramID);
302 mFunctions->uniform2iv(uniLoc(location), count, v);
303 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500304}
305
306void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
307{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800308 if (mFunctions->programUniform3iv != nullptr)
309 {
310 mFunctions->programUniform3iv(mProgramID, uniLoc(location), count, v);
311 }
312 else
313 {
314 mStateManager->useProgram(mProgramID);
315 mFunctions->uniform3iv(uniLoc(location), count, v);
316 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500317}
318
319void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
320{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800321 if (mFunctions->programUniform4iv != nullptr)
322 {
323 mFunctions->programUniform4iv(mProgramID, uniLoc(location), count, v);
324 }
325 else
326 {
327 mStateManager->useProgram(mProgramID);
328 mFunctions->uniform4iv(uniLoc(location), count, v);
329 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500330}
331
332void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
333{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800334 if (mFunctions->programUniform1uiv != nullptr)
335 {
336 mFunctions->programUniform1uiv(mProgramID, uniLoc(location), count, v);
337 }
338 else
339 {
340 mStateManager->useProgram(mProgramID);
341 mFunctions->uniform1uiv(uniLoc(location), count, v);
342 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500343}
344
345void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
346{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800347 if (mFunctions->programUniform2uiv != nullptr)
348 {
349 mFunctions->programUniform2uiv(mProgramID, uniLoc(location), count, v);
350 }
351 else
352 {
353 mStateManager->useProgram(mProgramID);
354 mFunctions->uniform2uiv(uniLoc(location), count, v);
355 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500356}
357
358void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
359{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800360 if (mFunctions->programUniform3uiv != nullptr)
361 {
362 mFunctions->programUniform3uiv(mProgramID, uniLoc(location), count, v);
363 }
364 else
365 {
366 mStateManager->useProgram(mProgramID);
367 mFunctions->uniform3uiv(uniLoc(location), count, v);
368 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500369}
370
371void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
372{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800373 if (mFunctions->programUniform4uiv != nullptr)
374 {
375 mFunctions->programUniform4uiv(mProgramID, uniLoc(location), count, v);
376 }
377 else
378 {
379 mStateManager->useProgram(mProgramID);
380 mFunctions->uniform4uiv(uniLoc(location), count, v);
381 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500382}
383
384void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
385{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800386 if (mFunctions->programUniformMatrix2fv != nullptr)
387 {
388 mFunctions->programUniformMatrix2fv(mProgramID, uniLoc(location), count, transpose, value);
389 }
390 else
391 {
392 mStateManager->useProgram(mProgramID);
393 mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
394 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500395}
396
397void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
398{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800399 if (mFunctions->programUniformMatrix3fv != nullptr)
400 {
401 mFunctions->programUniformMatrix3fv(mProgramID, uniLoc(location), count, transpose, value);
402 }
403 else
404 {
405 mStateManager->useProgram(mProgramID);
406 mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
407 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500408}
409
410void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
411{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800412 if (mFunctions->programUniformMatrix4fv != nullptr)
413 {
414 mFunctions->programUniformMatrix4fv(mProgramID, uniLoc(location), count, transpose, value);
415 }
416 else
417 {
418 mStateManager->useProgram(mProgramID);
419 mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
420 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500421}
422
423void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
424{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800425 if (mFunctions->programUniformMatrix2x3fv != nullptr)
426 {
427 mFunctions->programUniformMatrix2x3fv(mProgramID, uniLoc(location), count, transpose,
428 value);
429 }
430 else
431 {
432 mStateManager->useProgram(mProgramID);
433 mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
434 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500435}
436
437void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
438{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800439 if (mFunctions->programUniformMatrix3x2fv != nullptr)
440 {
441 mFunctions->programUniformMatrix3x2fv(mProgramID, uniLoc(location), count, transpose,
442 value);
443 }
444 else
445 {
446 mStateManager->useProgram(mProgramID);
447 mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
448 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500449}
450
451void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
452{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800453 if (mFunctions->programUniformMatrix2x4fv != nullptr)
454 {
455 mFunctions->programUniformMatrix2x4fv(mProgramID, uniLoc(location), count, transpose,
456 value);
457 }
458 else
459 {
460 mStateManager->useProgram(mProgramID);
461 mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
462 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500463}
464
465void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
466{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800467 if (mFunctions->programUniformMatrix4x2fv != nullptr)
468 {
469 mFunctions->programUniformMatrix4x2fv(mProgramID, uniLoc(location), count, transpose,
470 value);
471 }
472 else
473 {
474 mStateManager->useProgram(mProgramID);
475 mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
476 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500477}
478
479void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
480{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800481 if (mFunctions->programUniformMatrix3x4fv != nullptr)
482 {
483 mFunctions->programUniformMatrix3x4fv(mProgramID, uniLoc(location), count, transpose,
484 value);
485 }
486 else
487 {
488 mStateManager->useProgram(mProgramID);
489 mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
490 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500491}
492
493void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
494{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800495 if (mFunctions->programUniformMatrix4x3fv != nullptr)
496 {
497 mFunctions->programUniformMatrix4x3fv(mProgramID, uniLoc(location), count, transpose,
498 value);
499 }
500 else
501 {
502 mStateManager->useProgram(mProgramID);
503 mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
504 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500505}
506
Geoff Lang5d124a62015-09-15 13:03:27 -0400507void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
508{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400509 // Lazy init
510 if (mUniformBlockRealLocationMap.empty())
511 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400512 mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
Jiajia Qin729b2c62017-08-14 09:36:11 +0800513 for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill4a3c2342015-10-08 12:58:45 -0400514 {
Olli Etuaho855d9642017-05-17 14:05:06 +0300515 const std::string &mappedNameWithIndex = uniformBlock.mappedNameWithArrayIndex();
516 GLuint blockIndex =
517 mFunctions->getUniformBlockIndex(mProgramID, mappedNameWithIndex.c_str());
Jamie Madill4a3c2342015-10-08 12:58:45 -0400518 mUniformBlockRealLocationMap.push_back(blockIndex);
519 }
520 }
521
522 GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
523 if (realBlockIndex != GL_INVALID_INDEX)
524 {
525 mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
526 }
Geoff Lang5d124a62015-09-15 13:03:27 -0400527}
528
Geoff Langb1f435e2015-02-20 10:01:01 -0500529GLuint ProgramGL::getProgramID() const
530{
531 return mProgramID;
532}
533
Olli Etuaho855d9642017-05-17 14:05:06 +0300534bool ProgramGL::getUniformBlockSize(const std::string & /* blockName */,
535 const std::string &blockMappedName,
536 size_t *sizeOut) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400537{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400538 ASSERT(mProgramID != 0u);
Geoff Lang5d124a62015-09-15 13:03:27 -0400539
Olli Etuaho855d9642017-05-17 14:05:06 +0300540 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockMappedName.c_str());
Jamie Madill4a3c2342015-10-08 12:58:45 -0400541 if (blockIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400542 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400543 *sizeOut = 0;
544 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400545 }
546
Jamie Madill4a3c2342015-10-08 12:58:45 -0400547 GLint dataSize = 0;
548 mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
549 &dataSize);
550 *sizeOut = static_cast<size_t>(dataSize);
551 return true;
552}
553
Olli Etuaho855d9642017-05-17 14:05:06 +0300554bool ProgramGL::getUniformBlockMemberInfo(const std::string & /* memberUniformName */,
555 const std::string &memberUniformMappedName,
Jamie Madill4a3c2342015-10-08 12:58:45 -0400556 sh::BlockMemberInfo *memberInfoOut) const
557{
558 GLuint uniformIndex;
Olli Etuaho855d9642017-05-17 14:05:06 +0300559 const GLchar *memberNameGLStr = memberUniformMappedName.c_str();
Jamie Madill4a3c2342015-10-08 12:58:45 -0400560 mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
561
562 if (uniformIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400563 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400564 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
565 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400566 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400567
568 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
569 &memberInfoOut->offset);
570 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
571 &memberInfoOut->arrayStride);
572 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
573 &memberInfoOut->matrixStride);
574
575 // TODO(jmadill): possibly determine this at the gl::Program level.
576 GLint isRowMajorMatrix = 0;
577 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
578 &isRowMajorMatrix);
579 memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
580 return true;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400581}
Jamie Madill4a3c2342015-10-08 12:58:45 -0400582
Sami Väisänen46eaa942016-06-29 10:26:37 +0300583void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
584 GLenum genMode,
585 GLint components,
586 const GLfloat *coeffs)
587{
588 ASSERT(mEnablePathRendering);
589
590 for (const auto &input : mPathRenderingFragmentInputs)
591 {
Olli Etuaho855d9642017-05-17 14:05:06 +0300592 if (input.mappedName == inputName)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300593 {
594 mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
595 components, coeffs);
596 ASSERT(mFunctions->getError() == GL_NO_ERROR);
597 return;
598 }
599 }
600
601}
602
Geoff Lang65a0be92015-10-02 09:57:30 -0400603void ProgramGL::preLink()
604{
605 // Reset the program state
606 mUniformRealLocationMap.clear();
607 mUniformBlockRealLocationMap.clear();
Sami Väisänen46eaa942016-06-29 10:26:37 +0300608 mPathRenderingFragmentInputs.clear();
Martin Radev4e619f52017-08-09 11:50:06 +0300609
610 mMultiviewBaseViewLayerIndexUniformLocation = -1;
Geoff Lang65a0be92015-10-02 09:57:30 -0400611}
612
613bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
614{
615 GLint linkStatus = GL_FALSE;
616 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
617 if (linkStatus == GL_FALSE)
618 {
619 // Linking failed, put the error into the info log
620 GLint infoLogLength = 0;
621 mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
622
Geoff Lang65a0be92015-10-02 09:57:30 -0400623 // Info log length includes the null terminator, so 1 means that the info log is an empty
624 // string.
625 if (infoLogLength > 1)
626 {
627 std::vector<char> buf(infoLogLength);
628 mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
629
630 mFunctions->deleteProgram(mProgramID);
631 mProgramID = 0;
632
633 infoLog << buf.data();
634
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500635 WARN() << "Program link failed unexpectedly: " << buf.data();
Geoff Lang65a0be92015-10-02 09:57:30 -0400636 }
637 else
638 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500639 WARN() << "Program link failed unexpectedly with no info log.";
Geoff Lang65a0be92015-10-02 09:57:30 -0400640 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400641
642 // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
643 return false;
644 }
645
646 return true;
647}
648
649void ProgramGL::postLink()
650{
651 // Query the uniform information
652 ASSERT(mUniformRealLocationMap.empty());
Jamie Madill48ef11b2016-04-27 15:21:52 -0400653 const auto &uniformLocations = mState.getUniformLocations();
654 const auto &uniforms = mState.getUniforms();
Geoff Lang65a0be92015-10-02 09:57:30 -0400655 mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
656 for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
657 {
658 const auto &entry = uniformLocations[uniformLocation];
Jamie Madillfb997ec2017-09-20 15:44:27 -0400659 if (!entry.used())
Geoff Lang65a0be92015-10-02 09:57:30 -0400660 {
661 continue;
662 }
663
Olli Etuahoc8538042017-09-27 11:20:15 +0300664 // From the GLES 3.0.5 spec:
Geoff Lang65a0be92015-10-02 09:57:30 -0400665 // "Locations for sequential array indices are not required to be sequential."
666 const gl::LinkedUniform &uniform = uniforms[entry.index];
667 std::stringstream fullNameStr;
Geoff Lang65a0be92015-10-02 09:57:30 -0400668 if (uniform.isArray())
669 {
Olli Etuahod2551232017-10-26 20:03:33 +0300670 ASSERT(angle::EndsWith(uniform.mappedName, "[0]"));
671 fullNameStr << uniform.mappedName.substr(0, uniform.mappedName.length() - 3);
Olli Etuaho1734e172017-10-27 15:30:27 +0300672 fullNameStr << "[" << entry.arrayIndex << "]";
Olli Etuahod2551232017-10-26 20:03:33 +0300673 }
674 else
675 {
676 fullNameStr << uniform.mappedName;
Geoff Lang65a0be92015-10-02 09:57:30 -0400677 }
678 const std::string &fullName = fullNameStr.str();
679
680 GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
681 mUniformRealLocationMap[uniformLocation] = realLocation;
682 }
683
Martin Radev4e619f52017-08-09 11:50:06 +0300684 if (mState.usesMultiview())
685 {
686 mMultiviewBaseViewLayerIndexUniformLocation =
Olli Etuaho855d9642017-05-17 14:05:06 +0300687 mFunctions->getUniformLocation(mProgramID, "multiviewBaseViewLayerIndex");
Martin Radev4e619f52017-08-09 11:50:06 +0300688 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
689 }
690
Sami Väisänen46eaa942016-06-29 10:26:37 +0300691 // Discover CHROMIUM_path_rendering fragment inputs if enabled.
692 if (!mEnablePathRendering)
693 return;
694
695 GLint numFragmentInputs = 0;
696 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
697 &numFragmentInputs);
698 if (numFragmentInputs <= 0)
699 return;
700
701 GLint maxNameLength = 0;
702 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
703 &maxNameLength);
704 ASSERT(maxNameLength);
705
706 for (GLint i = 0; i < numFragmentInputs; ++i)
707 {
Olli Etuaho855d9642017-05-17 14:05:06 +0300708 std::string mappedName;
709 mappedName.resize(maxNameLength);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300710
711 GLsizei nameLen = 0;
712 mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
Olli Etuaho855d9642017-05-17 14:05:06 +0300713 &nameLen, &mappedName[0]);
714 mappedName.resize(nameLen);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300715
716 // Ignore built-ins
Olli Etuaho855d9642017-05-17 14:05:06 +0300717 if (angle::BeginsWith(mappedName, "gl_"))
Sami Väisänen46eaa942016-06-29 10:26:37 +0300718 continue;
719
720 const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
721 GLint queryResults[ArraySize(kQueryProperties)];
722 GLsizei queryLength = 0;
723
Geoff Lang3f6a3982016-07-15 15:20:45 -0400724 mFunctions->getProgramResourceiv(
725 mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
726 kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
727 queryResults);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300728
Olli Etuahoe3191712016-07-18 16:01:10 +0300729 ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300730
Geoff Lang3f6a3982016-07-15 15:20:45 -0400731 PathRenderingFragmentInput baseElementInput;
Olli Etuaho855d9642017-05-17 14:05:06 +0300732 baseElementInput.mappedName = mappedName;
Geoff Lang3f6a3982016-07-15 15:20:45 -0400733 baseElementInput.location = queryResults[0];
734 mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300735
736 // If the input is an array it's denoted by [0] suffix on the variable
737 // name. We'll then create an entry per each array index where index > 0
Olli Etuaho855d9642017-05-17 14:05:06 +0300738 if (angle::EndsWith(mappedName, "[0]"))
Sami Väisänen46eaa942016-06-29 10:26:37 +0300739 {
740 // drop the suffix
Olli Etuaho855d9642017-05-17 14:05:06 +0300741 mappedName.resize(mappedName.size() - 3);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300742
743 const auto arraySize = queryResults[1];
744 const auto baseLocation = queryResults[0];
745
Geoff Lang3f6a3982016-07-15 15:20:45 -0400746 for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300747 {
Geoff Lang3f6a3982016-07-15 15:20:45 -0400748 PathRenderingFragmentInput arrayElementInput;
Olli Etuaho855d9642017-05-17 14:05:06 +0300749 arrayElementInput.mappedName = mappedName + "[" + ToString(arrayIndex) + "]";
Geoff Lang3f6a3982016-07-15 15:20:45 -0400750 arrayElementInput.location = baseLocation + arrayIndex;
751 mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300752 }
753 }
754 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400755}
756
Martin Radev4e619f52017-08-09 11:50:06 +0300757void ProgramGL::enableSideBySideRenderingPath() const
758{
759 ASSERT(mState.usesMultiview());
760 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
761
762 ASSERT(mFunctions->programUniform1i != nullptr);
763 mFunctions->programUniform1i(mProgramID, mMultiviewBaseViewLayerIndexUniformLocation, -1);
764}
765
766void ProgramGL::enableLayeredRenderingPath(int baseViewIndex) const
767{
768 ASSERT(mState.usesMultiview());
769 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
770
771 ASSERT(mFunctions->programUniform1i != nullptr);
772 mFunctions->programUniform1i(mProgramID, mMultiviewBaseViewLayerIndexUniformLocation,
773 baseViewIndex);
774}
775
Jamie Madill54164b02017-08-28 15:17:37 -0400776void ProgramGL::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
777{
778 mFunctions->getUniformfv(mProgramID, uniLoc(location), params);
779}
780
781void ProgramGL::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
782{
783 mFunctions->getUniformiv(mProgramID, uniLoc(location), params);
784}
785
786void ProgramGL::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
787{
788 mFunctions->getUniformuiv(mProgramID, uniLoc(location), params);
789}
790
Jamie Madillfb997ec2017-09-20 15:44:27 -0400791void ProgramGL::markUnusedUniformLocations(std::vector<gl::VariableLocation> *uniformLocations,
792 std::vector<gl::SamplerBinding> *samplerBindings)
Jamie Madill54164b02017-08-28 15:17:37 -0400793{
794 GLint maxLocation = static_cast<GLint>(uniformLocations->size());
795 for (GLint location = 0; location < maxLocation; ++location)
796 {
797 if (uniLoc(location) == -1)
798 {
Jamie Madillfb997ec2017-09-20 15:44:27 -0400799 auto &locationRef = (*uniformLocations)[location];
800 if (mState.isSamplerUniformIndex(locationRef.index))
801 {
802 GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationRef.index);
803 (*samplerBindings)[samplerIndex].unreferenced = true;
804 }
805 locationRef.markUnused();
Jamie Madill54164b02017-08-28 15:17:37 -0400806 }
807 }
808}
809
Jamie Madill6db1c2e2017-11-08 09:17:40 -0500810void ProgramGL::linkResources(const gl::ProgramLinkedResources &resources)
811{
812 // Gather interface block info.
813 auto getUniformBlockSize = [this](const std::string &name, const std::string &mappedName,
814 size_t *sizeOut) {
815 return this->getUniformBlockSize(name, mappedName, sizeOut);
816 };
817
818 auto getUniformBlockMemberInfo = [this](const std::string &name, const std::string &mappedName,
819 sh::BlockMemberInfo *infoOut) {
820 return this->getUniformBlockMemberInfo(name, mappedName, infoOut);
821 };
822
823 resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo);
824
825 // TODO(jiajia.qin@intel.com): Determine correct shader storage block info.
826 auto getShaderStorageBlockSize = [](const std::string &name, const std::string &mappedName,
827 size_t *sizeOut) {
828 *sizeOut = 0;
829 return true;
830 };
831
832 auto getShaderStorageBlockMemberInfo =
833 [](const std::string &name, const std::string &mappedName, sh::BlockMemberInfo *infoOut) {
834 *infoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
835 return true;
836 };
837 resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize,
838 getShaderStorageBlockMemberInfo);
839}
840
Jamie Madill4a3c2342015-10-08 12:58:45 -0400841} // namespace rx