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