1 //
2 // Copyright 2002 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 // Shader.cpp: Implements the gl::Shader class and its  derived classes
8 // VertexShader and FragmentShader. Implements GL shader objects and related
9 // functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
10 
11 #include "libANGLE/Shader.h"
12 
13 #include <functional>
14 #include <sstream>
15 
16 #include "GLSLANG/ShaderLang.h"
17 #include "common/utilities.h"
18 #include "libANGLE/Caps.h"
19 #include "libANGLE/Compiler.h"
20 #include "libANGLE/Constants.h"
21 #include "libANGLE/Context.h"
22 #include "libANGLE/ResourceManager.h"
23 #include "libANGLE/renderer/GLImplFactory.h"
24 #include "libANGLE/renderer/ShaderImpl.h"
25 #include "platform/FrontendFeatures.h"
26 
27 namespace gl
28 {
29 
30 namespace
31 {
32 template <typename VarT>
GetActiveShaderVariables(const std::vector<VarT> * variableList)33 std::vector<VarT> GetActiveShaderVariables(const std::vector<VarT> *variableList)
34 {
35     ASSERT(variableList);
36     std::vector<VarT> result;
37     for (size_t varIndex = 0; varIndex < variableList->size(); varIndex++)
38     {
39         const VarT &var = variableList->at(varIndex);
40         if (var.active)
41         {
42             result.push_back(var);
43         }
44     }
45     return result;
46 }
47 
48 template <typename VarT>
GetShaderVariables(const std::vector<VarT> * variableList)49 const std::vector<VarT> &GetShaderVariables(const std::vector<VarT> *variableList)
50 {
51     ASSERT(variableList);
52     return *variableList;
53 }
54 
55 }  // anonymous namespace
56 
57 // true if varying x has a higher priority in packing than y
CompareShaderVar(const sh::ShaderVariable & x,const sh::ShaderVariable & y)58 bool CompareShaderVar(const sh::ShaderVariable &x, const sh::ShaderVariable &y)
59 {
60     if (x.type == y.type)
61     {
62         return x.getArraySizeProduct() > y.getArraySizeProduct();
63     }
64 
65     // Special case for handling structs: we sort these to the end of the list
66     if (x.type == GL_NONE)
67     {
68         return false;
69     }
70 
71     if (y.type == GL_NONE)
72     {
73         return true;
74     }
75 
76     return gl::VariableSortOrder(x.type) < gl::VariableSortOrder(y.type);
77 }
78 
GetShaderTypeString(ShaderType type)79 const char *GetShaderTypeString(ShaderType type)
80 {
81     switch (type)
82     {
83         case ShaderType::Vertex:
84             return "VERTEX";
85 
86         case ShaderType::Fragment:
87             return "FRAGMENT";
88 
89         case ShaderType::Compute:
90             return "COMPUTE";
91 
92         case ShaderType::Geometry:
93             return "GEOMETRY";
94 
95         case ShaderType::TessControl:
96             return "TESS_CONTROL";
97 
98         case ShaderType::TessEvaluation:
99             return "TESS_EVALUATION";
100 
101         default:
102             UNREACHABLE();
103             return "";
104     }
105 }
106 
107 class ScopedExit final : angle::NonCopyable
108 {
109   public:
ScopedExit(std::function<void ()> exit)110     ScopedExit(std::function<void()> exit) : mExit(exit) {}
~ScopedExit()111     ~ScopedExit() { mExit(); }
112 
113   private:
114     std::function<void()> mExit;
115 };
116 
117 struct Shader::CompilingState
118 {
119     std::shared_ptr<rx::WaitableCompileEvent> compileEvent;
120     ShCompilerInstance shCompilerInstance;
121 };
122 
ShaderState(ShaderType shaderType)123 ShaderState::ShaderState(ShaderType shaderType)
124     : mLabel(),
125       mShaderType(shaderType),
126       mShaderVersion(100),
127       mNumViews(-1),
128       mGeometryShaderInvocations(1),
129       mCompileStatus(CompileStatus::NOT_COMPILED)
130 {
131     mLocalSize.fill(-1);
132 }
133 
~ShaderState()134 ShaderState::~ShaderState() {}
135 
Shader(ShaderProgramManager * manager,rx::GLImplFactory * implFactory,const gl::Limitations & rendererLimitations,ShaderType type,ShaderProgramID handle)136 Shader::Shader(ShaderProgramManager *manager,
137                rx::GLImplFactory *implFactory,
138                const gl::Limitations &rendererLimitations,
139                ShaderType type,
140                ShaderProgramID handle)
141     : mState(type),
142       mImplementation(implFactory->createShader(mState)),
143       mRendererLimitations(rendererLimitations),
144       mHandle(handle),
145       mType(type),
146       mRefCount(0),
147       mDeleteStatus(false),
148       mResourceManager(manager),
149       mCurrentMaxComputeWorkGroupInvocations(0u)
150 {
151     ASSERT(mImplementation);
152 }
153 
onDestroy(const gl::Context * context)154 void Shader::onDestroy(const gl::Context *context)
155 {
156     resolveCompile();
157     mImplementation->destroy();
158     mBoundCompiler.set(context, nullptr);
159     mImplementation.reset(nullptr);
160     delete this;
161 }
162 
~Shader()163 Shader::~Shader()
164 {
165     ASSERT(!mImplementation);
166 }
167 
setLabel(const Context * context,const std::string & label)168 void Shader::setLabel(const Context *context, const std::string &label)
169 {
170     mState.mLabel = label;
171 }
172 
getLabel() const173 const std::string &Shader::getLabel() const
174 {
175     return mState.mLabel;
176 }
177 
getHandle() const178 ShaderProgramID Shader::getHandle() const
179 {
180     return mHandle;
181 }
182 
setSource(GLsizei count,const char * const * string,const GLint * length)183 void Shader::setSource(GLsizei count, const char *const *string, const GLint *length)
184 {
185     std::ostringstream stream;
186 
187     for (int i = 0; i < count; i++)
188     {
189         if (length == nullptr || length[i] < 0)
190         {
191             stream.write(string[i], strlen(string[i]));
192         }
193         else
194         {
195             stream.write(string[i], length[i]);
196         }
197     }
198 
199     mState.mSource = stream.str();
200 }
201 
getInfoLogLength()202 int Shader::getInfoLogLength()
203 {
204     resolveCompile();
205     if (mInfoLog.empty())
206     {
207         return 0;
208     }
209 
210     return (static_cast<int>(mInfoLog.length()) + 1);
211 }
212 
getInfoLog(GLsizei bufSize,GLsizei * length,char * infoLog)213 void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
214 {
215     resolveCompile();
216 
217     int index = 0;
218 
219     if (bufSize > 0)
220     {
221         index = std::min(bufSize - 1, static_cast<GLsizei>(mInfoLog.length()));
222         memcpy(infoLog, mInfoLog.c_str(), index);
223 
224         infoLog[index] = '\0';
225     }
226 
227     if (length)
228     {
229         *length = index;
230     }
231 }
232 
getSourceLength() const233 int Shader::getSourceLength() const
234 {
235     return mState.mSource.empty() ? 0 : (static_cast<int>(mState.mSource.length()) + 1);
236 }
237 
getTranslatedSourceLength()238 int Shader::getTranslatedSourceLength()
239 {
240     resolveCompile();
241 
242     if (mState.mTranslatedSource.empty())
243     {
244         return 0;
245     }
246 
247     return (static_cast<int>(mState.mTranslatedSource.length()) + 1);
248 }
249 
getTranslatedSourceWithDebugInfoLength()250 int Shader::getTranslatedSourceWithDebugInfoLength()
251 {
252     resolveCompile();
253 
254     const std::string &debugInfo = mImplementation->getDebugInfo();
255     if (debugInfo.empty())
256     {
257         return 0;
258     }
259 
260     return (static_cast<int>(debugInfo.length()) + 1);
261 }
262 
263 // static
GetSourceImpl(const std::string & source,GLsizei bufSize,GLsizei * length,char * buffer)264 void Shader::GetSourceImpl(const std::string &source,
265                            GLsizei bufSize,
266                            GLsizei *length,
267                            char *buffer)
268 {
269     int index = 0;
270 
271     if (bufSize > 0)
272     {
273         index = std::min(bufSize - 1, static_cast<GLsizei>(source.length()));
274         memcpy(buffer, source.c_str(), index);
275 
276         buffer[index] = '\0';
277     }
278 
279     if (length)
280     {
281         *length = index;
282     }
283 }
284 
getSource(GLsizei bufSize,GLsizei * length,char * buffer) const285 void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const
286 {
287     GetSourceImpl(mState.mSource, bufSize, length, buffer);
288 }
289 
getTranslatedSource(GLsizei bufSize,GLsizei * length,char * buffer)290 void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer)
291 {
292     GetSourceImpl(getTranslatedSource(), bufSize, length, buffer);
293 }
294 
getTranslatedSource()295 const std::string &Shader::getTranslatedSource()
296 {
297     resolveCompile();
298     return mState.mTranslatedSource;
299 }
300 
getCompiledBinary()301 const sh::BinaryBlob &Shader::getCompiledBinary()
302 {
303     resolveCompile();
304     return mState.mCompiledBinary;
305 }
306 
getTranslatedSourceWithDebugInfo(GLsizei bufSize,GLsizei * length,char * buffer)307 void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer)
308 {
309     resolveCompile();
310     const std::string &debugInfo = mImplementation->getDebugInfo();
311     GetSourceImpl(debugInfo, bufSize, length, buffer);
312 }
313 
compile(const Context * context)314 void Shader::compile(const Context *context)
315 {
316     resolveCompile();
317 
318     mState.mTranslatedSource.clear();
319     mState.mCompiledBinary.clear();
320     mInfoLog.clear();
321     mState.mShaderVersion = 100;
322     mState.mInputVaryings.clear();
323     mState.mOutputVaryings.clear();
324     mState.mUniforms.clear();
325     mState.mUniformBlocks.clear();
326     mState.mShaderStorageBlocks.clear();
327     mState.mActiveAttributes.clear();
328     mState.mActiveOutputVariables.clear();
329     mState.mNumViews = -1;
330     mState.mGeometryShaderInputPrimitiveType.reset();
331     mState.mGeometryShaderOutputPrimitiveType.reset();
332     mState.mGeometryShaderMaxVertices.reset();
333     mState.mGeometryShaderInvocations      = 1;
334     mState.mTessControlShaderVertices      = 0;
335     mState.mTessGenMode                    = 0;
336     mState.mTessGenSpacing                 = 0;
337     mState.mTessGenVertexOrder             = 0;
338     mState.mTessGenPointMode               = 0;
339     mState.mEarlyFragmentTestsOptimization = false;
340     mState.mSpecConstUsageBits.reset();
341 
342     mState.mCompileStatus = CompileStatus::COMPILE_REQUESTED;
343     mBoundCompiler.set(context, context->getCompiler());
344 
345     ShCompileOptions options = (SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID |
346                                 SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE);
347 
348     // Add default options to WebGL shaders to prevent unexpected behavior during
349     // compilation.
350     if (context->getExtensions().webglCompatibility)
351     {
352         options |= SH_INIT_GL_POSITION;
353         options |= SH_LIMIT_CALL_STACK_DEPTH;
354         options |= SH_LIMIT_EXPRESSION_COMPLEXITY;
355         options |= SH_ENFORCE_PACKING_RESTRICTIONS;
356         options |= SH_INIT_SHARED_VARIABLES;
357     }
358 
359     // Some targets (eg D3D11 Feature Level 9_3 and below) do not support non-constant loop
360     // indexes in fragment shaders. Shader compilation will fail. To provide a better error
361     // message we can instruct the compiler to pre-validate.
362     if (mRendererLimitations.shadersRequireIndexedLoopValidation)
363     {
364         options |= SH_VALIDATE_LOOP_INDEXING;
365     }
366 
367     if (context->getFrontendFeatures().scalarizeVecAndMatConstructorArgs.enabled)
368     {
369         options |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
370     }
371 
372     mCurrentMaxComputeWorkGroupInvocations =
373         static_cast<GLuint>(context->getCaps().maxComputeWorkGroupInvocations);
374 
375     mMaxComputeSharedMemory = context->getCaps().maxComputeSharedMemorySize;
376 
377     ASSERT(mBoundCompiler.get());
378     ShCompilerInstance compilerInstance = mBoundCompiler->getInstance(mState.mShaderType);
379     ShHandle compilerHandle             = compilerInstance.getHandle();
380     ASSERT(compilerHandle);
381     mCompilerResourcesString = compilerInstance.getBuiltinResourcesString();
382 
383     mCompilingState.reset(new CompilingState());
384     mCompilingState->shCompilerInstance = std::move(compilerInstance);
385     mCompilingState->compileEvent =
386         mImplementation->compile(context, &(mCompilingState->shCompilerInstance), options);
387 }
388 
resolveCompile()389 void Shader::resolveCompile()
390 {
391     if (!mState.compilePending())
392     {
393         return;
394     }
395 
396     ASSERT(mCompilingState.get());
397 
398     mCompilingState->compileEvent->wait();
399 
400     mInfoLog += mCompilingState->compileEvent->getInfoLog();
401 
402     ScopedExit exit([this]() {
403         mBoundCompiler->putInstance(std::move(mCompilingState->shCompilerInstance));
404         mCompilingState->compileEvent.reset();
405         mCompilingState.reset();
406     });
407 
408     ShHandle compilerHandle = mCompilingState->shCompilerInstance.getHandle();
409     if (!mCompilingState->compileEvent->getResult())
410     {
411         mInfoLog += sh::GetInfoLog(compilerHandle);
412         INFO() << std::endl << mInfoLog;
413         mState.mCompileStatus = CompileStatus::NOT_COMPILED;
414         return;
415     }
416 
417     const ShShaderOutput outputType = mCompilingState->shCompilerInstance.getShaderOutputType();
418     const bool isBinaryOutput =
419         outputType == SH_SPIRV_VULKAN_OUTPUT || outputType == SH_SPIRV_METAL_OUTPUT;
420 
421     if (isBinaryOutput)
422     {
423         mState.mCompiledBinary = sh::GetObjectBinaryBlob(compilerHandle);
424     }
425     else
426     {
427         mState.mTranslatedSource = sh::GetObjectCode(compilerHandle);
428 
429 #if !defined(NDEBUG)
430         // Prefix translated shader with commented out un-translated shader.
431         // Useful in diagnostics tools which capture the shader source.
432         std::ostringstream shaderStream;
433         shaderStream << "// GLSL\n";
434         shaderStream << "//\n";
435 
436         std::istringstream inputSourceStream(mState.mSource);
437         std::string line;
438         while (std::getline(inputSourceStream, line))
439         {
440             // Remove null characters from the source line
441             line.erase(std::remove(line.begin(), line.end(), '\0'), line.end());
442 
443             shaderStream << "// " << line;
444 
445             // glslang complains if a comment ends with backslash
446             if (!line.empty() && line.back() == '\\')
447             {
448                 shaderStream << "\\";
449             }
450 
451             shaderStream << std::endl;
452         }
453         shaderStream << "\n\n";
454         shaderStream << mState.mTranslatedSource;
455         mState.mTranslatedSource = shaderStream.str();
456 #endif  // !defined(NDEBUG)
457     }
458 
459     // Gather the shader information
460     mState.mShaderVersion = sh::GetShaderVersion(compilerHandle);
461 
462     mState.mUniforms            = GetShaderVariables(sh::GetUniforms(compilerHandle));
463     mState.mUniformBlocks       = GetShaderVariables(sh::GetUniformBlocks(compilerHandle));
464     mState.mShaderStorageBlocks = GetShaderVariables(sh::GetShaderStorageBlocks(compilerHandle));
465     mState.mSpecConstUsageBits =
466         rx::SpecConstUsageBits(sh::GetShaderSpecConstUsageBits(compilerHandle));
467 
468     switch (mState.mShaderType)
469     {
470         case ShaderType::Compute:
471         {
472             mState.mAllAttributes    = GetShaderVariables(sh::GetAttributes(compilerHandle));
473             mState.mActiveAttributes = GetActiveShaderVariables(&mState.mAllAttributes);
474             mState.mLocalSize        = sh::GetComputeShaderLocalGroupSize(compilerHandle);
475             if (mState.mLocalSize.isDeclared())
476             {
477                 angle::CheckedNumeric<uint32_t> checked_local_size_product(mState.mLocalSize[0]);
478                 checked_local_size_product *= mState.mLocalSize[1];
479                 checked_local_size_product *= mState.mLocalSize[2];
480 
481                 if (!checked_local_size_product.IsValid())
482                 {
483                     WARN() << std::endl
484                            << "Integer overflow when computing the product of local_size_x, "
485                            << "local_size_y and local_size_z.";
486                     mState.mCompileStatus = CompileStatus::NOT_COMPILED;
487                     return;
488                 }
489                 if (checked_local_size_product.ValueOrDie() >
490                     mCurrentMaxComputeWorkGroupInvocations)
491                 {
492                     WARN() << std::endl
493                            << "The total number of invocations within a work group exceeds "
494                            << "MAX_COMPUTE_WORK_GROUP_INVOCATIONS.";
495                     mState.mCompileStatus = CompileStatus::NOT_COMPILED;
496                     return;
497                 }
498             }
499 
500             unsigned int sharedMemSize = sh::GetShaderSharedMemorySize(compilerHandle);
501             if (sharedMemSize > mMaxComputeSharedMemory)
502             {
503                 WARN() << std::endl << "Exceeded maximum shared memory size";
504                 mState.mCompileStatus = CompileStatus::NOT_COMPILED;
505                 return;
506             }
507             break;
508         }
509         case ShaderType::Vertex:
510         {
511             mState.mOutputVaryings   = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
512             mState.mAllAttributes    = GetShaderVariables(sh::GetAttributes(compilerHandle));
513             mState.mActiveAttributes = GetActiveShaderVariables(&mState.mAllAttributes);
514             mState.mNumViews         = sh::GetVertexShaderNumViews(compilerHandle);
515             break;
516         }
517         case ShaderType::Fragment:
518         {
519             mState.mAllAttributes    = GetShaderVariables(sh::GetAttributes(compilerHandle));
520             mState.mActiveAttributes = GetActiveShaderVariables(&mState.mAllAttributes);
521             mState.mInputVaryings    = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
522             // TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
523             std::sort(mState.mInputVaryings.begin(), mState.mInputVaryings.end(), CompareShaderVar);
524             mState.mActiveOutputVariables =
525                 GetActiveShaderVariables(sh::GetOutputVariables(compilerHandle));
526             mState.mEarlyFragmentTestsOptimization =
527                 sh::HasEarlyFragmentTestsOptimization(compilerHandle);
528             break;
529         }
530         case ShaderType::Geometry:
531         {
532             mState.mInputVaryings  = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
533             mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
534 
535             if (sh::HasValidGeometryShaderInputPrimitiveType(compilerHandle))
536             {
537                 mState.mGeometryShaderInputPrimitiveType = FromGLenum<PrimitiveMode>(
538                     sh::GetGeometryShaderInputPrimitiveType(compilerHandle));
539             }
540             if (sh::HasValidGeometryShaderOutputPrimitiveType(compilerHandle))
541             {
542                 mState.mGeometryShaderOutputPrimitiveType = FromGLenum<PrimitiveMode>(
543                     sh::GetGeometryShaderOutputPrimitiveType(compilerHandle));
544             }
545             if (sh::HasValidGeometryShaderMaxVertices(compilerHandle))
546             {
547                 mState.mGeometryShaderMaxVertices =
548                     sh::GetGeometryShaderMaxVertices(compilerHandle);
549             }
550             mState.mGeometryShaderInvocations = sh::GetGeometryShaderInvocations(compilerHandle);
551             break;
552         }
553         case ShaderType::TessControl:
554         {
555             mState.mInputVaryings  = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
556             mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
557             mState.mTessControlShaderVertices = sh::GetTessControlShaderVertices(compilerHandle);
558             break;
559         }
560         case ShaderType::TessEvaluation:
561         {
562             mState.mInputVaryings  = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
563             mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
564             if (sh::HasValidTessGenMode(compilerHandle))
565             {
566                 mState.mTessGenMode = sh::GetTessGenMode(compilerHandle);
567             }
568             if (sh::HasValidTessGenSpacing(compilerHandle))
569             {
570                 mState.mTessGenSpacing = sh::GetTessGenSpacing(compilerHandle);
571             }
572             if (sh::HasValidTessGenVertexOrder(compilerHandle))
573             {
574                 mState.mTessGenVertexOrder = sh::GetTessGenVertexOrder(compilerHandle);
575             }
576             if (sh::HasValidTessGenPointMode(compilerHandle))
577             {
578                 mState.mTessGenPointMode = sh::GetTessGenPointMode(compilerHandle);
579             }
580             break;
581         }
582 
583         default:
584             UNREACHABLE();
585     }
586 
587     ASSERT(!mState.mTranslatedSource.empty() || !mState.mCompiledBinary.empty());
588 
589     bool success          = mCompilingState->compileEvent->postTranslate(&mInfoLog);
590     mState.mCompileStatus = success ? CompileStatus::COMPILED : CompileStatus::NOT_COMPILED;
591 }
592 
addRef()593 void Shader::addRef()
594 {
595     mRefCount++;
596 }
597 
release(const Context * context)598 void Shader::release(const Context *context)
599 {
600     mRefCount--;
601 
602     if (mRefCount == 0 && mDeleteStatus)
603     {
604         mResourceManager->deleteShader(context, mHandle);
605     }
606 }
607 
getRefCount() const608 unsigned int Shader::getRefCount() const
609 {
610     return mRefCount;
611 }
612 
isFlaggedForDeletion() const613 bool Shader::isFlaggedForDeletion() const
614 {
615     return mDeleteStatus;
616 }
617 
flagForDeletion()618 void Shader::flagForDeletion()
619 {
620     mDeleteStatus = true;
621 }
622 
isCompiled()623 bool Shader::isCompiled()
624 {
625     resolveCompile();
626     return mState.mCompileStatus == CompileStatus::COMPILED;
627 }
628 
isCompleted()629 bool Shader::isCompleted()
630 {
631     return (!mState.compilePending() || mCompilingState->compileEvent->isReady());
632 }
633 
getShaderVersion()634 int Shader::getShaderVersion()
635 {
636     resolveCompile();
637     return mState.mShaderVersion;
638 }
639 
getInputVaryings()640 const std::vector<sh::ShaderVariable> &Shader::getInputVaryings()
641 {
642     resolveCompile();
643     return mState.getInputVaryings();
644 }
645 
getOutputVaryings()646 const std::vector<sh::ShaderVariable> &Shader::getOutputVaryings()
647 {
648     resolveCompile();
649     return mState.getOutputVaryings();
650 }
651 
getUniforms()652 const std::vector<sh::ShaderVariable> &Shader::getUniforms()
653 {
654     resolveCompile();
655     return mState.getUniforms();
656 }
657 
getUniformBlocks()658 const std::vector<sh::InterfaceBlock> &Shader::getUniformBlocks()
659 {
660     resolveCompile();
661     return mState.getUniformBlocks();
662 }
663 
getShaderStorageBlocks()664 const std::vector<sh::InterfaceBlock> &Shader::getShaderStorageBlocks()
665 {
666     resolveCompile();
667     return mState.getShaderStorageBlocks();
668 }
669 
getActiveAttributes()670 const std::vector<sh::ShaderVariable> &Shader::getActiveAttributes()
671 {
672     resolveCompile();
673     return mState.getActiveAttributes();
674 }
675 
getAllAttributes()676 const std::vector<sh::ShaderVariable> &Shader::getAllAttributes()
677 {
678     resolveCompile();
679     return mState.getAllAttributes();
680 }
681 
getActiveOutputVariables()682 const std::vector<sh::ShaderVariable> &Shader::getActiveOutputVariables()
683 {
684     resolveCompile();
685     return mState.getActiveOutputVariables();
686 }
687 
getTransformFeedbackVaryingMappedName(const std::string & tfVaryingName)688 std::string Shader::getTransformFeedbackVaryingMappedName(const std::string &tfVaryingName)
689 {
690     ASSERT(mState.getShaderType() != ShaderType::Fragment &&
691            mState.getShaderType() != ShaderType::Compute);
692     const auto &varyings = getOutputVaryings();
693     auto bracketPos      = tfVaryingName.find("[");
694     if (bracketPos != std::string::npos)
695     {
696         auto tfVaryingBaseName = tfVaryingName.substr(0, bracketPos);
697         for (const auto &varying : varyings)
698         {
699             if (varying.name == tfVaryingBaseName)
700             {
701                 std::string mappedNameWithArrayIndex =
702                     varying.mappedName + tfVaryingName.substr(bracketPos);
703                 return mappedNameWithArrayIndex;
704             }
705         }
706     }
707     else
708     {
709         for (const auto &varying : varyings)
710         {
711             if (varying.name == tfVaryingName)
712             {
713                 return varying.mappedName;
714             }
715             else if (varying.isStruct())
716             {
717                 GLuint fieldIndex = 0;
718                 const auto *field = varying.findField(tfVaryingName, &fieldIndex);
719                 if (field == nullptr)
720                 {
721                     continue;
722                 }
723                 ASSERT(field != nullptr && !field->isStruct() &&
724                        (!field->isArray() || varying.isShaderIOBlock));
725                 std::string mappedName;
726                 // If it's an I/O block without an instance name, don't include the block name.
727                 if (!varying.isShaderIOBlock || !varying.name.empty())
728                 {
729                     mappedName = varying.isShaderIOBlock ? varying.mappedStructOrBlockName
730                                                          : varying.mappedName;
731                     mappedName += '.';
732                 }
733                 return mappedName + field->mappedName;
734             }
735         }
736     }
737     UNREACHABLE();
738     return std::string();
739 }
740 
getWorkGroupSize()741 const sh::WorkGroupSize &Shader::getWorkGroupSize()
742 {
743     resolveCompile();
744     return mState.mLocalSize;
745 }
746 
getNumViews()747 int Shader::getNumViews()
748 {
749     resolveCompile();
750     return mState.mNumViews;
751 }
752 
getGeometryShaderInputPrimitiveType()753 Optional<PrimitiveMode> Shader::getGeometryShaderInputPrimitiveType()
754 {
755     resolveCompile();
756     return mState.mGeometryShaderInputPrimitiveType;
757 }
758 
getGeometryShaderOutputPrimitiveType()759 Optional<PrimitiveMode> Shader::getGeometryShaderOutputPrimitiveType()
760 {
761     resolveCompile();
762     return mState.mGeometryShaderOutputPrimitiveType;
763 }
764 
getGeometryShaderInvocations()765 int Shader::getGeometryShaderInvocations()
766 {
767     resolveCompile();
768     return mState.mGeometryShaderInvocations;
769 }
770 
getGeometryShaderMaxVertices()771 Optional<GLint> Shader::getGeometryShaderMaxVertices()
772 {
773     resolveCompile();
774     return mState.mGeometryShaderMaxVertices;
775 }
776 
getTessControlShaderVertices()777 int Shader::getTessControlShaderVertices()
778 {
779     resolveCompile();
780     return mState.mTessControlShaderVertices;
781 }
782 
getTessGenMode()783 GLenum Shader::getTessGenMode()
784 {
785     resolveCompile();
786     return mState.mTessGenMode;
787 }
788 
getTessGenSpacing()789 GLenum Shader::getTessGenSpacing()
790 {
791     resolveCompile();
792     return mState.mTessGenSpacing;
793 }
794 
getTessGenVertexOrder()795 GLenum Shader::getTessGenVertexOrder()
796 {
797     resolveCompile();
798     return mState.mTessGenVertexOrder;
799 }
800 
getTessGenPointMode()801 GLenum Shader::getTessGenPointMode()
802 {
803     resolveCompile();
804     return mState.mTessGenPointMode;
805 }
806 
getCompilerResourcesString() const807 const std::string &Shader::getCompilerResourcesString() const
808 {
809     return mCompilerResourcesString;
810 }
811 
812 }  // namespace gl
813