LCOV - code coverage report
Current view: top level - dom/canvas - WebGLShaderValidator.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 280 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 21 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "WebGLShaderValidator.h"
       7             : 
       8             : #include "angle/ShaderLang.h"
       9             : #include "gfxPrefs.h"
      10             : #include "GLContext.h"
      11             : #include "mozilla/Preferences.h"
      12             : #include "MurmurHash3.h"
      13             : #include "nsPrintfCString.h"
      14             : #include <string>
      15             : #include <vector>
      16             : #include "WebGLContext.h"
      17             : 
      18             : namespace mozilla {
      19             : namespace webgl {
      20             : 
      21             : uint64_t
      22           0 : IdentifierHashFunc(const char* name, size_t len)
      23             : {
      24             :     // NB: we use the x86 function everywhere, even though it's suboptimal perf
      25             :     // on x64.  They return different results; not sure if that's a requirement.
      26             :     uint64_t hash[2];
      27           0 :     MurmurHash3_x86_128(name, len, 0, hash);
      28           0 :     return hash[0];
      29             : }
      30             : 
      31             : static ShCompileOptions
      32           0 : ChooseValidatorCompileOptions(const ShBuiltInResources& resources,
      33             :                               const mozilla::gl::GLContext* gl)
      34             : {
      35             :     ShCompileOptions options = SH_VARIABLES |
      36             :                                SH_ENFORCE_PACKING_RESTRICTIONS |
      37             :                                SH_OBJECT_CODE |
      38           0 :                                SH_INIT_GL_POSITION;
      39             : 
      40             : #ifndef XP_MACOSX
      41             :     // We want to do this everywhere, but to do this on Mac, we need
      42             :     // to do it only on Mac OSX > 10.6 as this causes the shader
      43             :     // compiler in 10.6 to crash
      44           0 :     options |= SH_CLAMP_INDIRECT_ARRAY_BOUNDS;
      45             : #endif
      46             : 
      47           0 :     if (gl->WorkAroundDriverBugs()) {
      48             : #ifdef XP_MACOSX
      49             :         // Work around https://bugs.webkit.org/show_bug.cgi?id=124684,
      50             :         // https://chromium.googlesource.com/angle/angle/+/5e70cf9d0b1bb
      51             :         options |= SH_UNFOLD_SHORT_CIRCUIT;
      52             : 
      53             :         // Work around that Mac drivers handle struct scopes incorrectly.
      54             :         options |= SH_REGENERATE_STRUCT_NAMES;
      55             :         options |= SH_INIT_OUTPUT_VARIABLES;
      56             : 
      57             :         // Work around that Intel drivers on Mac OSX handle for-loop incorrectly.
      58             :         if (gl->Vendor() == gl::GLVendor::Intel) {
      59             :             options |= SH_ADD_AND_TRUE_TO_LOOP_CONDITION;
      60             :         }
      61             : #endif
      62             : 
      63           0 :         if (!gl->IsANGLE() && gl->Vendor() == gl::GLVendor::Intel) {
      64             :             // Failures on at least Windows+Intel+OGL on:
      65             :             // conformance/glsl/constructors/glsl-construct-mat2.html
      66           0 :             options |= SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS;
      67             :         }
      68             :     }
      69             : 
      70           0 :     if (gfxPrefs::WebGLAllANGLEOptions()) {
      71           0 :         options = -1;
      72             : 
      73           0 :         options ^= SH_INTERMEDIATE_TREE;
      74           0 :         options ^= SH_LINE_DIRECTIVES;
      75           0 :         options ^= SH_SOURCE_PATH;
      76             : 
      77           0 :         options ^= SH_LIMIT_EXPRESSION_COMPLEXITY;
      78           0 :         options ^= SH_LIMIT_CALL_STACK_DEPTH;
      79             : 
      80           0 :         options ^= SH_EXPAND_SELECT_HLSL_INTEGER_POW_EXPRESSIONS;
      81           0 :         options ^= SH_HLSL_GET_DIMENSIONS_IGNORES_BASE_LEVEL;
      82             : 
      83           0 :         options ^= SH_DONT_REMOVE_INVARIANT_FOR_FRAGMENT_INPUT;
      84           0 :         options ^= SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3;
      85             :     }
      86             : 
      87           0 :     if (resources.MaxExpressionComplexity > 0) {
      88           0 :         options |= SH_LIMIT_EXPRESSION_COMPLEXITY;
      89             :     }
      90           0 :     if (resources.MaxCallStackDepth > 0) {
      91           0 :         options |= SH_LIMIT_CALL_STACK_DEPTH;
      92             :     }
      93             : 
      94           0 :     return options;
      95             : }
      96             : 
      97             : } // namespace webgl
      98             : 
      99             : ////////////////////////////////////////
     100             : 
     101             : static ShShaderOutput
     102           0 : ShaderOutput(gl::GLContext* gl)
     103             : {
     104           0 :     if (gl->IsGLES()) {
     105           0 :         return SH_ESSL_OUTPUT;
     106             :     } else {
     107           0 :         uint32_t version = gl->ShadingLanguageVersion();
     108           0 :         switch (version) {
     109           0 :         case 100: return SH_GLSL_COMPATIBILITY_OUTPUT;
     110           0 :         case 120: return SH_GLSL_COMPATIBILITY_OUTPUT;
     111           0 :         case 130: return SH_GLSL_130_OUTPUT;
     112           0 :         case 140: return SH_GLSL_140_OUTPUT;
     113           0 :         case 150: return SH_GLSL_150_CORE_OUTPUT;
     114           0 :         case 330: return SH_GLSL_330_CORE_OUTPUT;
     115           0 :         case 400: return SH_GLSL_400_CORE_OUTPUT;
     116           0 :         case 410: return SH_GLSL_410_CORE_OUTPUT;
     117           0 :         case 420: return SH_GLSL_420_CORE_OUTPUT;
     118           0 :         case 430: return SH_GLSL_430_CORE_OUTPUT;
     119           0 :         case 440: return SH_GLSL_440_CORE_OUTPUT;
     120           0 :         case 450: return SH_GLSL_450_CORE_OUTPUT;
     121             :         default:
     122           0 :             MOZ_CRASH("GFX: Unexpected GLSL version.");
     123             :         }
     124             :     }
     125             : 
     126             :     return SH_GLSL_COMPATIBILITY_OUTPUT;
     127             : }
     128             : 
     129             : webgl::ShaderValidator*
     130           0 : WebGLContext::CreateShaderValidator(GLenum shaderType) const
     131             : {
     132           0 :     if (mBypassShaderValidation)
     133           0 :         return nullptr;
     134             : 
     135           0 :     const auto spec = (IsWebGL2() ? SH_WEBGL2_SPEC : SH_WEBGL_SPEC);
     136           0 :     const auto outputLanguage = ShaderOutput(gl);
     137             : 
     138             :     ShBuiltInResources resources;
     139           0 :     memset(&resources, 0, sizeof(resources));
     140           0 :     ShInitBuiltInResources(&resources);
     141             : 
     142           0 :     resources.HashFunction = webgl::IdentifierHashFunc;
     143             : 
     144           0 :     resources.MaxVertexAttribs = mGLMaxVertexAttribs;
     145           0 :     resources.MaxVertexUniformVectors = mGLMaxVertexUniformVectors;
     146           0 :     resources.MaxVaryingVectors = mGLMaxVaryingVectors;
     147           0 :     resources.MaxVertexTextureImageUnits = mGLMaxVertexTextureImageUnits;
     148           0 :     resources.MaxCombinedTextureImageUnits = mGLMaxTextureUnits;
     149           0 :     resources.MaxTextureImageUnits = mGLMaxTextureImageUnits;
     150           0 :     resources.MaxFragmentUniformVectors = mGLMaxFragmentUniformVectors;
     151             : 
     152           0 :     const bool hasMRTs = (IsWebGL2() ||
     153           0 :                           IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers));
     154           0 :     resources.MaxDrawBuffers = (hasMRTs ? mGLMaxDrawBuffers : 1);
     155             : 
     156           0 :     if (IsExtensionEnabled(WebGLExtensionID::EXT_frag_depth))
     157           0 :         resources.EXT_frag_depth = 1;
     158             : 
     159           0 :     if (IsExtensionEnabled(WebGLExtensionID::OES_standard_derivatives))
     160           0 :         resources.OES_standard_derivatives = 1;
     161             : 
     162           0 :     if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
     163           0 :         resources.EXT_draw_buffers = 1;
     164             : 
     165           0 :     if (IsExtensionEnabled(WebGLExtensionID::EXT_shader_texture_lod))
     166           0 :         resources.EXT_shader_texture_lod = 1;
     167             : 
     168             :     // Tell ANGLE to allow highp in frag shaders. (unless disabled)
     169             :     // If underlying GLES doesn't have highp in frag shaders, it should complain anyways.
     170           0 :     resources.FragmentPrecisionHigh = mDisableFragHighP ? 0 : 1;
     171             : 
     172           0 :     if (gl->WorkAroundDriverBugs()) {
     173             : #ifdef XP_MACOSX
     174             :         if (gl->Vendor() == gl::GLVendor::NVIDIA) {
     175             :             // Work around bug 890432
     176             :             resources.MaxExpressionComplexity = 1000;
     177             :         }
     178             : #endif
     179             :     }
     180             : 
     181           0 :     const auto compileOptions = webgl::ChooseValidatorCompileOptions(resources, gl);
     182             :     return webgl::ShaderValidator::Create(shaderType, spec, outputLanguage, resources,
     183           0 :                                           compileOptions);
     184             : }
     185             : 
     186             : ////////////////////////////////////////
     187             : 
     188             : namespace webgl {
     189             : 
     190             : /*static*/ ShaderValidator*
     191           0 : ShaderValidator::Create(GLenum shaderType, ShShaderSpec spec,
     192             :                         ShShaderOutput outputLanguage,
     193             :                         const ShBuiltInResources& resources,
     194             :                         ShCompileOptions compileOptions)
     195             : {
     196           0 :     ShHandle handle = ShConstructCompiler(shaderType, spec, outputLanguage, &resources);
     197           0 :     if (!handle)
     198           0 :         return nullptr;
     199             : 
     200           0 :     return new ShaderValidator(handle, compileOptions, resources.MaxVaryingVectors);
     201             : }
     202             : 
     203           0 : ShaderValidator::~ShaderValidator()
     204             : {
     205           0 :     ShDestruct(mHandle);
     206           0 : }
     207             : 
     208             : bool
     209           0 : ShaderValidator::ValidateAndTranslate(const char* source)
     210             : {
     211           0 :     MOZ_ASSERT(!mHasRun);
     212           0 :     mHasRun = true;
     213             : 
     214             :     const char* const parts[] = {
     215             :         source
     216           0 :     };
     217           0 :     return ShCompile(mHandle, parts, ArrayLength(parts), mCompileOptions);
     218             : }
     219             : 
     220             : void
     221           0 : ShaderValidator::GetInfoLog(nsACString* out) const
     222             : {
     223           0 :     MOZ_ASSERT(mHasRun);
     224             : 
     225           0 :     const std::string &log = ShGetInfoLog(mHandle);
     226           0 :     out->Assign(log.data(), log.length());
     227           0 : }
     228             : 
     229             : void
     230           0 : ShaderValidator::GetOutput(nsACString* out) const
     231             : {
     232           0 :     MOZ_ASSERT(mHasRun);
     233             : 
     234           0 :     const std::string &output = ShGetObjectCode(mHandle);
     235           0 :     out->Assign(output.data(), output.length());
     236           0 : }
     237             : 
     238             : template<size_t N>
     239             : static bool
     240           0 : StartsWith(const std::string& haystack, const char (&needle)[N])
     241             : {
     242           0 :     return haystack.compare(0, N - 1, needle) == 0;
     243             : }
     244             : 
     245             : bool
     246           0 : ShaderValidator::CanLinkTo(const ShaderValidator* prev, nsCString* const out_log) const
     247             : {
     248           0 :     if (!prev) {
     249           0 :         nsPrintfCString error("Passed in NULL prev ShaderValidator.");
     250           0 :         *out_log = error;
     251           0 :         return false;
     252             :     }
     253             : 
     254           0 :     const auto shaderVersion = ShGetShaderVersion(mHandle);
     255           0 :     if (ShGetShaderVersion(prev->mHandle) != shaderVersion) {
     256             :         nsPrintfCString error("Vertex shader version %d does not match"
     257             :                               " fragment shader version %d.",
     258           0 :                               ShGetShaderVersion(prev->mHandle),
     259           0 :                               ShGetShaderVersion(mHandle));
     260           0 :         *out_log = error;
     261           0 :         return false;
     262             :     }
     263             : 
     264             :     {
     265           0 :         const std::vector<sh::Uniform>* vertPtr = ShGetUniforms(prev->mHandle);
     266           0 :         const std::vector<sh::Uniform>* fragPtr = ShGetUniforms(mHandle);
     267           0 :         if (!vertPtr || !fragPtr) {
     268           0 :             nsPrintfCString error("Could not create uniform list.");
     269           0 :             *out_log = error;
     270           0 :             return false;
     271             :         }
     272             : 
     273           0 :         for (auto itrFrag = fragPtr->begin(); itrFrag != fragPtr->end(); ++itrFrag) {
     274           0 :             for (auto itrVert = vertPtr->begin(); itrVert != vertPtr->end(); ++itrVert) {
     275           0 :                 if (itrVert->name != itrFrag->name)
     276           0 :                     continue;
     277             : 
     278           0 :                 if (!itrVert->isSameUniformAtLinkTime(*itrFrag)) {
     279             :                     nsPrintfCString error("Uniform `%s` is not linkable between"
     280             :                                           " attached shaders.",
     281           0 :                                           itrFrag->name.c_str());
     282           0 :                     *out_log = error;
     283           0 :                     return false;
     284             :                 }
     285             : 
     286           0 :                 break;
     287             :             }
     288             :         }
     289             :     }
     290             :     {
     291           0 :         const auto vertVars = sh::GetInterfaceBlocks(prev->mHandle);
     292           0 :         const auto fragVars = sh::GetInterfaceBlocks(mHandle);
     293           0 :         if (!vertVars || !fragVars) {
     294           0 :             nsPrintfCString error("Could not create uniform block list.");
     295           0 :             *out_log = error;
     296           0 :             return false;
     297             :         }
     298             : 
     299           0 :         for (const auto& fragVar : *fragVars) {
     300           0 :             for (const auto& vertVar : *vertVars) {
     301           0 :                 if (vertVar.name != fragVar.name)
     302           0 :                     continue;
     303             : 
     304           0 :                 if (!vertVar.isSameInterfaceBlockAtLinkTime(fragVar)) {
     305             :                     nsPrintfCString error("Interface block `%s` is not linkable between"
     306             :                                           " attached shaders.",
     307           0 :                                           fragVar.name.c_str());
     308           0 :                     *out_log = error;
     309           0 :                     return false;
     310             :                 }
     311             : 
     312           0 :                 break;
     313             :             }
     314             :         }
     315             :     }
     316             : 
     317           0 :     const auto& vertVaryings = ShGetVaryings(prev->mHandle);
     318           0 :     const auto& fragVaryings = ShGetVaryings(mHandle);
     319           0 :     if (!vertVaryings || !fragVaryings) {
     320           0 :         nsPrintfCString error("Could not create varying list.");
     321           0 :         *out_log = error;
     322           0 :         return false;
     323             :     }
     324             : 
     325             :     {
     326           0 :         std::vector<sh::ShaderVariable> staticUseVaryingList;
     327             : 
     328           0 :         for (const auto& fragVarying : *fragVaryings) {
     329             :             static const char prefix[] = "gl_";
     330           0 :             if (StartsWith(fragVarying.name, prefix)) {
     331           0 :                 if (fragVarying.staticUse) {
     332           0 :                     staticUseVaryingList.push_back(fragVarying);
     333             :                 }
     334           0 :                 continue;
     335             :             }
     336             : 
     337           0 :             bool definedInVertShader = false;
     338           0 :             bool staticVertUse = false;
     339             : 
     340           0 :             for (const auto& vertVarying : *vertVaryings) {
     341           0 :                 if (vertVarying.name != fragVarying.name)
     342           0 :                     continue;
     343             : 
     344           0 :                 if (!vertVarying.isSameVaryingAtLinkTime(fragVarying, shaderVersion)) {
     345             :                     nsPrintfCString error("Varying `%s`is not linkable between"
     346             :                                           " attached shaders.",
     347           0 :                                           fragVarying.name.c_str());
     348           0 :                     *out_log = error;
     349           0 :                     return false;
     350             :                 }
     351             : 
     352           0 :                 definedInVertShader = true;
     353           0 :                 staticVertUse = vertVarying.staticUse;
     354           0 :                 break;
     355             :             }
     356             : 
     357           0 :             if (!definedInVertShader && fragVarying.staticUse) {
     358             :                 nsPrintfCString error("Varying `%s` has static-use in the frag"
     359             :                                       " shader, but is undeclared in the vert"
     360           0 :                                       " shader.", fragVarying.name.c_str());
     361           0 :                 *out_log = error;
     362           0 :                 return false;
     363             :             }
     364             : 
     365           0 :             if (staticVertUse && fragVarying.staticUse) {
     366           0 :                 staticUseVaryingList.push_back(fragVarying);
     367             :             }
     368             :         }
     369             : 
     370           0 :         if (!ShCheckVariablesWithinPackingLimits(mMaxVaryingVectors,
     371             :                                                  staticUseVaryingList))
     372             :         {
     373             :             *out_log = "Statically used varyings do not fit within packing limits. (see"
     374           0 :                        " GLSL ES Specification 1.0.17, p111)";
     375           0 :             return false;
     376             :         }
     377             :     }
     378             : 
     379           0 :     if (shaderVersion == 100) {
     380             :         // Enforce ESSL1 invariant linking rules.
     381           0 :         bool isInvariant_Position = false;
     382           0 :         bool isInvariant_PointSize = false;
     383           0 :         bool isInvariant_FragCoord = false;
     384           0 :         bool isInvariant_PointCoord = false;
     385             : 
     386           0 :         for (const auto& varying : *vertVaryings) {
     387           0 :             if (varying.name == "gl_Position") {
     388           0 :                 isInvariant_Position = varying.isInvariant;
     389           0 :             } else if (varying.name == "gl_PointSize") {
     390           0 :                 isInvariant_PointSize = varying.isInvariant;
     391             :             }
     392             :         }
     393             : 
     394           0 :         for (const auto& varying : *fragVaryings) {
     395           0 :             if (varying.name == "gl_FragCoord") {
     396           0 :                 isInvariant_FragCoord = varying.isInvariant;
     397           0 :             } else if (varying.name == "gl_PointCoord") {
     398           0 :                 isInvariant_PointCoord = varying.isInvariant;
     399             :             }
     400             :         }
     401             : 
     402             :         ////
     403             : 
     404           0 :         const auto fnCanBuiltInsLink = [](bool vertIsInvariant, bool fragIsInvariant) {
     405           0 :             if (vertIsInvariant)
     406           0 :                 return true;
     407             : 
     408           0 :             return !fragIsInvariant;
     409             :         };
     410             : 
     411           0 :         if (!fnCanBuiltInsLink(isInvariant_Position, isInvariant_FragCoord)) {
     412             :             *out_log = "gl_Position must be invariant if gl_FragCoord is. (see GLSL ES"
     413           0 :                        " Specification 1.0.17, p39)";
     414           0 :             return false;
     415             :         }
     416             : 
     417           0 :         if (!fnCanBuiltInsLink(isInvariant_PointSize, isInvariant_PointCoord)) {
     418             :             *out_log = "gl_PointSize must be invariant if gl_PointCoord is. (see GLSL ES"
     419           0 :                        " Specification 1.0.17, p39)";
     420           0 :             return false;
     421             :         }
     422             :     }
     423             : 
     424           0 :     return true;
     425             : }
     426             : 
     427             : size_t
     428           0 : ShaderValidator::CalcNumSamplerUniforms() const
     429             : {
     430           0 :     size_t accum = 0;
     431             : 
     432           0 :     const std::vector<sh::Uniform>& uniforms = *ShGetUniforms(mHandle);
     433             : 
     434           0 :     for (auto itr = uniforms.begin(); itr != uniforms.end(); ++itr) {
     435           0 :         GLenum type = itr->type;
     436           0 :         if (type == LOCAL_GL_SAMPLER_2D ||
     437             :             type == LOCAL_GL_SAMPLER_CUBE)
     438             :         {
     439           0 :             accum += itr->arraySize;
     440             :         }
     441             :     }
     442             : 
     443           0 :     return accum;
     444             : }
     445             : 
     446             : size_t
     447           0 : ShaderValidator::NumAttributes() const
     448             : {
     449           0 :   return ShGetAttributes(mHandle)->size();
     450             : }
     451             : 
     452             : // Attribs cannot be structs or arrays, and neither can vertex inputs in ES3.
     453             : // Therefore, attrib names are always simple.
     454             : bool
     455           0 : ShaderValidator::FindAttribUserNameByMappedName(const std::string& mappedName,
     456             :                                                 const std::string** const out_userName) const
     457             : {
     458           0 :     const std::vector<sh::Attribute>& attribs = *ShGetAttributes(mHandle);
     459           0 :     for (auto itr = attribs.begin(); itr != attribs.end(); ++itr) {
     460           0 :         if (itr->mappedName == mappedName) {
     461           0 :             *out_userName = &(itr->name);
     462           0 :             return true;
     463             :         }
     464             :     }
     465             : 
     466           0 :     return false;
     467             : }
     468             : 
     469             : bool
     470           0 : ShaderValidator::FindAttribMappedNameByUserName(const std::string& userName,
     471             :                                                 const std::string** const out_mappedName) const
     472             : {
     473           0 :     const std::vector<sh::Attribute>& attribs = *ShGetAttributes(mHandle);
     474           0 :     for (auto itr = attribs.begin(); itr != attribs.end(); ++itr) {
     475           0 :         if (itr->name == userName) {
     476           0 :             *out_mappedName = &(itr->mappedName);
     477           0 :             return true;
     478             :         }
     479             :     }
     480             : 
     481           0 :     return false;
     482             : }
     483             : 
     484             : bool
     485           0 : ShaderValidator::FindVaryingByMappedName(const std::string& mappedName,
     486             :                                          std::string* const out_userName,
     487             :                                          bool* const out_isArray) const
     488             : {
     489           0 :     const std::vector<sh::Varying>& varyings = *ShGetVaryings(mHandle);
     490           0 :     for (auto itr = varyings.begin(); itr != varyings.end(); ++itr) {
     491             :         const sh::ShaderVariable* found;
     492           0 :         if (!itr->findInfoByMappedName(mappedName, &found, out_userName))
     493           0 :             continue;
     494             : 
     495           0 :         *out_isArray = found->isArray();
     496           0 :         return true;
     497             :     }
     498             : 
     499           0 :     return false;
     500             : }
     501             : 
     502             : bool
     503           0 : ShaderValidator::FindVaryingMappedNameByUserName(const std::string& userName,
     504             :                                                  const std::string** const out_mappedName) const
     505             : {
     506           0 :     const std::vector<sh::Varying>& attribs = *ShGetVaryings(mHandle);
     507           0 :     for (auto itr = attribs.begin(); itr != attribs.end(); ++itr) {
     508           0 :         if (itr->name == userName) {
     509           0 :             *out_mappedName = &(itr->mappedName);
     510           0 :             return true;
     511             :         }
     512             :     }
     513             : 
     514           0 :     return false;
     515             : }
     516             : // This must handle names like "foo.bar[0]".
     517             : bool
     518           0 : ShaderValidator::FindUniformByMappedName(const std::string& mappedName,
     519             :                                          std::string* const out_userName,
     520             :                                          bool* const out_isArray) const
     521             : {
     522           0 :     const std::vector<sh::Uniform>& uniforms = *ShGetUniforms(mHandle);
     523           0 :     for (auto itr = uniforms.begin(); itr != uniforms.end(); ++itr) {
     524             :         const sh::ShaderVariable* found;
     525           0 :         if (!itr->findInfoByMappedName(mappedName, &found, out_userName))
     526           0 :             continue;
     527             : 
     528           0 :         *out_isArray = found->isArray();
     529           0 :         return true;
     530             :     }
     531             : 
     532           0 :     const size_t dotPos = mappedName.find(".");
     533             : 
     534           0 :     const std::vector<sh::InterfaceBlock>& interfaces = *ShGetInterfaceBlocks(mHandle);
     535           0 :     for (const auto& interface : interfaces) {
     536             : 
     537           0 :         std::string mappedFieldName;
     538           0 :         const bool hasInstanceName = !interface.instanceName.empty();
     539             : 
     540             :         // If the InterfaceBlock has an instanceName, all variables defined
     541             :         // within the block are qualified with the block name, as opposed
     542             :         // to being placed in the global scope.
     543           0 :         if (hasInstanceName) {
     544             : 
     545             :             // If mappedName has no block name prefix, skip
     546           0 :             if (std::string::npos == dotPos)
     547           0 :                 continue;
     548             : 
     549             :             // If mappedName has a block name prefix that doesn't match, skip
     550           0 :             const std::string mappedInterfaceBlockName = mappedName.substr(0, dotPos);
     551           0 :             if (interface.mappedName != mappedInterfaceBlockName)
     552           0 :                 continue;
     553             : 
     554           0 :             mappedFieldName = mappedName.substr(dotPos + 1);
     555             :         } else {
     556           0 :             mappedFieldName = mappedName;
     557             :         }
     558             : 
     559           0 :         for (const auto& field : interface.fields) {
     560             :             const sh::ShaderVariable* found;
     561             : 
     562           0 :             if (!field.findInfoByMappedName(mappedFieldName, &found, out_userName))
     563           0 :                 continue;
     564             : 
     565           0 :             if (hasInstanceName) {
     566             :                 // Prepend the user name of the interface that matched
     567           0 :                 *out_userName = interface.name + "." + *out_userName;
     568             :             }
     569             : 
     570           0 :             *out_isArray = found->isArray();
     571           0 :             return true;
     572             :         }
     573             :     }
     574             : 
     575           0 :     return false;
     576             : }
     577             : 
     578             : bool
     579           0 : ShaderValidator::UnmapUniformBlockName(const nsACString& baseMappedName,
     580             :                                        nsCString* const out_baseUserName) const
     581             : {
     582           0 :     const std::vector<sh::InterfaceBlock>& interfaces = *ShGetInterfaceBlocks(mHandle);
     583           0 :     for (const auto& interface : interfaces) {
     584             :         const nsDependentCString interfaceMappedName(interface.mappedName.data(),
     585           0 :                                                      interface.mappedName.size());
     586           0 :         if (baseMappedName == interfaceMappedName) {
     587           0 :             *out_baseUserName = interface.name.data();
     588           0 :             return true;
     589             :         }
     590             :     }
     591             : 
     592           0 :     return false;
     593             : }
     594             : 
     595             : void
     596           0 : ShaderValidator::EnumerateFragOutputs(std::map<nsCString, const nsCString> &out_FragOutputs) const
     597             : {
     598           0 :     const auto* fragOutputs = ShGetOutputVariables(mHandle);
     599             : 
     600           0 :     if (fragOutputs) {
     601           0 :         for (const auto& fragOutput : *fragOutputs) {
     602           0 :             out_FragOutputs.insert({nsCString(fragOutput.name.c_str()),
     603           0 :                                     nsCString(fragOutput.mappedName.c_str())});
     604             :         }
     605             :     }
     606           0 : }
     607             : 
     608             : } // namespace webgl
     609             : } // namespace mozilla

Generated by: LCOV version 1.13