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