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