• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 ANGLE_NO_DISCARD 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.mAdvancedBlendEquations.reset();
340     mState.mEarlyFragmentTestsOptimization = false;
341     mState.mSpecConstUsageBits.reset();
342 
343     mState.mCompileStatus = CompileStatus::COMPILE_REQUESTED;
344     mBoundCompiler.set(context, context->getCompiler());
345 
346     ShCompileOptions options = (SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID);
347 
348     // Add default options to WebGL shaders to prevent unexpected behavior during
349     // compilation.
350     if (context->isWebGL())
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     else
359     {
360         // Per https://github.com/KhronosGroup/WebGL/pull/3278 gl_BaseVertex/gl_BaseInstance are
361         // removed from WebGL
362         options |= SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE;
363     }
364 
365     // Some targets (e.g. D3D11 Feature Level 9_3 and below) do not support non-constant loop
366     // indexes in fragment shaders. Shader compilation will fail. To provide a better error
367     // message we can instruct the compiler to pre-validate.
368     if (mRendererLimitations.shadersRequireIndexedLoopValidation)
369     {
370         options |= SH_VALIDATE_LOOP_INDEXING;
371     }
372 
373     if (context->getFrontendFeatures().scalarizeVecAndMatConstructorArgs.enabled)
374     {
375         options |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
376     }
377 
378     if (context->getFrontendFeatures().forceInitShaderVariables.enabled)
379     {
380         options |= SH_INIT_OUTPUT_VARIABLES;
381         options |= SH_INITIALIZE_UNINITIALIZED_LOCALS;
382     }
383 
384     mCurrentMaxComputeWorkGroupInvocations =
385         static_cast<GLuint>(context->getCaps().maxComputeWorkGroupInvocations);
386 
387     mMaxComputeSharedMemory = context->getCaps().maxComputeSharedMemorySize;
388 
389     ASSERT(mBoundCompiler.get());
390     ShCompilerInstance compilerInstance = mBoundCompiler->getInstance(mState.mShaderType);
391     ShHandle compilerHandle             = compilerInstance.getHandle();
392     ASSERT(compilerHandle);
393     mCompilerResourcesString = compilerInstance.getBuiltinResourcesString();
394 
395     mCompilingState.reset(new CompilingState());
396     mCompilingState->shCompilerInstance = std::move(compilerInstance);
397     mCompilingState->compileEvent =
398         mImplementation->compile(context, &(mCompilingState->shCompilerInstance), options);
399 }
400 
resolveCompile()401 void Shader::resolveCompile()
402 {
403     if (!mState.compilePending())
404     {
405         return;
406     }
407 
408     ASSERT(mCompilingState.get());
409 
410     mCompilingState->compileEvent->wait();
411 
412     mInfoLog += mCompilingState->compileEvent->getInfoLog();
413 
414     ScopedExit exit([this]() {
415         mBoundCompiler->putInstance(std::move(mCompilingState->shCompilerInstance));
416         mCompilingState->compileEvent.reset();
417         mCompilingState.reset();
418     });
419 
420     ShHandle compilerHandle = mCompilingState->shCompilerInstance.getHandle();
421     if (!mCompilingState->compileEvent->getResult())
422     {
423         mInfoLog += sh::GetInfoLog(compilerHandle);
424         INFO() << std::endl << mInfoLog;
425         mState.mCompileStatus = CompileStatus::NOT_COMPILED;
426         return;
427     }
428 
429     const ShShaderOutput outputType = mCompilingState->shCompilerInstance.getShaderOutputType();
430     const bool isBinaryOutput =
431         outputType == SH_SPIRV_VULKAN_OUTPUT || outputType == SH_SPIRV_METAL_OUTPUT;
432 
433     if (isBinaryOutput)
434     {
435         mState.mCompiledBinary = sh::GetObjectBinaryBlob(compilerHandle);
436     }
437     else
438     {
439         mState.mTranslatedSource = sh::GetObjectCode(compilerHandle);
440 
441 #if !defined(NDEBUG)
442         // Prefix translated shader with commented out un-translated shader.
443         // Useful in diagnostics tools which capture the shader source.
444         std::ostringstream shaderStream;
445         shaderStream << "// GLSL\n";
446         shaderStream << "//\n";
447 
448         std::istringstream inputSourceStream(mState.mSource);
449         std::string line;
450         while (std::getline(inputSourceStream, line))
451         {
452             // Remove null characters from the source line
453             line.erase(std::remove(line.begin(), line.end(), '\0'), line.end());
454 
455             shaderStream << "// " << line;
456 
457             // glslang complains if a comment ends with backslash
458             if (!line.empty() && line.back() == '\\')
459             {
460                 shaderStream << "\\";
461             }
462 
463             shaderStream << std::endl;
464         }
465         shaderStream << "\n\n";
466         shaderStream << mState.mTranslatedSource;
467         mState.mTranslatedSource = shaderStream.str();
468 #endif  // !defined(NDEBUG)
469     }
470 
471     // Gather the shader information
472     mState.mShaderVersion = sh::GetShaderVersion(compilerHandle);
473 
474     mState.mUniforms            = GetShaderVariables(sh::GetUniforms(compilerHandle));
475     mState.mUniformBlocks       = GetShaderVariables(sh::GetUniformBlocks(compilerHandle));
476     mState.mShaderStorageBlocks = GetShaderVariables(sh::GetShaderStorageBlocks(compilerHandle));
477     mState.mSpecConstUsageBits =
478         rx::SpecConstUsageBits(sh::GetShaderSpecConstUsageBits(compilerHandle));
479 
480     switch (mState.mShaderType)
481     {
482         case ShaderType::Compute:
483         {
484             mState.mAllAttributes    = GetShaderVariables(sh::GetAttributes(compilerHandle));
485             mState.mActiveAttributes = GetActiveShaderVariables(&mState.mAllAttributes);
486             mState.mLocalSize        = sh::GetComputeShaderLocalGroupSize(compilerHandle);
487             if (mState.mLocalSize.isDeclared())
488             {
489                 angle::CheckedNumeric<uint32_t> checked_local_size_product(mState.mLocalSize[0]);
490                 checked_local_size_product *= mState.mLocalSize[1];
491                 checked_local_size_product *= mState.mLocalSize[2];
492 
493                 if (!checked_local_size_product.IsValid())
494                 {
495                     WARN() << std::endl
496                            << "Integer overflow when computing the product of local_size_x, "
497                            << "local_size_y and local_size_z.";
498                     mState.mCompileStatus = CompileStatus::NOT_COMPILED;
499                     return;
500                 }
501                 if (checked_local_size_product.ValueOrDie() >
502                     mCurrentMaxComputeWorkGroupInvocations)
503                 {
504                     WARN() << std::endl
505                            << "The total number of invocations within a work group exceeds "
506                            << "MAX_COMPUTE_WORK_GROUP_INVOCATIONS.";
507                     mState.mCompileStatus = CompileStatus::NOT_COMPILED;
508                     return;
509                 }
510             }
511 
512             unsigned int sharedMemSize = sh::GetShaderSharedMemorySize(compilerHandle);
513             if (sharedMemSize > mMaxComputeSharedMemory)
514             {
515                 WARN() << std::endl << "Exceeded maximum shared memory size";
516                 mState.mCompileStatus = CompileStatus::NOT_COMPILED;
517                 return;
518             }
519             break;
520         }
521         case ShaderType::Vertex:
522         {
523             mState.mOutputVaryings   = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
524             mState.mAllAttributes    = GetShaderVariables(sh::GetAttributes(compilerHandle));
525             mState.mActiveAttributes = GetActiveShaderVariables(&mState.mAllAttributes);
526             mState.mNumViews         = sh::GetVertexShaderNumViews(compilerHandle);
527             break;
528         }
529         case ShaderType::Fragment:
530         {
531             mState.mAllAttributes    = GetShaderVariables(sh::GetAttributes(compilerHandle));
532             mState.mActiveAttributes = GetActiveShaderVariables(&mState.mAllAttributes);
533             mState.mInputVaryings    = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
534             // TODO(jmadill): Figure out why we only sort in the FS, and if we need to.
535             std::sort(mState.mInputVaryings.begin(), mState.mInputVaryings.end(), CompareShaderVar);
536             mState.mActiveOutputVariables =
537                 GetActiveShaderVariables(sh::GetOutputVariables(compilerHandle));
538             mState.mEarlyFragmentTestsOptimization =
539                 sh::HasEarlyFragmentTestsOptimization(compilerHandle);
540             mState.mAdvancedBlendEquations =
541                 BlendEquationBitSet(sh::GetAdvancedBlendEquations(compilerHandle));
542             break;
543         }
544         case ShaderType::Geometry:
545         {
546             mState.mInputVaryings  = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
547             mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
548 
549             if (sh::HasValidGeometryShaderInputPrimitiveType(compilerHandle))
550             {
551                 mState.mGeometryShaderInputPrimitiveType = FromGLenum<PrimitiveMode>(
552                     sh::GetGeometryShaderInputPrimitiveType(compilerHandle));
553             }
554             if (sh::HasValidGeometryShaderOutputPrimitiveType(compilerHandle))
555             {
556                 mState.mGeometryShaderOutputPrimitiveType = FromGLenum<PrimitiveMode>(
557                     sh::GetGeometryShaderOutputPrimitiveType(compilerHandle));
558             }
559             if (sh::HasValidGeometryShaderMaxVertices(compilerHandle))
560             {
561                 mState.mGeometryShaderMaxVertices =
562                     sh::GetGeometryShaderMaxVertices(compilerHandle);
563             }
564             mState.mGeometryShaderInvocations = sh::GetGeometryShaderInvocations(compilerHandle);
565             break;
566         }
567         case ShaderType::TessControl:
568         {
569             mState.mInputVaryings  = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
570             mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
571             mState.mTessControlShaderVertices = sh::GetTessControlShaderVertices(compilerHandle);
572             break;
573         }
574         case ShaderType::TessEvaluation:
575         {
576             mState.mInputVaryings  = GetShaderVariables(sh::GetInputVaryings(compilerHandle));
577             mState.mOutputVaryings = GetShaderVariables(sh::GetOutputVaryings(compilerHandle));
578             if (sh::HasValidTessGenMode(compilerHandle))
579             {
580                 mState.mTessGenMode = sh::GetTessGenMode(compilerHandle);
581             }
582             if (sh::HasValidTessGenSpacing(compilerHandle))
583             {
584                 mState.mTessGenSpacing = sh::GetTessGenSpacing(compilerHandle);
585             }
586             if (sh::HasValidTessGenVertexOrder(compilerHandle))
587             {
588                 mState.mTessGenVertexOrder = sh::GetTessGenVertexOrder(compilerHandle);
589             }
590             if (sh::HasValidTessGenPointMode(compilerHandle))
591             {
592                 mState.mTessGenPointMode = sh::GetTessGenPointMode(compilerHandle);
593             }
594             break;
595         }
596 
597         default:
598             UNREACHABLE();
599     }
600 
601     ASSERT(!mState.mTranslatedSource.empty() || !mState.mCompiledBinary.empty());
602 
603     bool success          = mCompilingState->compileEvent->postTranslate(&mInfoLog);
604     mState.mCompileStatus = success ? CompileStatus::COMPILED : CompileStatus::NOT_COMPILED;
605 }
606 
addRef()607 void Shader::addRef()
608 {
609     mRefCount++;
610 }
611 
release(const Context * context)612 void Shader::release(const Context *context)
613 {
614     mRefCount--;
615 
616     if (mRefCount == 0 && mDeleteStatus)
617     {
618         mResourceManager->deleteShader(context, mHandle);
619     }
620 }
621 
getRefCount() const622 unsigned int Shader::getRefCount() const
623 {
624     return mRefCount;
625 }
626 
isFlaggedForDeletion() const627 bool Shader::isFlaggedForDeletion() const
628 {
629     return mDeleteStatus;
630 }
631 
flagForDeletion()632 void Shader::flagForDeletion()
633 {
634     mDeleteStatus = true;
635 }
636 
isCompiled()637 bool Shader::isCompiled()
638 {
639     resolveCompile();
640     return mState.mCompileStatus == CompileStatus::COMPILED;
641 }
642 
isCompleted()643 bool Shader::isCompleted()
644 {
645     return (!mState.compilePending() || mCompilingState->compileEvent->isReady());
646 }
647 
getShaderVersion()648 int Shader::getShaderVersion()
649 {
650     resolveCompile();
651     return mState.mShaderVersion;
652 }
653 
getInputVaryings()654 const std::vector<sh::ShaderVariable> &Shader::getInputVaryings()
655 {
656     resolveCompile();
657     return mState.getInputVaryings();
658 }
659 
getOutputVaryings()660 const std::vector<sh::ShaderVariable> &Shader::getOutputVaryings()
661 {
662     resolveCompile();
663     return mState.getOutputVaryings();
664 }
665 
getUniforms()666 const std::vector<sh::ShaderVariable> &Shader::getUniforms()
667 {
668     resolveCompile();
669     return mState.getUniforms();
670 }
671 
getUniformBlocks()672 const std::vector<sh::InterfaceBlock> &Shader::getUniformBlocks()
673 {
674     resolveCompile();
675     return mState.getUniformBlocks();
676 }
677 
getShaderStorageBlocks()678 const std::vector<sh::InterfaceBlock> &Shader::getShaderStorageBlocks()
679 {
680     resolveCompile();
681     return mState.getShaderStorageBlocks();
682 }
683 
getActiveAttributes()684 const std::vector<sh::ShaderVariable> &Shader::getActiveAttributes()
685 {
686     resolveCompile();
687     return mState.getActiveAttributes();
688 }
689 
getAllAttributes()690 const std::vector<sh::ShaderVariable> &Shader::getAllAttributes()
691 {
692     resolveCompile();
693     return mState.getAllAttributes();
694 }
695 
getActiveOutputVariables()696 const std::vector<sh::ShaderVariable> &Shader::getActiveOutputVariables()
697 {
698     resolveCompile();
699     return mState.getActiveOutputVariables();
700 }
701 
getTransformFeedbackVaryingMappedName(const std::string & tfVaryingName)702 std::string Shader::getTransformFeedbackVaryingMappedName(const std::string &tfVaryingName)
703 {
704     ASSERT(mState.getShaderType() != ShaderType::Fragment &&
705            mState.getShaderType() != ShaderType::Compute);
706     const auto &varyings = getOutputVaryings();
707     auto bracketPos      = tfVaryingName.find("[");
708     if (bracketPos != std::string::npos)
709     {
710         auto tfVaryingBaseName = tfVaryingName.substr(0, bracketPos);
711         for (const auto &varying : varyings)
712         {
713             if (varying.name == tfVaryingBaseName)
714             {
715                 std::string mappedNameWithArrayIndex =
716                     varying.mappedName + tfVaryingName.substr(bracketPos);
717                 return mappedNameWithArrayIndex;
718             }
719         }
720     }
721     else
722     {
723         for (const auto &varying : varyings)
724         {
725             if (varying.name == tfVaryingName)
726             {
727                 return varying.mappedName;
728             }
729             else if (varying.isStruct())
730             {
731                 GLuint fieldIndex = 0;
732                 const auto *field = varying.findField(tfVaryingName, &fieldIndex);
733                 if (field == nullptr)
734                 {
735                     continue;
736                 }
737                 ASSERT(field != nullptr && !field->isStruct() &&
738                        (!field->isArray() || varying.isShaderIOBlock));
739                 std::string mappedName;
740                 // If it's an I/O block without an instance name, don't include the block name.
741                 if (!varying.isShaderIOBlock || !varying.name.empty())
742                 {
743                     mappedName = varying.isShaderIOBlock ? varying.mappedStructOrBlockName
744                                                          : varying.mappedName;
745                     mappedName += '.';
746                 }
747                 return mappedName + field->mappedName;
748             }
749         }
750     }
751     UNREACHABLE();
752     return std::string();
753 }
754 
getWorkGroupSize()755 const sh::WorkGroupSize &Shader::getWorkGroupSize()
756 {
757     resolveCompile();
758     return mState.mLocalSize;
759 }
760 
getNumViews()761 int Shader::getNumViews()
762 {
763     resolveCompile();
764     return mState.mNumViews;
765 }
766 
getGeometryShaderInputPrimitiveType()767 Optional<PrimitiveMode> Shader::getGeometryShaderInputPrimitiveType()
768 {
769     resolveCompile();
770     return mState.mGeometryShaderInputPrimitiveType;
771 }
772 
getGeometryShaderOutputPrimitiveType()773 Optional<PrimitiveMode> Shader::getGeometryShaderOutputPrimitiveType()
774 {
775     resolveCompile();
776     return mState.mGeometryShaderOutputPrimitiveType;
777 }
778 
getGeometryShaderInvocations()779 int Shader::getGeometryShaderInvocations()
780 {
781     resolveCompile();
782     return mState.mGeometryShaderInvocations;
783 }
784 
getGeometryShaderMaxVertices()785 Optional<GLint> Shader::getGeometryShaderMaxVertices()
786 {
787     resolveCompile();
788     return mState.mGeometryShaderMaxVertices;
789 }
790 
getTessControlShaderVertices()791 int Shader::getTessControlShaderVertices()
792 {
793     resolveCompile();
794     return mState.mTessControlShaderVertices;
795 }
796 
getTessGenMode()797 GLenum Shader::getTessGenMode()
798 {
799     resolveCompile();
800     return mState.mTessGenMode;
801 }
802 
getTessGenSpacing()803 GLenum Shader::getTessGenSpacing()
804 {
805     resolveCompile();
806     return mState.mTessGenSpacing;
807 }
808 
getTessGenVertexOrder()809 GLenum Shader::getTessGenVertexOrder()
810 {
811     resolveCompile();
812     return mState.mTessGenVertexOrder;
813 }
814 
getTessGenPointMode()815 GLenum Shader::getTessGenPointMode()
816 {
817     resolveCompile();
818     return mState.mTessGenPointMode;
819 }
820 
getCompilerResourcesString() const821 const std::string &Shader::getCompilerResourcesString() const
822 {
823     return mCompilerResourcesString;
824 }
825 
826 }  // namespace gl
827