1 //
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
11 #include "common/angleutils.h"
12 #include "common/bitset_utils.h"
13 #include "common/debug.h"
14 #include "common/string_utils.h"
15 #include "common/utilities.h"
16 #include "libANGLE/Context.h"
17 #include "libANGLE/ProgramLinkedResources.h"
18 #include "libANGLE/Uniform.h"
19 #include "libANGLE/WorkerThread.h"
20 #include "libANGLE/queryconversions.h"
21 #include "libANGLE/renderer/gl/ContextGL.h"
22 #include "libANGLE/renderer/gl/FunctionsGL.h"
23 #include "libANGLE/renderer/gl/RendererGL.h"
24 #include "libANGLE/renderer/gl/ShaderGL.h"
25 #include "libANGLE/renderer/gl/StateManagerGL.h"
26 #include "platform/FeaturesGL.h"
27 #include "platform/Platform.h"
28
29 namespace rx
30 {
31
ProgramGL(const gl::ProgramState & data,const FunctionsGL * functions,const angle::FeaturesGL & features,StateManagerGL * stateManager,bool enablePathRendering,const std::shared_ptr<RendererGL> & renderer)32 ProgramGL::ProgramGL(const gl::ProgramState &data,
33 const FunctionsGL *functions,
34 const angle::FeaturesGL &features,
35 StateManagerGL *stateManager,
36 bool enablePathRendering,
37 const std::shared_ptr<RendererGL> &renderer)
38 : ProgramImpl(data),
39 mFunctions(functions),
40 mFeatures(features),
41 mStateManager(stateManager),
42 mEnablePathRendering(enablePathRendering),
43 mMultiviewBaseViewLayerIndexUniformLocation(-1),
44 mProgramID(0),
45 mRenderer(renderer),
46 mLinkedInParallel(false)
47 {
48 ASSERT(mFunctions);
49 ASSERT(mStateManager);
50
51 mProgramID = mFunctions->createProgram();
52 }
53
~ProgramGL()54 ProgramGL::~ProgramGL()
55 {
56 mFunctions->deleteProgram(mProgramID);
57 mProgramID = 0;
58 }
59
load(const gl::Context * context,gl::BinaryInputStream * stream,gl::InfoLog & infoLog)60 std::unique_ptr<LinkEvent> ProgramGL::load(const gl::Context *context,
61 gl::BinaryInputStream *stream,
62 gl::InfoLog &infoLog)
63 {
64 preLink();
65
66 // Read the binary format, size and blob
67 GLenum binaryFormat = stream->readInt<GLenum>();
68 GLint binaryLength = stream->readInt<GLint>();
69 const uint8_t *binary = stream->data() + stream->offset();
70 stream->skip(binaryLength);
71
72 // Load the binary
73 mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength);
74
75 // Verify that the program linked
76 if (!checkLinkStatus(infoLog))
77 {
78 return std::make_unique<LinkEventDone>(angle::Result::Incomplete);
79 }
80
81 postLink();
82 reapplyUBOBindingsIfNeeded(context);
83
84 return std::make_unique<LinkEventDone>(angle::Result::Continue);
85 }
86
save(const gl::Context * context,gl::BinaryOutputStream * stream)87 void ProgramGL::save(const gl::Context *context, gl::BinaryOutputStream *stream)
88 {
89 GLint binaryLength = 0;
90 mFunctions->getProgramiv(mProgramID, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
91
92 std::vector<uint8_t> binary(std::max(binaryLength, 1));
93 GLenum binaryFormat = GL_NONE;
94 mFunctions->getProgramBinary(mProgramID, binaryLength, &binaryLength, &binaryFormat,
95 binary.data());
96
97 stream->writeInt(binaryFormat);
98 stream->writeInt(binaryLength);
99 stream->writeBytes(binary.data(), binaryLength);
100
101 reapplyUBOBindingsIfNeeded(context);
102 }
103
reapplyUBOBindingsIfNeeded(const gl::Context * context)104 void ProgramGL::reapplyUBOBindingsIfNeeded(const gl::Context *context)
105 {
106 // Re-apply UBO bindings to work around driver bugs.
107 const angle::FeaturesGL &features = GetImplAs<ContextGL>(context)->getFeaturesGL();
108 if (features.reapplyUBOBindingsAfterUsingBinaryProgram.enabled)
109 {
110 const auto &blocks = mState.getUniformBlocks();
111 for (size_t blockIndex : mState.getActiveUniformBlockBindingsMask())
112 {
113 setUniformBlockBinding(static_cast<GLuint>(blockIndex), blocks[blockIndex].binding);
114 }
115 }
116 }
117
setBinaryRetrievableHint(bool retrievable)118 void ProgramGL::setBinaryRetrievableHint(bool retrievable)
119 {
120 // glProgramParameteri isn't always available on ES backends.
121 if (mFunctions->programParameteri)
122 {
123 mFunctions->programParameteri(mProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT,
124 retrievable ? GL_TRUE : GL_FALSE);
125 }
126 }
127
setSeparable(bool separable)128 void ProgramGL::setSeparable(bool separable)
129 {
130 mFunctions->programParameteri(mProgramID, GL_PROGRAM_SEPARABLE, separable ? GL_TRUE : GL_FALSE);
131 }
132
133 using LinkImplFunctor = std::function<bool(std::string &)>;
134 class ProgramGL::LinkTask final : public angle::Closure
135 {
136 public:
LinkTask(LinkImplFunctor && functor)137 LinkTask(LinkImplFunctor &&functor) : mLinkImplFunctor(functor), mFallbackToMainContext(false)
138 {}
139
operator ()()140 void operator()() override { mFallbackToMainContext = mLinkImplFunctor(mInfoLog); }
fallbackToMainContext()141 bool fallbackToMainContext() { return mFallbackToMainContext; }
getInfoLog()142 const std::string &getInfoLog() { return mInfoLog; }
143
144 private:
145 LinkImplFunctor mLinkImplFunctor;
146 bool mFallbackToMainContext;
147 std::string mInfoLog;
148 };
149
150 using PostLinkImplFunctor = std::function<angle::Result(bool, const std::string &)>;
151
152 // The event for a parallelized linking using the native driver extension.
153 class ProgramGL::LinkEventNativeParallel final : public LinkEvent
154 {
155 public:
LinkEventNativeParallel(PostLinkImplFunctor && functor,const FunctionsGL * functions,GLuint programID)156 LinkEventNativeParallel(PostLinkImplFunctor &&functor,
157 const FunctionsGL *functions,
158 GLuint programID)
159 : mPostLinkImplFunctor(functor), mFunctions(functions), mProgramID(programID)
160 {}
161
wait(const gl::Context * context)162 angle::Result wait(const gl::Context *context) override
163 {
164 GLint linkStatus = GL_FALSE;
165 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
166 if (linkStatus == GL_TRUE)
167 {
168 return mPostLinkImplFunctor(false, std::string());
169 }
170 return angle::Result::Incomplete;
171 }
172
isLinking()173 bool isLinking() override
174 {
175 GLint completionStatus = GL_FALSE;
176 mFunctions->getProgramiv(mProgramID, GL_COMPLETION_STATUS, &completionStatus);
177 return completionStatus == GL_FALSE;
178 }
179
180 private:
181 PostLinkImplFunctor mPostLinkImplFunctor;
182 const FunctionsGL *mFunctions;
183 GLuint mProgramID;
184 };
185
186 // The event for a parallelized linking using the worker thread pool.
187 class ProgramGL::LinkEventGL final : public LinkEvent
188 {
189 public:
LinkEventGL(std::shared_ptr<angle::WorkerThreadPool> workerPool,std::shared_ptr<ProgramGL::LinkTask> linkTask,PostLinkImplFunctor && functor)190 LinkEventGL(std::shared_ptr<angle::WorkerThreadPool> workerPool,
191 std::shared_ptr<ProgramGL::LinkTask> linkTask,
192 PostLinkImplFunctor &&functor)
193 : mLinkTask(linkTask),
194 mWaitableEvent(std::shared_ptr<angle::WaitableEvent>(
195 angle::WorkerThreadPool::PostWorkerTask(workerPool, mLinkTask))),
196 mPostLinkImplFunctor(functor)
197 {}
198
wait(const gl::Context * context)199 angle::Result wait(const gl::Context *context) override
200 {
201 mWaitableEvent->wait();
202 return mPostLinkImplFunctor(mLinkTask->fallbackToMainContext(), mLinkTask->getInfoLog());
203 }
204
isLinking()205 bool isLinking() override { return !mWaitableEvent->isReady(); }
206
207 private:
208 std::shared_ptr<ProgramGL::LinkTask> mLinkTask;
209 std::shared_ptr<angle::WaitableEvent> mWaitableEvent;
210 PostLinkImplFunctor mPostLinkImplFunctor;
211 };
212
link(const gl::Context * context,const gl::ProgramLinkedResources & resources,gl::InfoLog & infoLog)213 std::unique_ptr<LinkEvent> ProgramGL::link(const gl::Context *context,
214 const gl::ProgramLinkedResources &resources,
215 gl::InfoLog &infoLog)
216 {
217 preLink();
218
219 if (mState.getAttachedShader(gl::ShaderType::Compute))
220 {
221 const ShaderGL *computeShaderGL =
222 GetImplAs<ShaderGL>(mState.getAttachedShader(gl::ShaderType::Compute));
223
224 mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID());
225 }
226 else
227 {
228 // Set the transform feedback state
229 std::vector<std::string> transformFeedbackVaryingMappedNames;
230 for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
231 {
232 std::string tfVaryingMappedName =
233 mState.getAttachedShader(gl::ShaderType::Vertex)
234 ->getTransformFeedbackVaryingMappedName(tfVarying);
235 transformFeedbackVaryingMappedNames.push_back(tfVaryingMappedName);
236 }
237
238 if (transformFeedbackVaryingMappedNames.empty())
239 {
240 if (mFunctions->transformFeedbackVaryings)
241 {
242 mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
243 mState.getTransformFeedbackBufferMode());
244 }
245 }
246 else
247 {
248 ASSERT(mFunctions->transformFeedbackVaryings);
249 std::vector<const GLchar *> transformFeedbackVaryings;
250 for (const auto &varying : transformFeedbackVaryingMappedNames)
251 {
252 transformFeedbackVaryings.push_back(varying.c_str());
253 }
254 mFunctions->transformFeedbackVaryings(
255 mProgramID, static_cast<GLsizei>(transformFeedbackVaryingMappedNames.size()),
256 &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
257 }
258
259 const ShaderGL *vertexShaderGL =
260 GetImplAs<ShaderGL>(mState.getAttachedShader(gl::ShaderType::Vertex));
261 const ShaderGL *fragmentShaderGL =
262 GetImplAs<ShaderGL>(mState.getAttachedShader(gl::ShaderType::Fragment));
263 const ShaderGL *geometryShaderGL = rx::SafeGetImplAs<ShaderGL, gl::Shader>(
264 mState.getAttachedShader(gl::ShaderType::Geometry));
265
266 // Attach the shaders
267 mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
268 mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
269 if (geometryShaderGL)
270 {
271 mFunctions->attachShader(mProgramID, geometryShaderGL->getShaderID());
272 }
273
274 // Bind attribute locations to match the GL layer.
275 for (const sh::Attribute &attribute : mState.getAttributes())
276 {
277 if (!attribute.active || attribute.isBuiltIn())
278 {
279 continue;
280 }
281
282 mFunctions->bindAttribLocation(mProgramID, attribute.location,
283 attribute.mappedName.c_str());
284 }
285
286 // Bind the secondary fragment color outputs defined in EXT_blend_func_extended. We only use
287 // the API to bind fragment output locations in case EXT_blend_func_extended is enabled.
288 // Otherwise shader-assigned locations will work.
289 if (context->getExtensions().blendFuncExtended)
290 {
291 if (mState.getAttachedShader(gl::ShaderType::Fragment)->getShaderVersion() == 100)
292 {
293 // TODO(http://anglebug.com/2833): The bind done below is only valid in case the
294 // compiler transforms the shader outputs to the angle/webgl prefixed ones. If we
295 // added support for running EXT_blend_func_extended on top of GLES, some changes
296 // would be required:
297 // - If we're backed by GLES 2.0, we shouldn't do the bind because it's not needed.
298 // - If we're backed by GLES 3.0+, it's a bit unclear what should happen. Currently
299 // the compiler doesn't support transforming GLSL ES 1.00 shaders to GLSL ES 3.00
300 // shaders in general, but support for that might be required. Or we might be
301 // able to skip the bind in case the compiler outputs GLSL ES 1.00.
302 const auto &shaderOutputs =
303 mState.getAttachedShader(gl::ShaderType::Fragment)->getActiveOutputVariables();
304 for (const auto &output : shaderOutputs)
305 {
306 // TODO(http://anglebug.com/1085) This could be cleaner if the transformed names
307 // would be set correctly in ShaderVariable::mappedName. This would require some
308 // refactoring in the translator. Adding a mapped name dictionary for builtins
309 // into the symbol table would be one fairly clean way to do it.
310 if (output.name == "gl_SecondaryFragColorEXT")
311 {
312 mFunctions->bindFragDataLocationIndexed(mProgramID, 0, 0,
313 "webgl_FragColor");
314 mFunctions->bindFragDataLocationIndexed(mProgramID, 0, 1,
315 "angle_SecondaryFragColor");
316 }
317 else if (output.name == "gl_SecondaryFragDataEXT")
318 {
319 // Basically we should have a loop here going over the output
320 // array binding "webgl_FragData[i]" and "angle_SecondaryFragData[i]" array
321 // indices to the correct color buffers and color indices.
322 // However I'm not sure if this construct is legal or not, neither ARB or
323 // EXT version of the spec mention this. They only mention that
324 // automatically assigned array locations for ESSL 3.00 output arrays need
325 // to have contiguous locations.
326 //
327 // In practice it seems that binding array members works on some drivers and
328 // fails on others. One option could be to modify the shader translator to
329 // expand the arrays into individual output variables instead of using an
330 // array.
331 //
332 // For now we're going to have a limitation of assuming that
333 // GL_MAX_DUAL_SOURCE_DRAW_BUFFERS is *always* 1 and then only bind the
334 // basename of the variable ignoring any indices. This appears to work
335 // uniformly.
336 ASSERT(output.isArray() && output.getOutermostArraySize() == 1);
337
338 mFunctions->bindFragDataLocationIndexed(mProgramID, 0, 0, "webgl_FragData");
339 mFunctions->bindFragDataLocationIndexed(mProgramID, 0, 1,
340 "angle_SecondaryFragData");
341 }
342 }
343 }
344 else
345 {
346 // ESSL 3.00 and up.
347 const auto &outputLocations = mState.getOutputLocations();
348 const auto &secondaryOutputLocations = mState.getSecondaryOutputLocations();
349 for (size_t outputLocationIndex = 0u; outputLocationIndex < outputLocations.size();
350 ++outputLocationIndex)
351 {
352 const gl::VariableLocation &outputLocation =
353 outputLocations[outputLocationIndex];
354 if (outputLocation.arrayIndex == 0 && outputLocation.used() &&
355 !outputLocation.ignored)
356 {
357 const sh::OutputVariable &outputVar =
358 mState.getOutputVariables()[outputLocation.index];
359 if (outputVar.location == -1)
360 {
361 // We only need to assign the location and index via the API in case the
362 // variable doesn't have its location set in the shader. If a variable
363 // doesn't have its location set in the shader it doesn't have the index
364 // set either.
365 ASSERT(outputVar.index == -1);
366 mFunctions->bindFragDataLocationIndexed(
367 mProgramID, static_cast<int>(outputLocationIndex), 0,
368 outputVar.mappedName.c_str());
369 }
370 }
371 }
372 for (size_t outputLocationIndex = 0u;
373 outputLocationIndex < secondaryOutputLocations.size(); ++outputLocationIndex)
374 {
375 const gl::VariableLocation &outputLocation =
376 secondaryOutputLocations[outputLocationIndex];
377 if (outputLocation.arrayIndex == 0 && outputLocation.used() &&
378 !outputLocation.ignored)
379 {
380 const sh::OutputVariable &outputVar =
381 mState.getOutputVariables()[outputLocation.index];
382 if (outputVar.location == -1 || outputVar.index == -1)
383 {
384 // We only need to assign the location and index via the API in case the
385 // variable doesn't have a shader-assigned location and index. If a
386 // variable doesn't have its location set in the shader it doesn't have
387 // the index set either.
388 ASSERT(outputVar.index == -1);
389 mFunctions->bindFragDataLocationIndexed(
390 mProgramID, static_cast<int>(outputLocationIndex), 1,
391 outputVar.mappedName.c_str());
392 }
393 }
394 }
395 }
396 }
397 }
398 auto workerPool = context->getWorkerThreadPool();
399 auto linkTask = std::make_shared<LinkTask>([this](std::string &infoLog) {
400 std::string workerInfoLog;
401 ScopedWorkerContextGL worker(mRenderer.get(), &workerInfoLog);
402 if (!worker())
403 {
404 #if !defined(NDEBUG)
405 infoLog += "bindWorkerContext failed.\n" + workerInfoLog;
406 #endif
407 // Fallback to the main context.
408 return true;
409 }
410
411 mFunctions->linkProgram(mProgramID);
412
413 // Make sure the driver actually does the link job.
414 GLint linkStatus = GL_FALSE;
415 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
416
417 return false;
418 });
419
420 auto postLinkImplTask = [this, &infoLog, &resources](bool fallbackToMainContext,
421 const std::string &workerInfoLog) {
422 infoLog << workerInfoLog;
423 if (fallbackToMainContext)
424 {
425 mFunctions->linkProgram(mProgramID);
426 }
427
428 if (mState.getAttachedShader(gl::ShaderType::Compute))
429 {
430 const ShaderGL *computeShaderGL =
431 GetImplAs<ShaderGL>(mState.getAttachedShader(gl::ShaderType::Compute));
432
433 mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID());
434 }
435 else
436 {
437 const ShaderGL *vertexShaderGL =
438 GetImplAs<ShaderGL>(mState.getAttachedShader(gl::ShaderType::Vertex));
439 const ShaderGL *fragmentShaderGL =
440 GetImplAs<ShaderGL>(mState.getAttachedShader(gl::ShaderType::Fragment));
441 const ShaderGL *geometryShaderGL = rx::SafeGetImplAs<ShaderGL, gl::Shader>(
442 mState.getAttachedShader(gl::ShaderType::Geometry));
443
444 // Detach the shaders
445 mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
446 mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
447 if (geometryShaderGL)
448 {
449 mFunctions->detachShader(mProgramID, geometryShaderGL->getShaderID());
450 }
451 }
452 // Verify the link
453 if (!checkLinkStatus(infoLog))
454 {
455 return angle::Result::Incomplete;
456 }
457
458 if (mFeatures.alwaysCallUseProgramAfterLink.enabled)
459 {
460 mStateManager->forceUseProgram(mProgramID);
461 }
462
463 linkResources(resources);
464 postLink();
465
466 return angle::Result::Continue;
467 };
468
469 if (mRenderer->hasNativeParallelCompile())
470 {
471 mFunctions->linkProgram(mProgramID);
472 return std::make_unique<LinkEventNativeParallel>(postLinkImplTask, mFunctions, mProgramID);
473 }
474 else if (workerPool->isAsync() &&
475 (!mFeatures.dontRelinkProgramsInParallel.enabled || !mLinkedInParallel))
476 {
477 mLinkedInParallel = true;
478 return std::make_unique<LinkEventGL>(workerPool, linkTask, postLinkImplTask);
479 }
480 else
481 {
482 return std::make_unique<LinkEventDone>(postLinkImplTask(true, std::string()));
483 }
484 }
485
validate(const gl::Caps &,gl::InfoLog *)486 GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
487 {
488 // TODO(jmadill): implement validate
489 return true;
490 }
491
setUniform1fv(GLint location,GLsizei count,const GLfloat * v)492 void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
493 {
494 if (mFunctions->programUniform1fv != nullptr)
495 {
496 mFunctions->programUniform1fv(mProgramID, uniLoc(location), count, v);
497 }
498 else
499 {
500 mStateManager->useProgram(mProgramID);
501 mFunctions->uniform1fv(uniLoc(location), count, v);
502 }
503 }
504
setUniform2fv(GLint location,GLsizei count,const GLfloat * v)505 void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
506 {
507 if (mFunctions->programUniform2fv != nullptr)
508 {
509 mFunctions->programUniform2fv(mProgramID, uniLoc(location), count, v);
510 }
511 else
512 {
513 mStateManager->useProgram(mProgramID);
514 mFunctions->uniform2fv(uniLoc(location), count, v);
515 }
516 }
517
setUniform3fv(GLint location,GLsizei count,const GLfloat * v)518 void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
519 {
520 if (mFunctions->programUniform3fv != nullptr)
521 {
522 mFunctions->programUniform3fv(mProgramID, uniLoc(location), count, v);
523 }
524 else
525 {
526 mStateManager->useProgram(mProgramID);
527 mFunctions->uniform3fv(uniLoc(location), count, v);
528 }
529 }
530
setUniform4fv(GLint location,GLsizei count,const GLfloat * v)531 void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
532 {
533 if (mFunctions->programUniform4fv != nullptr)
534 {
535 mFunctions->programUniform4fv(mProgramID, uniLoc(location), count, v);
536 }
537 else
538 {
539 mStateManager->useProgram(mProgramID);
540 mFunctions->uniform4fv(uniLoc(location), count, v);
541 }
542 }
543
setUniform1iv(GLint location,GLsizei count,const GLint * v)544 void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
545 {
546 if (mFunctions->programUniform1iv != nullptr)
547 {
548 mFunctions->programUniform1iv(mProgramID, uniLoc(location), count, v);
549 }
550 else
551 {
552 mStateManager->useProgram(mProgramID);
553 mFunctions->uniform1iv(uniLoc(location), count, v);
554 }
555 }
556
setUniform2iv(GLint location,GLsizei count,const GLint * v)557 void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
558 {
559 if (mFunctions->programUniform2iv != nullptr)
560 {
561 mFunctions->programUniform2iv(mProgramID, uniLoc(location), count, v);
562 }
563 else
564 {
565 mStateManager->useProgram(mProgramID);
566 mFunctions->uniform2iv(uniLoc(location), count, v);
567 }
568 }
569
setUniform3iv(GLint location,GLsizei count,const GLint * v)570 void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
571 {
572 if (mFunctions->programUniform3iv != nullptr)
573 {
574 mFunctions->programUniform3iv(mProgramID, uniLoc(location), count, v);
575 }
576 else
577 {
578 mStateManager->useProgram(mProgramID);
579 mFunctions->uniform3iv(uniLoc(location), count, v);
580 }
581 }
582
setUniform4iv(GLint location,GLsizei count,const GLint * v)583 void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
584 {
585 if (mFunctions->programUniform4iv != nullptr)
586 {
587 mFunctions->programUniform4iv(mProgramID, uniLoc(location), count, v);
588 }
589 else
590 {
591 mStateManager->useProgram(mProgramID);
592 mFunctions->uniform4iv(uniLoc(location), count, v);
593 }
594 }
595
setUniform1uiv(GLint location,GLsizei count,const GLuint * v)596 void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
597 {
598 if (mFunctions->programUniform1uiv != nullptr)
599 {
600 mFunctions->programUniform1uiv(mProgramID, uniLoc(location), count, v);
601 }
602 else
603 {
604 mStateManager->useProgram(mProgramID);
605 mFunctions->uniform1uiv(uniLoc(location), count, v);
606 }
607 }
608
setUniform2uiv(GLint location,GLsizei count,const GLuint * v)609 void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
610 {
611 if (mFunctions->programUniform2uiv != nullptr)
612 {
613 mFunctions->programUniform2uiv(mProgramID, uniLoc(location), count, v);
614 }
615 else
616 {
617 mStateManager->useProgram(mProgramID);
618 mFunctions->uniform2uiv(uniLoc(location), count, v);
619 }
620 }
621
setUniform3uiv(GLint location,GLsizei count,const GLuint * v)622 void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
623 {
624 if (mFunctions->programUniform3uiv != nullptr)
625 {
626 mFunctions->programUniform3uiv(mProgramID, uniLoc(location), count, v);
627 }
628 else
629 {
630 mStateManager->useProgram(mProgramID);
631 mFunctions->uniform3uiv(uniLoc(location), count, v);
632 }
633 }
634
setUniform4uiv(GLint location,GLsizei count,const GLuint * v)635 void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
636 {
637 if (mFunctions->programUniform4uiv != nullptr)
638 {
639 mFunctions->programUniform4uiv(mProgramID, uniLoc(location), count, v);
640 }
641 else
642 {
643 mStateManager->useProgram(mProgramID);
644 mFunctions->uniform4uiv(uniLoc(location), count, v);
645 }
646 }
647
setUniformMatrix2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)648 void ProgramGL::setUniformMatrix2fv(GLint location,
649 GLsizei count,
650 GLboolean transpose,
651 const GLfloat *value)
652 {
653 if (mFunctions->programUniformMatrix2fv != nullptr)
654 {
655 mFunctions->programUniformMatrix2fv(mProgramID, uniLoc(location), count, transpose, value);
656 }
657 else
658 {
659 mStateManager->useProgram(mProgramID);
660 mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
661 }
662 }
663
setUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)664 void ProgramGL::setUniformMatrix3fv(GLint location,
665 GLsizei count,
666 GLboolean transpose,
667 const GLfloat *value)
668 {
669 if (mFunctions->programUniformMatrix3fv != nullptr)
670 {
671 mFunctions->programUniformMatrix3fv(mProgramID, uniLoc(location), count, transpose, value);
672 }
673 else
674 {
675 mStateManager->useProgram(mProgramID);
676 mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
677 }
678 }
679
setUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)680 void ProgramGL::setUniformMatrix4fv(GLint location,
681 GLsizei count,
682 GLboolean transpose,
683 const GLfloat *value)
684 {
685 if (mFunctions->programUniformMatrix4fv != nullptr)
686 {
687 mFunctions->programUniformMatrix4fv(mProgramID, uniLoc(location), count, transpose, value);
688 }
689 else
690 {
691 mStateManager->useProgram(mProgramID);
692 mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
693 }
694 }
695
setUniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)696 void ProgramGL::setUniformMatrix2x3fv(GLint location,
697 GLsizei count,
698 GLboolean transpose,
699 const GLfloat *value)
700 {
701 if (mFunctions->programUniformMatrix2x3fv != nullptr)
702 {
703 mFunctions->programUniformMatrix2x3fv(mProgramID, uniLoc(location), count, transpose,
704 value);
705 }
706 else
707 {
708 mStateManager->useProgram(mProgramID);
709 mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
710 }
711 }
712
setUniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)713 void ProgramGL::setUniformMatrix3x2fv(GLint location,
714 GLsizei count,
715 GLboolean transpose,
716 const GLfloat *value)
717 {
718 if (mFunctions->programUniformMatrix3x2fv != nullptr)
719 {
720 mFunctions->programUniformMatrix3x2fv(mProgramID, uniLoc(location), count, transpose,
721 value);
722 }
723 else
724 {
725 mStateManager->useProgram(mProgramID);
726 mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
727 }
728 }
729
setUniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)730 void ProgramGL::setUniformMatrix2x4fv(GLint location,
731 GLsizei count,
732 GLboolean transpose,
733 const GLfloat *value)
734 {
735 if (mFunctions->programUniformMatrix2x4fv != nullptr)
736 {
737 mFunctions->programUniformMatrix2x4fv(mProgramID, uniLoc(location), count, transpose,
738 value);
739 }
740 else
741 {
742 mStateManager->useProgram(mProgramID);
743 mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
744 }
745 }
746
setUniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)747 void ProgramGL::setUniformMatrix4x2fv(GLint location,
748 GLsizei count,
749 GLboolean transpose,
750 const GLfloat *value)
751 {
752 if (mFunctions->programUniformMatrix4x2fv != nullptr)
753 {
754 mFunctions->programUniformMatrix4x2fv(mProgramID, uniLoc(location), count, transpose,
755 value);
756 }
757 else
758 {
759 mStateManager->useProgram(mProgramID);
760 mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
761 }
762 }
763
setUniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)764 void ProgramGL::setUniformMatrix3x4fv(GLint location,
765 GLsizei count,
766 GLboolean transpose,
767 const GLfloat *value)
768 {
769 if (mFunctions->programUniformMatrix3x4fv != nullptr)
770 {
771 mFunctions->programUniformMatrix3x4fv(mProgramID, uniLoc(location), count, transpose,
772 value);
773 }
774 else
775 {
776 mStateManager->useProgram(mProgramID);
777 mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
778 }
779 }
780
setUniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)781 void ProgramGL::setUniformMatrix4x3fv(GLint location,
782 GLsizei count,
783 GLboolean transpose,
784 const GLfloat *value)
785 {
786 if (mFunctions->programUniformMatrix4x3fv != nullptr)
787 {
788 mFunctions->programUniformMatrix4x3fv(mProgramID, uniLoc(location), count, transpose,
789 value);
790 }
791 else
792 {
793 mStateManager->useProgram(mProgramID);
794 mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
795 }
796 }
797
setUniformBlockBinding(GLuint uniformBlockIndex,GLuint uniformBlockBinding)798 void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
799 {
800 // Lazy init
801 if (mUniformBlockRealLocationMap.empty())
802 {
803 mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
804 for (const gl::InterfaceBlock &uniformBlock : mState.getUniformBlocks())
805 {
806 const std::string &mappedNameWithIndex = uniformBlock.mappedNameWithArrayIndex();
807 GLuint blockIndex =
808 mFunctions->getUniformBlockIndex(mProgramID, mappedNameWithIndex.c_str());
809 mUniformBlockRealLocationMap.push_back(blockIndex);
810 }
811 }
812
813 GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
814 if (realBlockIndex != GL_INVALID_INDEX)
815 {
816 mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
817 }
818 }
819
getUniformBlockSize(const std::string &,const std::string & blockMappedName,size_t * sizeOut) const820 bool ProgramGL::getUniformBlockSize(const std::string & /* blockName */,
821 const std::string &blockMappedName,
822 size_t *sizeOut) const
823 {
824 ASSERT(mProgramID != 0u);
825
826 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockMappedName.c_str());
827 if (blockIndex == GL_INVALID_INDEX)
828 {
829 *sizeOut = 0;
830 return false;
831 }
832
833 GLint dataSize = 0;
834 mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
835 &dataSize);
836 *sizeOut = static_cast<size_t>(dataSize);
837 return true;
838 }
839
getUniformBlockMemberInfo(const std::string &,const std::string & memberUniformMappedName,sh::BlockMemberInfo * memberInfoOut) const840 bool ProgramGL::getUniformBlockMemberInfo(const std::string & /* memberUniformName */,
841 const std::string &memberUniformMappedName,
842 sh::BlockMemberInfo *memberInfoOut) const
843 {
844 GLuint uniformIndex;
845 const GLchar *memberNameGLStr = memberUniformMappedName.c_str();
846 mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
847
848 if (uniformIndex == GL_INVALID_INDEX)
849 {
850 *memberInfoOut = sh::kDefaultBlockMemberInfo;
851 return false;
852 }
853
854 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
855 &memberInfoOut->offset);
856 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
857 &memberInfoOut->arrayStride);
858 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
859 &memberInfoOut->matrixStride);
860
861 // TODO(jmadill): possibly determine this at the gl::Program level.
862 GLint isRowMajorMatrix = 0;
863 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
864 &isRowMajorMatrix);
865 memberInfoOut->isRowMajorMatrix = gl::ConvertToBool(isRowMajorMatrix);
866 return true;
867 }
868
getShaderStorageBlockMemberInfo(const std::string &,const std::string & memberUniformMappedName,sh::BlockMemberInfo * memberInfoOut) const869 bool ProgramGL::getShaderStorageBlockMemberInfo(const std::string & /* memberName */,
870 const std::string &memberUniformMappedName,
871 sh::BlockMemberInfo *memberInfoOut) const
872 {
873 const GLchar *memberNameGLStr = memberUniformMappedName.c_str();
874 GLuint index =
875 mFunctions->getProgramResourceIndex(mProgramID, GL_BUFFER_VARIABLE, memberNameGLStr);
876
877 if (index == GL_INVALID_INDEX)
878 {
879 *memberInfoOut = sh::kDefaultBlockMemberInfo;
880 return false;
881 }
882
883 constexpr int kPropCount = 5;
884 std::array<GLenum, kPropCount> props = {
885 {GL_ARRAY_STRIDE, GL_IS_ROW_MAJOR, GL_MATRIX_STRIDE, GL_OFFSET, GL_TOP_LEVEL_ARRAY_STRIDE}};
886 std::array<GLint, kPropCount> params;
887 GLsizei length;
888 mFunctions->getProgramResourceiv(mProgramID, GL_BUFFER_VARIABLE, index, kPropCount,
889 props.data(), kPropCount, &length, params.data());
890 ASSERT(kPropCount == length);
891 memberInfoOut->arrayStride = params[0];
892 memberInfoOut->isRowMajorMatrix = params[1] != 0;
893 memberInfoOut->matrixStride = params[2];
894 memberInfoOut->offset = params[3];
895 memberInfoOut->topLevelArrayStride = params[4];
896
897 return true;
898 }
899
getShaderStorageBlockSize(const std::string & name,const std::string & mappedName,size_t * sizeOut) const900 bool ProgramGL::getShaderStorageBlockSize(const std::string &name,
901 const std::string &mappedName,
902 size_t *sizeOut) const
903 {
904 const GLchar *nameGLStr = mappedName.c_str();
905 GLuint index =
906 mFunctions->getProgramResourceIndex(mProgramID, GL_SHADER_STORAGE_BLOCK, nameGLStr);
907
908 if (index == GL_INVALID_INDEX)
909 {
910 *sizeOut = 0;
911 return false;
912 }
913
914 GLenum prop = GL_BUFFER_DATA_SIZE;
915 GLsizei length = 0;
916 GLint dataSize = 0;
917 mFunctions->getProgramResourceiv(mProgramID, GL_SHADER_STORAGE_BLOCK, index, 1, &prop, 1,
918 &length, &dataSize);
919 *sizeOut = static_cast<size_t>(dataSize);
920 return true;
921 }
922
getAtomicCounterBufferSizeMap(std::map<int,unsigned int> * sizeMapOut) const923 void ProgramGL::getAtomicCounterBufferSizeMap(std::map<int, unsigned int> *sizeMapOut) const
924 {
925 if (mFunctions->getProgramInterfaceiv == nullptr)
926 {
927 return;
928 }
929
930 int resourceCount = 0;
931 mFunctions->getProgramInterfaceiv(mProgramID, GL_ATOMIC_COUNTER_BUFFER, GL_ACTIVE_RESOURCES,
932 &resourceCount);
933
934 for (int index = 0; index < resourceCount; index++)
935 {
936 constexpr int kPropCount = 2;
937 std::array<GLenum, kPropCount> props = {{GL_BUFFER_BINDING, GL_BUFFER_DATA_SIZE}};
938 std::array<GLint, kPropCount> params;
939 GLsizei length;
940 mFunctions->getProgramResourceiv(mProgramID, GL_ATOMIC_COUNTER_BUFFER, index, kPropCount,
941 props.data(), kPropCount, &length, params.data());
942 ASSERT(kPropCount == length);
943 int bufferBinding = params[0];
944 unsigned int bufferDataSize = params[1];
945 sizeMapOut->insert(std::pair<int, unsigned int>(bufferBinding, bufferDataSize));
946 }
947 }
948
setPathFragmentInputGen(const std::string & inputName,GLenum genMode,GLint components,const GLfloat * coeffs)949 void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
950 GLenum genMode,
951 GLint components,
952 const GLfloat *coeffs)
953 {
954 ASSERT(mEnablePathRendering);
955
956 for (const auto &input : mPathRenderingFragmentInputs)
957 {
958 if (input.mappedName == inputName)
959 {
960 mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
961 components, coeffs);
962 ASSERT(mFunctions->getError() == GL_NO_ERROR);
963 return;
964 }
965 }
966 }
967
preLink()968 void ProgramGL::preLink()
969 {
970 // Reset the program state
971 mUniformRealLocationMap.clear();
972 mUniformBlockRealLocationMap.clear();
973 mPathRenderingFragmentInputs.clear();
974
975 mMultiviewBaseViewLayerIndexUniformLocation = -1;
976 }
977
checkLinkStatus(gl::InfoLog & infoLog)978 bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
979 {
980 GLint linkStatus = GL_FALSE;
981 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
982 if (linkStatus == GL_FALSE)
983 {
984 // Linking or program binary loading failed, put the error into the info log.
985 GLint infoLogLength = 0;
986 mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
987
988 // Info log length includes the null terminator, so 1 means that the info log is an empty
989 // string.
990 if (infoLogLength > 1)
991 {
992 std::vector<char> buf(infoLogLength);
993 mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
994
995 infoLog << buf.data();
996
997 WARN() << "Program link or binary loading failed: " << buf.data();
998 }
999 else
1000 {
1001 WARN() << "Program link or binary loading failed with no info log.";
1002 }
1003
1004 // This may happen under normal circumstances if we're loading program binaries and the
1005 // driver or hardware has changed.
1006 ASSERT(mProgramID != 0);
1007 return false;
1008 }
1009
1010 return true;
1011 }
1012
postLink()1013 void ProgramGL::postLink()
1014 {
1015 // Query the uniform information
1016 ASSERT(mUniformRealLocationMap.empty());
1017 const auto &uniformLocations = mState.getUniformLocations();
1018 const auto &uniforms = mState.getUniforms();
1019 mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
1020 for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
1021 {
1022 const auto &entry = uniformLocations[uniformLocation];
1023 if (!entry.used())
1024 {
1025 continue;
1026 }
1027
1028 // From the GLES 3.0.5 spec:
1029 // "Locations for sequential array indices are not required to be sequential."
1030 const gl::LinkedUniform &uniform = uniforms[entry.index];
1031 std::stringstream fullNameStr;
1032 if (uniform.isArray())
1033 {
1034 ASSERT(angle::EndsWith(uniform.mappedName, "[0]"));
1035 fullNameStr << uniform.mappedName.substr(0, uniform.mappedName.length() - 3);
1036 fullNameStr << "[" << entry.arrayIndex << "]";
1037 }
1038 else
1039 {
1040 fullNameStr << uniform.mappedName;
1041 }
1042 const std::string &fullName = fullNameStr.str();
1043
1044 GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
1045 mUniformRealLocationMap[uniformLocation] = realLocation;
1046 }
1047
1048 if (mState.usesMultiview())
1049 {
1050 mMultiviewBaseViewLayerIndexUniformLocation =
1051 mFunctions->getUniformLocation(mProgramID, "multiviewBaseViewLayerIndex");
1052 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
1053 }
1054
1055 // Discover CHROMIUM_path_rendering fragment inputs if enabled.
1056 if (!mEnablePathRendering)
1057 return;
1058
1059 GLint numFragmentInputs = 0;
1060 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
1061 &numFragmentInputs);
1062 if (numFragmentInputs <= 0)
1063 return;
1064
1065 GLint maxNameLength = 0;
1066 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
1067 &maxNameLength);
1068 ASSERT(maxNameLength);
1069
1070 for (GLint i = 0; i < numFragmentInputs; ++i)
1071 {
1072 std::string mappedName;
1073 mappedName.resize(maxNameLength);
1074
1075 GLsizei nameLen = 0;
1076 mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
1077 &nameLen, &mappedName[0]);
1078 mappedName.resize(nameLen);
1079
1080 // Ignore built-ins
1081 if (angle::BeginsWith(mappedName, "gl_"))
1082 continue;
1083
1084 const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
1085 GLint queryResults[ArraySize(kQueryProperties)];
1086 GLsizei queryLength = 0;
1087
1088 mFunctions->getProgramResourceiv(
1089 mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
1090 kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
1091 queryResults);
1092
1093 ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
1094
1095 PathRenderingFragmentInput baseElementInput;
1096 baseElementInput.mappedName = mappedName;
1097 baseElementInput.location = queryResults[0];
1098 mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
1099
1100 // If the input is an array it's denoted by [0] suffix on the variable
1101 // name. We'll then create an entry per each array index where index > 0
1102 if (angle::EndsWith(mappedName, "[0]"))
1103 {
1104 // drop the suffix
1105 mappedName.resize(mappedName.size() - 3);
1106
1107 const auto arraySize = queryResults[1];
1108 const auto baseLocation = queryResults[0];
1109
1110 for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
1111 {
1112 PathRenderingFragmentInput arrayElementInput;
1113 arrayElementInput.mappedName = mappedName + "[" + ToString(arrayIndex) + "]";
1114 arrayElementInput.location = baseLocation + arrayIndex;
1115 mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
1116 }
1117 }
1118 }
1119 }
1120
enableSideBySideRenderingPath() const1121 void ProgramGL::enableSideBySideRenderingPath() const
1122 {
1123 ASSERT(mState.usesMultiview());
1124 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
1125
1126 ASSERT(mFunctions->programUniform1i != nullptr);
1127 mFunctions->programUniform1i(mProgramID, mMultiviewBaseViewLayerIndexUniformLocation, -1);
1128 }
1129
enableLayeredRenderingPath(int baseViewIndex) const1130 void ProgramGL::enableLayeredRenderingPath(int baseViewIndex) const
1131 {
1132 ASSERT(mState.usesMultiview());
1133 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
1134
1135 ASSERT(mFunctions->programUniform1i != nullptr);
1136 mFunctions->programUniform1i(mProgramID, mMultiviewBaseViewLayerIndexUniformLocation,
1137 baseViewIndex);
1138 }
1139
getUniformfv(const gl::Context * context,GLint location,GLfloat * params) const1140 void ProgramGL::getUniformfv(const gl::Context *context, GLint location, GLfloat *params) const
1141 {
1142 mFunctions->getUniformfv(mProgramID, uniLoc(location), params);
1143 }
1144
getUniformiv(const gl::Context * context,GLint location,GLint * params) const1145 void ProgramGL::getUniformiv(const gl::Context *context, GLint location, GLint *params) const
1146 {
1147 mFunctions->getUniformiv(mProgramID, uniLoc(location), params);
1148 }
1149
getUniformuiv(const gl::Context * context,GLint location,GLuint * params) const1150 void ProgramGL::getUniformuiv(const gl::Context *context, GLint location, GLuint *params) const
1151 {
1152 mFunctions->getUniformuiv(mProgramID, uniLoc(location), params);
1153 }
1154
markUnusedUniformLocations(std::vector<gl::VariableLocation> * uniformLocations,std::vector<gl::SamplerBinding> * samplerBindings,std::vector<gl::ImageBinding> * imageBindings)1155 void ProgramGL::markUnusedUniformLocations(std::vector<gl::VariableLocation> *uniformLocations,
1156 std::vector<gl::SamplerBinding> *samplerBindings,
1157 std::vector<gl::ImageBinding> *imageBindings)
1158 {
1159 GLint maxLocation = static_cast<GLint>(uniformLocations->size());
1160 for (GLint location = 0; location < maxLocation; ++location)
1161 {
1162 if (uniLoc(location) == -1)
1163 {
1164 auto &locationRef = (*uniformLocations)[location];
1165 if (mState.isSamplerUniformIndex(locationRef.index))
1166 {
1167 GLuint samplerIndex = mState.getSamplerIndexFromUniformIndex(locationRef.index);
1168 (*samplerBindings)[samplerIndex].unreferenced = true;
1169 }
1170 else if (mState.isImageUniformIndex(locationRef.index))
1171 {
1172 GLuint imageIndex = mState.getImageIndexFromUniformIndex(locationRef.index);
1173 (*imageBindings)[imageIndex].unreferenced = true;
1174 }
1175 locationRef.markUnused();
1176 }
1177 }
1178 }
1179
linkResources(const gl::ProgramLinkedResources & resources)1180 void ProgramGL::linkResources(const gl::ProgramLinkedResources &resources)
1181 {
1182 // Gather interface block info.
1183 auto getUniformBlockSize = [this](const std::string &name, const std::string &mappedName,
1184 size_t *sizeOut) {
1185 return this->getUniformBlockSize(name, mappedName, sizeOut);
1186 };
1187
1188 auto getUniformBlockMemberInfo = [this](const std::string &name, const std::string &mappedName,
1189 sh::BlockMemberInfo *infoOut) {
1190 return this->getUniformBlockMemberInfo(name, mappedName, infoOut);
1191 };
1192
1193 resources.uniformBlockLinker.linkBlocks(getUniformBlockSize, getUniformBlockMemberInfo);
1194
1195 auto getShaderStorageBlockSize = [this](const std::string &name, const std::string &mappedName,
1196 size_t *sizeOut) {
1197 return this->getShaderStorageBlockSize(name, mappedName, sizeOut);
1198 };
1199
1200 auto getShaderStorageBlockMemberInfo = [this](const std::string &name,
1201 const std::string &mappedName,
1202 sh::BlockMemberInfo *infoOut) {
1203 return this->getShaderStorageBlockMemberInfo(name, mappedName, infoOut);
1204 };
1205 resources.shaderStorageBlockLinker.linkBlocks(getShaderStorageBlockSize,
1206 getShaderStorageBlockMemberInfo);
1207
1208 // Gather atomic counter buffer info.
1209 std::map<int, unsigned int> sizeMap;
1210 getAtomicCounterBufferSizeMap(&sizeMap);
1211 resources.atomicCounterBufferLinker.link(sizeMap);
1212 }
1213
syncState(const gl::Context * context,const gl::Program::DirtyBits & dirtyBits)1214 angle::Result ProgramGL::syncState(const gl::Context *context,
1215 const gl::Program::DirtyBits &dirtyBits)
1216 {
1217 for (size_t dirtyBit : dirtyBits)
1218 {
1219 ASSERT(dirtyBit <= gl::Program::DIRTY_BIT_UNIFORM_BLOCK_BINDING_MAX);
1220 GLuint binding = static_cast<GLuint>(dirtyBit);
1221 setUniformBlockBinding(binding, mState.getUniformBlockBinding(binding));
1222 }
1223 return angle::Result::Continue;
1224 }
1225 } // namespace rx
1226