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