xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/gl/ProgramExecutableGL.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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