1 //
2 // Copyright 2023 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 // ProgramExecutableGL.cpp: Implementation of ProgramExecutableGL.
7
8 #include "libANGLE/renderer/gl/ProgramExecutableGL.h"
9
10 #include "common/string_utils.h"
11 #include "libANGLE/Context.h"
12 #include "libANGLE/Program.h"
13 #include "libANGLE/Uniform.h"
14 #include "libANGLE/renderer/gl/ContextGL.h"
15 #include "libANGLE/renderer/gl/FunctionsGL.h"
16 #include "libANGLE/renderer/gl/RendererGL.h"
17 #include "libANGLE/renderer/gl/StateManagerGL.h"
18
19 namespace rx
20 {
ProgramExecutableGL(const gl::ProgramExecutable * executable)21 ProgramExecutableGL::ProgramExecutableGL(const gl::ProgramExecutable *executable)
22 : ProgramExecutableImpl(executable),
23 mHasAppliedTransformFeedbackVaryings(false),
24 mClipDistanceEnabledUniformLocation(-1),
25 mClipOriginUniformLocation(-1),
26 mMultiviewBaseViewLayerIndexUniformLocation(-1),
27 mProgramID(0),
28 mFunctions(nullptr),
29 mStateManager(nullptr)
30 {}
31
~ProgramExecutableGL()32 ProgramExecutableGL::~ProgramExecutableGL() {}
33
destroy(const gl::Context * context)34 void ProgramExecutableGL::destroy(const gl::Context *context) {}
35
reset()36 void ProgramExecutableGL::reset()
37 {
38 mUniformRealLocationMap.clear();
39 mUniformBlockRealLocationMap.clear();
40
41 mClipDistanceEnabledUniformLocation = -1;
42 mClipOriginUniformLocation = -1;
43 mMultiviewBaseViewLayerIndexUniformLocation = -1;
44 }
45
postLink(const FunctionsGL * functions,StateManagerGL * stateManager,const angle::FeaturesGL & features,GLuint programID)46 void ProgramExecutableGL::postLink(const FunctionsGL *functions,
47 StateManagerGL *stateManager,
48 const angle::FeaturesGL &features,
49 GLuint programID)
50 {
51 // Cache the following so the executable is capable of making the appropriate GL calls without
52 // having to involve ProgramGL.
53 mProgramID = programID;
54 mFunctions = functions;
55 mStateManager = stateManager;
56
57 // Query the uniform information
58 ASSERT(mUniformRealLocationMap.empty());
59 const auto &uniformLocations = mExecutable->getUniformLocations();
60 const auto &uniforms = mExecutable->getUniforms();
61 mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
62 for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
63 {
64 const auto &entry = uniformLocations[uniformLocation];
65 if (!entry.used())
66 {
67 continue;
68 }
69
70 // From the GLES 3.0.5 spec:
71 // "Locations for sequential array indices are not required to be sequential."
72 const gl::LinkedUniform &uniform = uniforms[entry.index];
73 const std::string &uniformMappedName = mExecutable->getUniformMappedNames()[entry.index];
74 std::stringstream fullNameStr;
75 if (uniform.isArray())
76 {
77 ASSERT(angle::EndsWith(uniformMappedName, "[0]"));
78 fullNameStr << uniformMappedName.substr(0, uniformMappedName.length() - 3);
79 fullNameStr << "[" << entry.arrayIndex << "]";
80 }
81 else
82 {
83 fullNameStr << uniformMappedName;
84 }
85 const std::string &fullName = fullNameStr.str();
86
87 GLint realLocation = functions->getUniformLocation(programID, fullName.c_str());
88 mUniformRealLocationMap[uniformLocation] = realLocation;
89 }
90
91 if (features.emulateClipDistanceState.enabled && mExecutable->hasClipDistance())
92 {
93 ASSERT(functions->standard == STANDARD_GL_ES);
94 mClipDistanceEnabledUniformLocation =
95 functions->getUniformLocation(programID, "angle_ClipDistanceEnabled");
96 ASSERT(mClipDistanceEnabledUniformLocation != -1);
97 }
98
99 if (features.emulateClipOrigin.enabled)
100 {
101 ASSERT(functions->standard == STANDARD_GL_ES);
102 mClipOriginUniformLocation = functions->getUniformLocation(programID, "angle_ClipOrigin");
103 }
104
105 if (mExecutable->usesMultiview())
106 {
107 mMultiviewBaseViewLayerIndexUniformLocation =
108 functions->getUniformLocation(programID, "multiviewBaseViewLayerIndex");
109 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
110 }
111 }
112
updateEnabledClipDistances(uint8_t enabledClipDistancesPacked) const113 void ProgramExecutableGL::updateEnabledClipDistances(uint8_t enabledClipDistancesPacked) const
114 {
115 ASSERT(mExecutable->hasClipDistance());
116 ASSERT(mClipDistanceEnabledUniformLocation != -1);
117
118 ASSERT(mFunctions->programUniform1ui != nullptr);
119 mFunctions->programUniform1ui(mProgramID, mClipDistanceEnabledUniformLocation,
120 enabledClipDistancesPacked);
121 }
122
updateEmulatedClipOrigin(gl::ClipOrigin origin) const123 void ProgramExecutableGL::updateEmulatedClipOrigin(gl::ClipOrigin origin) const
124 {
125 if (mClipOriginUniformLocation == -1)
126 {
127 // A driver may optimize away the uniform when gl_Position.y is always zero.
128 return;
129 }
130
131 const float originValue = (origin == gl::ClipOrigin::LowerLeft) ? 1.0f : -1.0f;
132 if (mFunctions->programUniform1f != nullptr)
133 {
134 mFunctions->programUniform1f(mProgramID, mClipOriginUniformLocation, originValue);
135 }
136 else
137 {
138 mStateManager->useProgram(mProgramID);
139 mFunctions->uniform1f(mClipOriginUniformLocation, originValue);
140 }
141 }
142
enableLayeredRenderingPath(int baseViewIndex) const143 void ProgramExecutableGL::enableLayeredRenderingPath(int baseViewIndex) const
144 {
145 ASSERT(mExecutable->usesMultiview());
146 ASSERT(mMultiviewBaseViewLayerIndexUniformLocation != -1);
147
148 ASSERT(mFunctions->programUniform1i != nullptr);
149 mFunctions->programUniform1i(mProgramID, mMultiviewBaseViewLayerIndexUniformLocation,
150 baseViewIndex);
151 }
152
setUniform1fv(GLint location,GLsizei count,const GLfloat * v)153 void ProgramExecutableGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
154 {
155 if (mFunctions->programUniform1fv != nullptr)
156 {
157 mFunctions->programUniform1fv(mProgramID, uniLoc(location), count, v);
158 }
159 else
160 {
161 mStateManager->useProgram(mProgramID);
162 mFunctions->uniform1fv(uniLoc(location), count, v);
163 }
164 }
165
setUniform2fv(GLint location,GLsizei count,const GLfloat * v)166 void ProgramExecutableGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
167 {
168 if (mFunctions->programUniform2fv != nullptr)
169 {
170 mFunctions->programUniform2fv(mProgramID, uniLoc(location), count, v);
171 }
172 else
173 {
174 mStateManager->useProgram(mProgramID);
175 mFunctions->uniform2fv(uniLoc(location), count, v);
176 }
177 }
178
setUniform3fv(GLint location,GLsizei count,const GLfloat * v)179 void ProgramExecutableGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
180 {
181 if (mFunctions->programUniform3fv != nullptr)
182 {
183 mFunctions->programUniform3fv(mProgramID, uniLoc(location), count, v);
184 }
185 else
186 {
187 mStateManager->useProgram(mProgramID);
188 mFunctions->uniform3fv(uniLoc(location), count, v);
189 }
190 }
191
setUniform4fv(GLint location,GLsizei count,const GLfloat * v)192 void ProgramExecutableGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
193 {
194 if (mFunctions->programUniform4fv != nullptr)
195 {
196 mFunctions->programUniform4fv(mProgramID, uniLoc(location), count, v);
197 }
198 else
199 {
200 mStateManager->useProgram(mProgramID);
201 mFunctions->uniform4fv(uniLoc(location), count, v);
202 }
203 }
204
setUniform1iv(GLint location,GLsizei count,const GLint * v)205 void ProgramExecutableGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
206 {
207 if (mFunctions->programUniform1iv != nullptr)
208 {
209 mFunctions->programUniform1iv(mProgramID, uniLoc(location), count, v);
210 }
211 else
212 {
213 mStateManager->useProgram(mProgramID);
214 mFunctions->uniform1iv(uniLoc(location), count, v);
215 }
216 }
217
setUniform2iv(GLint location,GLsizei count,const GLint * v)218 void ProgramExecutableGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
219 {
220 if (mFunctions->programUniform2iv != nullptr)
221 {
222 mFunctions->programUniform2iv(mProgramID, uniLoc(location), count, v);
223 }
224 else
225 {
226 mStateManager->useProgram(mProgramID);
227 mFunctions->uniform2iv(uniLoc(location), count, v);
228 }
229 }
230
setUniform3iv(GLint location,GLsizei count,const GLint * v)231 void ProgramExecutableGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
232 {
233 if (mFunctions->programUniform3iv != nullptr)
234 {
235 mFunctions->programUniform3iv(mProgramID, uniLoc(location), count, v);
236 }
237 else
238 {
239 mStateManager->useProgram(mProgramID);
240 mFunctions->uniform3iv(uniLoc(location), count, v);
241 }
242 }
243
setUniform4iv(GLint location,GLsizei count,const GLint * v)244 void ProgramExecutableGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
245 {
246 if (mFunctions->programUniform4iv != nullptr)
247 {
248 mFunctions->programUniform4iv(mProgramID, uniLoc(location), count, v);
249 }
250 else
251 {
252 mStateManager->useProgram(mProgramID);
253 mFunctions->uniform4iv(uniLoc(location), count, v);
254 }
255 }
256
setUniform1uiv(GLint location,GLsizei count,const GLuint * v)257 void ProgramExecutableGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
258 {
259 if (mFunctions->programUniform1uiv != nullptr)
260 {
261 mFunctions->programUniform1uiv(mProgramID, uniLoc(location), count, v);
262 }
263 else
264 {
265 mStateManager->useProgram(mProgramID);
266 mFunctions->uniform1uiv(uniLoc(location), count, v);
267 }
268 }
269
setUniform2uiv(GLint location,GLsizei count,const GLuint * v)270 void ProgramExecutableGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
271 {
272 if (mFunctions->programUniform2uiv != nullptr)
273 {
274 mFunctions->programUniform2uiv(mProgramID, uniLoc(location), count, v);
275 }
276 else
277 {
278 mStateManager->useProgram(mProgramID);
279 mFunctions->uniform2uiv(uniLoc(location), count, v);
280 }
281 }
282
setUniform3uiv(GLint location,GLsizei count,const GLuint * v)283 void ProgramExecutableGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
284 {
285 if (mFunctions->programUniform3uiv != nullptr)
286 {
287 mFunctions->programUniform3uiv(mProgramID, uniLoc(location), count, v);
288 }
289 else
290 {
291 mStateManager->useProgram(mProgramID);
292 mFunctions->uniform3uiv(uniLoc(location), count, v);
293 }
294 }
295
setUniform4uiv(GLint location,GLsizei count,const GLuint * v)296 void ProgramExecutableGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
297 {
298 if (mFunctions->programUniform4uiv != nullptr)
299 {
300 mFunctions->programUniform4uiv(mProgramID, uniLoc(location), count, v);
301 }
302 else
303 {
304 mStateManager->useProgram(mProgramID);
305 mFunctions->uniform4uiv(uniLoc(location), count, v);
306 }
307 }
308
setUniformMatrix2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)309 void ProgramExecutableGL::setUniformMatrix2fv(GLint location,
310 GLsizei count,
311 GLboolean transpose,
312 const GLfloat *value)
313 {
314 if (mFunctions->programUniformMatrix2fv != nullptr)
315 {
316 mFunctions->programUniformMatrix2fv(mProgramID, uniLoc(location), count, transpose, value);
317 }
318 else
319 {
320 mStateManager->useProgram(mProgramID);
321 mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
322 }
323 }
324
setUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)325 void ProgramExecutableGL::setUniformMatrix3fv(GLint location,
326 GLsizei count,
327 GLboolean transpose,
328 const GLfloat *value)
329 {
330 if (mFunctions->programUniformMatrix3fv != nullptr)
331 {
332 mFunctions->programUniformMatrix3fv(mProgramID, uniLoc(location), count, transpose, value);
333 }
334 else
335 {
336 mStateManager->useProgram(mProgramID);
337 mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
338 }
339 }
340
setUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)341 void ProgramExecutableGL::setUniformMatrix4fv(GLint location,
342 GLsizei count,
343 GLboolean transpose,
344 const GLfloat *value)
345 {
346 if (mFunctions->programUniformMatrix4fv != nullptr)
347 {
348 mFunctions->programUniformMatrix4fv(mProgramID, uniLoc(location), count, transpose, value);
349 }
350 else
351 {
352 mStateManager->useProgram(mProgramID);
353 mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
354 }
355 }
356
setUniformMatrix2x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)357 void ProgramExecutableGL::setUniformMatrix2x3fv(GLint location,
358 GLsizei count,
359 GLboolean transpose,
360 const GLfloat *value)
361 {
362 if (mFunctions->programUniformMatrix2x3fv != nullptr)
363 {
364 mFunctions->programUniformMatrix2x3fv(mProgramID, uniLoc(location), count, transpose,
365 value);
366 }
367 else
368 {
369 mStateManager->useProgram(mProgramID);
370 mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
371 }
372 }
373
setUniformMatrix3x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)374 void ProgramExecutableGL::setUniformMatrix3x2fv(GLint location,
375 GLsizei count,
376 GLboolean transpose,
377 const GLfloat *value)
378 {
379 if (mFunctions->programUniformMatrix3x2fv != nullptr)
380 {
381 mFunctions->programUniformMatrix3x2fv(mProgramID, uniLoc(location), count, transpose,
382 value);
383 }
384 else
385 {
386 mStateManager->useProgram(mProgramID);
387 mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
388 }
389 }
390
setUniformMatrix2x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)391 void ProgramExecutableGL::setUniformMatrix2x4fv(GLint location,
392 GLsizei count,
393 GLboolean transpose,
394 const GLfloat *value)
395 {
396 if (mFunctions->programUniformMatrix2x4fv != nullptr)
397 {
398 mFunctions->programUniformMatrix2x4fv(mProgramID, uniLoc(location), count, transpose,
399 value);
400 }
401 else
402 {
403 mStateManager->useProgram(mProgramID);
404 mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
405 }
406 }
407
setUniformMatrix4x2fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)408 void ProgramExecutableGL::setUniformMatrix4x2fv(GLint location,
409 GLsizei count,
410 GLboolean transpose,
411 const GLfloat *value)
412 {
413 if (mFunctions->programUniformMatrix4x2fv != nullptr)
414 {
415 mFunctions->programUniformMatrix4x2fv(mProgramID, uniLoc(location), count, transpose,
416 value);
417 }
418 else
419 {
420 mStateManager->useProgram(mProgramID);
421 mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
422 }
423 }
424
setUniformMatrix3x4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)425 void ProgramExecutableGL::setUniformMatrix3x4fv(GLint location,
426 GLsizei count,
427 GLboolean transpose,
428 const GLfloat *value)
429 {
430 if (mFunctions->programUniformMatrix3x4fv != nullptr)
431 {
432 mFunctions->programUniformMatrix3x4fv(mProgramID, uniLoc(location), count, transpose,
433 value);
434 }
435 else
436 {
437 mStateManager->useProgram(mProgramID);
438 mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
439 }
440 }
441
setUniformMatrix4x3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat * value)442 void ProgramExecutableGL::setUniformMatrix4x3fv(GLint location,
443 GLsizei count,
444 GLboolean transpose,
445 const GLfloat *value)
446 {
447 if (mFunctions->programUniformMatrix4x3fv != nullptr)
448 {
449 mFunctions->programUniformMatrix4x3fv(mProgramID, uniLoc(location), count, transpose,
450 value);
451 }
452 else
453 {
454 mStateManager->useProgram(mProgramID);
455 mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
456 }
457 }
458
getUniformfv(const gl::Context * context,GLint location,GLfloat * params) const459 void ProgramExecutableGL::getUniformfv(const gl::Context *context,
460 GLint location,
461 GLfloat *params) const
462 {
463 mFunctions->getUniformfv(mProgramID, uniLoc(location), params);
464 }
465
getUniformiv(const gl::Context * context,GLint location,GLint * params) const466 void ProgramExecutableGL::getUniformiv(const gl::Context *context,
467 GLint location,
468 GLint *params) const
469 {
470 mFunctions->getUniformiv(mProgramID, uniLoc(location), params);
471 }
472
getUniformuiv(const gl::Context * context,GLint location,GLuint * params) const473 void ProgramExecutableGL::getUniformuiv(const gl::Context *context,
474 GLint location,
475 GLuint *params) const
476 {
477 mFunctions->getUniformuiv(mProgramID, uniLoc(location), params);
478 }
479
setUniformBlockBinding(GLuint uniformBlockIndex,GLuint uniformBlockBinding)480 void ProgramExecutableGL::setUniformBlockBinding(GLuint uniformBlockIndex,
481 GLuint uniformBlockBinding)
482 {
483 // Lazy init
484 if (mUniformBlockRealLocationMap.empty())
485 {
486 mUniformBlockRealLocationMap.reserve(mExecutable->getUniformBlocks().size());
487 for (const gl::InterfaceBlock &uniformBlock : mExecutable->getUniformBlocks())
488 {
489 const std::string &mappedNameWithIndex = uniformBlock.mappedNameWithArrayIndex();
490 GLuint blockIndex =
491 mFunctions->getUniformBlockIndex(mProgramID, mappedNameWithIndex.c_str());
492 mUniformBlockRealLocationMap.push_back(blockIndex);
493 }
494 }
495
496 const GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
497 if (realBlockIndex != GL_INVALID_INDEX)
498 {
499 mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
500 }
501 }
502
reapplyUBOBindings()503 void ProgramExecutableGL::reapplyUBOBindings()
504 {
505 const std::vector<gl::InterfaceBlock> &blocks = mExecutable->getUniformBlocks();
506 for (size_t blockIndex = 0; blockIndex < blocks.size(); ++blockIndex)
507 {
508 if (blocks[blockIndex].activeShaders().any())
509 {
510 const GLuint index = static_cast<GLuint>(blockIndex);
511 setUniformBlockBinding(index, mExecutable->getUniformBlockBinding(index));
512 }
513 }
514 }
515
syncUniformBlockBindings()516 void ProgramExecutableGL::syncUniformBlockBindings()
517 {
518 for (size_t uniformBlockIndex : mDirtyUniformBlockBindings)
519 {
520 const GLuint index = static_cast<GLuint>(uniformBlockIndex);
521 setUniformBlockBinding(index, mExecutable->getUniformBlockBinding(index));
522 }
523
524 mDirtyUniformBlockBindings.reset();
525 }
526 } // namespace rx
527