Bug 1325699 (flattened) - Fix uniform block handling. - r=daoshengmu
authorJeff Gilbert <jgilbert@mozilla.com>
Fri, 23 Dec 2016 13:29:07 -0800
changeset 327492 c274a7c25dc7e3a9228b3b9a5c1917e985ff4192
parent 327491 c0eb5a38f7168f4731c3e796d5f25d9788e9d87a
child 327493 0b58022dda33469d7d7cb652ec31407e7fa6b8a8
push id85205
push userjgilbert@mozilla.com
push dateThu, 29 Dec 2016 10:47:30 +0000
treeherdermozilla-inbound@c274a7c25dc7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdaoshengmu
bugs1325699
milestone53.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1325699 (flattened) - Fix uniform block handling. - r=daoshengmu Flattened with: * Handle -1 attrib locations. - r=daoshengmu
dom/canvas/WebGLContextDraw.cpp
dom/canvas/WebGLProgram.cpp
dom/canvas/WebGLProgram.h
dom/canvas/WebGLShader.cpp
dom/canvas/WebGLShader.h
dom/canvas/WebGLShaderValidator.cpp
dom/canvas/WebGLShaderValidator.h
--- a/dom/canvas/WebGLContextDraw.cpp
+++ b/dom/canvas/WebGLContextDraw.cpp
@@ -391,16 +391,18 @@ public:
                 return;
             }
         }
 
         ////
 
         for (const auto& progAttrib : mWebGL->mActiveProgramLinkInfo->attribs) {
             const auto& loc = progAttrib.mLoc;
+            if (loc == -1)
+                continue;
 
             const auto& attribData = mWebGL->mBoundVertexArray->mAttribs[loc];
 
             GLenum attribDataBaseType;
             if (attribData.mEnabled) {
                 attribDataBaseType = attribData.BaseType();
             } else {
                 attribDataBaseType = mWebGL->mGenericVertexAttribTypes[loc];
@@ -926,18 +928,20 @@ WebGLContext::ValidateBufferFetching(con
         }
 
         ++i;
     }
 
     mBufferFetch_IsAttrib0Active = false;
 
     for (const auto& attrib : mActiveProgramLinkInfo->attribs) {
-        const auto& attribLoc = attrib.mLoc;
+        if (attrib.mLoc == -1)
+            continue;
 
+        const uint32_t attribLoc(attrib.mLoc);
         if (attribLoc >= attribCount)
             continue;
 
         if (attribLoc == 0) {
             mBufferFetch_IsAttrib0Active = true;
         }
 
         const auto& vd = mBoundVertexArray->mAttribs[attribLoc];
--- a/dom/canvas/WebGLProgram.cpp
+++ b/dom/canvas/WebGLProgram.cpp
@@ -167,17 +167,17 @@ webgl::UniformInfo::UniformInfo(WebGLAct
 {
     if (mSamplerTexList) {
         mSamplerValues.assign(mActiveInfo->mElemCount, 0);
     }
 }
 
 //////////
 
-//#define DUMP_SHADERVAR_MAPPINGS
+#define DUMP_SHADERVAR_MAPPINGS
 
 static already_AddRefed<const webgl::LinkedProgramInfo>
 QueryProgramInfo(WebGLProgram* prog, gl::GLContext* gl)
 {
     WebGLContext* const webgl = prog->mContext;
 
     RefPtr<webgl::LinkedProgramInfo> info(new webgl::LinkedProgramInfo(prog));
 
@@ -204,24 +204,17 @@ QueryProgramInfo(WebGLProgram* prog, gl:
     GLuint maxTransformFeedbackVaryingLenWithNull = 0;
     if (gl->IsSupported(gl::GLFeature::transform_feedback2)) {
         gl->fGetProgramiv(prog->mGLName, LOCAL_GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH,
                           (GLint*)&maxTransformFeedbackVaryingLenWithNull);
         if (maxTransformFeedbackVaryingLenWithNull < 1)
             maxTransformFeedbackVaryingLenWithNull = 1;
     }
 
-
-#ifdef DUMP_SHADERVAR_MAPPINGS
-    printf_stderr("maxAttribLenWithNull: %d\n", maxAttribLenWithNull);
-    printf_stderr("maxUniformLenWithNull: %d\n", maxUniformLenWithNull);
-    printf_stderr("maxUniformBlockLenWithNull: %d\n", maxUniformBlockLenWithNull);
-#endif
-
-    // Attribs
+    // Attribs (can't be arrays)
 
     GLuint numActiveAttribs = 0;
     gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_ATTRIBUTES,
                       (GLint*)&numActiveAttribs);
 
     for (GLuint i = 0; i < numActiveAttribs; i++) {
         nsAutoCString mappedName;
         mappedName.SetLength(maxAttribLenWithNull - 1);
@@ -233,51 +226,45 @@ QueryProgramInfo(WebGLProgram* prog, gl:
                              &elemCount, &elemType, mappedName.BeginWriting());
         GLenum error = gl->fGetError();
         if (error != LOCAL_GL_NO_ERROR) {
             gfxCriticalNote << "Failed to do glGetActiveAttrib: " << error;
         }
 
         mappedName.SetLength(lengthWithoutNull);
 
-        // Attribs can't be arrays, so we can skip some of the mess we have in the Uniform
-        // path.
-        nsDependentCString userName;
-        if (!prog->FindAttribUserNameByMappedName(mappedName, &userName))
-            userName.Rebind(mappedName, 0);
+        ////
+
+        nsCString userName;
+        if (!prog->FindAttribUserNameByMappedName(mappedName, &userName)) {
+            userName = mappedName;
+        }
 
         ///////
 
         const GLint loc = gl->fGetAttribLocation(prog->mGLName,
                                                  mappedName.BeginReading());
-        if (loc == -1) {
-            MOZ_ASSERT(mappedName == "gl_InstanceID",
-                       "Active attrib should have a location.");
-            continue;
-        }
-
 #ifdef DUMP_SHADERVAR_MAPPINGS
-        printf_stderr("[attrib %i: %i] %s/%s\n", i, loc, mappedName.BeginReading(),
-                      userName.BeginReading());
-        printf_stderr("    lengthWithoutNull: %d\n", lengthWithoutNull);
+        printf_stderr("[attrib %u/%u] @%i %s->%s\n", i, numActiveAttribs, loc,
+                      userName.BeginReading(), mappedName.BeginReading());
 #endif
 
         ///////
 
         const bool isArray = false;
         const RefPtr<WebGLActiveInfo> activeInfo = new WebGLActiveInfo(webgl, elemCount,
                                                                        elemType, isArray,
                                                                        userName,
                                                                        mappedName);
         const GLenum baseType = AttribBaseType(elemType);
-        const webgl::AttribInfo attrib = {activeInfo, uint32_t(loc), baseType};
+        const webgl::AttribInfo attrib = {activeInfo, loc, baseType};
         info->attribs.push_back(attrib);
     }
 
-    // Uniforms
+    // Uniforms (can be basically anything)
 
     const bool needsCheckForArrays = gl->WorkAroundDriverBugs();
 
     GLuint numActiveUniforms = 0;
     gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_UNIFORMS,
                       (GLint*)&numActiveUniforms);
 
     for (GLuint i = 0; i < numActiveUniforms; i++) {
@@ -321,21 +308,18 @@ QueryProgramInfo(WebGLProgram* prog, gl:
                 if (loc != -1)
                     isArray = true;
             }
         }
 
         ///////
 
 #ifdef DUMP_SHADERVAR_MAPPINGS
-        printf_stderr("[uniform %i] %s/%i/%s/%s\n", i, mappedName.BeginReading(),
-                      (int)isArray, baseMappedName.BeginReading(),
-                      baseUserName.BeginReading());
-        printf_stderr("    lengthWithoutNull: %d\n", lengthWithoutNull);
-        printf_stderr("    isArray: %d\n", (int)isArray);
+        printf_stderr("[uniform %u/%u] %s->%s\n", i, numActiveUniforms,
+                      baseUserName.BeginReading(), mappedName.BeginReading());
 #endif
 
         ///////
 
         const RefPtr<WebGLActiveInfo> activeInfo = new WebGLActiveInfo(webgl, elemCount,
                                                                        elemType, isArray,
                                                                        baseUserName,
                                                                        baseMappedName);
@@ -343,78 +327,58 @@ QueryProgramInfo(WebGLProgram* prog, gl:
         auto* uniform = new webgl::UniformInfo(activeInfo);
         info->uniforms.push_back(uniform);
 
         if (uniform->mSamplerTexList) {
             info->uniformSamplers.push_back(uniform);
         }
     }
 
-    // Uniform Blocks
-    // (no sampler types allowed!)
+    // Uniform Blocks (can be arrays, but can't contain sampler types)
 
     if (gl->IsSupported(gl::GLFeature::uniform_buffer_object)) {
         GLuint numActiveUniformBlocks = 0;
         gl->fGetProgramiv(prog->mGLName, LOCAL_GL_ACTIVE_UNIFORM_BLOCKS,
                           (GLint*)&numActiveUniformBlocks);
 
         for (GLuint i = 0; i < numActiveUniformBlocks; i++) {
             nsAutoCString mappedName;
             mappedName.SetLength(maxUniformBlockLenWithNull - 1);
 
             GLint lengthWithoutNull;
             gl->fGetActiveUniformBlockiv(prog->mGLName, i, LOCAL_GL_UNIFORM_BLOCK_NAME_LENGTH, &lengthWithoutNull);
             gl->fGetActiveUniformBlockName(prog->mGLName, i, maxUniformBlockLenWithNull, &lengthWithoutNull, mappedName.BeginWriting());
             mappedName.SetLength(lengthWithoutNull);
 
-            nsAutoCString baseMappedName;
-            bool isArray;
-            size_t arrayIndex;
-            if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex))
-                MOZ_CRASH("GFX: Failed to parse `mappedName` received from driver.");
+            ////
 
-            nsAutoCString baseUserName;
-            if (!prog->FindUniformBlockByMappedName(baseMappedName, &baseUserName,
-                                                    &isArray))
-            {
-                baseUserName = baseMappedName;
+            nsCString userName;
+            if (!prog->UnmapUniformBlockName(mappedName, &userName))
+                continue;
 
-                if (needsCheckForArrays && !isArray) {
-                    std::string mappedNameStr = baseMappedName.BeginReading();
-                    mappedNameStr += "[0]";
-
-                    GLuint loc = gl->fGetUniformBlockIndex(prog->mGLName,
-                                                           mappedNameStr.c_str());
-                    if (loc != LOCAL_GL_INVALID_INDEX)
-                        isArray = true;
-                }
-            }
+#ifdef DUMP_SHADERVAR_MAPPINGS
+            printf_stderr("[uniform block %u/%u] %s->%s\n", i, numActiveUniformBlocks,
+                          userName.BeginReading(), mappedName.BeginReading());
+#endif
 
             ////
 
             GLuint dataSize = 0;
             gl->fGetActiveUniformBlockiv(prog->mGLName, i,
                                          LOCAL_GL_UNIFORM_BLOCK_DATA_SIZE,
                                          (GLint*)&dataSize);
 
-#ifdef DUMP_SHADERVAR_MAPPINGS
-            printf_stderr("[uniform block %i] %s/%i/%s/%s\n", i,
-                          mappedName.BeginReading(), (int)isArray,
-                          baseMappedName.BeginReading(), baseUserName.BeginReading());
-            printf_stderr("    lengthWithoutNull: %d\n", lengthWithoutNull);
-            printf_stderr("    isArray: %d\n", (int)isArray);
-#endif
 
-            auto* block = new webgl::UniformBlockInfo(webgl, baseUserName, baseMappedName,
+            auto* block = new webgl::UniformBlockInfo(webgl, userName, mappedName,
                                                       dataSize);
             info->uniformBlocks.push_back(block);
         }
     }
 
-    // Transform feedback varyings
+    // Transform feedback varyings (can be arrays)
 
     if (gl->IsSupported(gl::GLFeature::transform_feedback2)) {
         GLuint numTransformFeedbackVaryings = 0;
         gl->fGetProgramiv(prog->mGLName, LOCAL_GL_TRANSFORM_FEEDBACK_VARYINGS,
                           (GLint*)&numTransformFeedbackVaryings);
 
         for (GLuint i = 0; i < numTransformFeedbackVaryings; i++) {
             nsAutoCString mappedName;
@@ -432,34 +396,29 @@ QueryProgramInfo(WebGLProgram* prog, gl:
             ////
 
             nsAutoCString baseMappedName;
             bool isArray;
             size_t arrayIndex;
             if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex))
                 MOZ_CRASH("GFX: Failed to parse `mappedName` received from driver.");
 
-
             nsAutoCString baseUserName;
             if (!prog->FindVaryingByMappedName(mappedName, &baseUserName, &isArray)) {
                 baseUserName = baseMappedName;
-
-                if (needsCheckForArrays && !isArray) {
-                    std::string mappedNameStr = baseMappedName.BeginReading();
-                    mappedNameStr += "[0]";
-
-                    GLuint loc = gl->fGetUniformBlockIndex(prog->mGLName,
-                                                           mappedNameStr.c_str());
-                    if (loc != LOCAL_GL_INVALID_INDEX)
-                        isArray = true;
-                }
             }
 
             ////
 
+#ifdef DUMP_SHADERVAR_MAPPINGS
+            printf_stderr("[transform feedback varying %u/%u] %s->%s\n", i,
+                          numTransformFeedbackVaryings, baseUserName.BeginReading(),
+                          mappedName.BeginReading());
+#endif
+
             const RefPtr<WebGLActiveInfo> activeInfo = new WebGLActiveInfo(webgl,
                                                                            elemCount,
                                                                            elemType,
                                                                            isArray,
                                                                            baseUserName,
                                                                            mappedName);
             info->transformFeedbackVaryings.push_back(activeInfo);
         }
@@ -783,23 +742,30 @@ WebGLProgram::GetUniformBlockIndex(const
 
     if (!IsLinked()) {
         mContext->ErrorInvalidOperation("getUniformBlockIndex: `program` must be linked.");
         return LOCAL_GL_INVALID_INDEX;
     }
 
     const NS_LossyConvertUTF16toASCII userName(userName_wide);
 
-    nsCString mappedName;
-    if (!LinkInfo()->MapUniformBlockName(userName, &mappedName))
+    const webgl::UniformBlockInfo* info = nullptr;
+    for (const auto& cur : LinkInfo()->uniformBlocks) {
+        if (cur->mUserName == userName) {
+            info = cur;
+            break;
+        }
+    }
+    if (!info)
         return LOCAL_GL_INVALID_INDEX;
 
+    const auto& mappedName = info->mMappedName;
+
     gl::GLContext* gl = mContext->GL();
     gl->MakeCurrent();
-
     return gl->fGetUniformBlockIndex(mGLName, mappedName.BeginReading());
 }
 
 void
 WebGLProgram::GetActiveUniformBlockName(GLuint uniformBlockIndex, nsAString& retval) const
 {
     if (!IsLinked()) {
         mContext->ErrorInvalidOperation("getActiveUniformBlockName: `program` must be linked.");
@@ -808,19 +774,18 @@ WebGLProgram::GetActiveUniformBlockName(
 
     const webgl::LinkedProgramInfo* linkInfo = LinkInfo();
     GLuint uniformBlockCount = (GLuint) linkInfo->uniformBlocks.size();
     if (uniformBlockIndex >= uniformBlockCount) {
         mContext->ErrorInvalidValue("getActiveUniformBlockName: index %u invalid.", uniformBlockIndex);
         return;
     }
 
-    const webgl::UniformBlockInfo* blockInfo = linkInfo->uniformBlocks[uniformBlockIndex];
-
-    retval.Assign(NS_ConvertASCIItoUTF16(blockInfo->mBaseUserName));
+    const auto& blockInfo = linkInfo->uniformBlocks[uniformBlockIndex];
+    retval.Assign(NS_ConvertASCIItoUTF16(blockInfo->mUserName));
 }
 
 JS::Value
 WebGLProgram::GetActiveUniformBlockParam(GLuint uniformBlockIndex, GLenum pname) const
 {
     if (!IsLinked()) {
         mContext->ErrorInvalidOperation("getActiveUniformBlockParameter: `program` must be linked.");
         return JS::NullValue();
@@ -1215,16 +1180,19 @@ WebGLProgram::ValidateAfterTentativeLink
                                                attribName.BeginReading());
                 return false;
             }
         }
     }
 
     std::map<uint32_t, const webgl::AttribInfo*> attribsByLoc;
     for (const auto& attrib : linkInfo->attribs) {
+        if (attrib.mLoc == -1)
+            continue;
+
         const auto& elemType = attrib.mActiveInfo->mElemType;
         const auto numUsedLocs = NumUsedLocationsByElemType(elemType);
         for (uint32_t i = 0; i < numUsedLocs; i++) {
             const uint32_t usedLoc = attrib.mLoc + i;
 
             const auto res = attribsByLoc.insert({usedLoc, &attrib});
             const bool& didInsert = res.second;
             if (!didInsert) {
@@ -1399,17 +1367,17 @@ WebGLProgram::LinkAndUpdate()
         return;
 
     mMostRecentLinkInfo = QueryProgramInfo(this, gl);
     MOZ_RELEASE_ASSERT(mMostRecentLinkInfo, "GFX: most recent link info not set.");
 }
 
 bool
 WebGLProgram::FindAttribUserNameByMappedName(const nsACString& mappedName,
-                                             nsDependentCString* const out_userName) const
+                                             nsCString* const out_userName) const
 {
     if (mVertShader->FindAttribUserNameByMappedName(mappedName, out_userName))
         return true;
 
     return false;
 }
 
 bool
@@ -1494,27 +1462,34 @@ WebGLProgram::GetTransformFeedbackVaryin
         return nullptr;
     }
 
     RefPtr<WebGLActiveInfo> ret = LinkInfo()->transformFeedbackVaryings[index];
     return ret.forget();
 }
 
 bool
-WebGLProgram::FindUniformBlockByMappedName(const nsACString& mappedName,
-                                           nsCString* const out_userName,
-                                           bool* const out_isArray) const
+WebGLProgram::UnmapUniformBlockName(const nsCString& mappedName,
+                                    nsCString* const out_userName) const
 {
-    if (mVertShader->FindUniformBlockByMappedName(mappedName, out_userName, out_isArray))
-        return true;
+    nsCString baseMappedName;
+    bool isArray;
+    size_t arrayIndex;
+    if (!ParseName(mappedName, &baseMappedName, &isArray, &arrayIndex))
+        return false;
 
-    if (mFragShader->FindUniformBlockByMappedName(mappedName, out_userName, out_isArray))
-        return true;
+    nsCString baseUserName;
+    if (!mVertShader->UnmapUniformBlockName(baseMappedName, &baseUserName) &&
+        !mFragShader->UnmapUniformBlockName(baseMappedName, &baseUserName))
+    {
+        return false;
+    }
 
-    return false;
+    AssembleName(baseUserName, isArray, arrayIndex, out_userName);
+    return true;
 }
 
 void
 WebGLProgram::EnumerateFragOutputs(std::map<nsCString, const nsCString> &out_FragOutputs) const
 {
     MOZ_ASSERT(mFragShader);
 
     mFragShader->EnumerateFragOutputs(out_FragOutputs);
@@ -1573,41 +1548,16 @@ webgl::LinkedProgramInfo::FindUniform(co
     AssembleName(baseMappedName, isArray, arrayIndex, out_mappedName);
 
     *out_arrayIndex = arrayIndex;
     *out_info = info;
     return true;
 }
 
 bool
-webgl::LinkedProgramInfo::MapUniformBlockName(const nsCString& userName,
-                                              nsCString* const out_mappedName) const
-{
-    nsCString baseUserName;
-    bool isArray;
-    size_t arrayIndex;
-    if (!ParseName(userName, &baseUserName, &isArray, &arrayIndex))
-        return false;
-
-    const webgl::UniformBlockInfo* info = nullptr;
-    for (const auto& block : uniformBlocks) {
-        if (block->mBaseUserName == baseUserName) {
-            info = block;
-            break;
-        }
-    }
-    if (!info)
-        return false;
-
-    const auto& baseMappedName = info->mBaseMappedName;
-    AssembleName(baseMappedName, isArray, arrayIndex, out_mappedName);
-    return true;
-}
-
-bool
 webgl::LinkedProgramInfo::MapFragDataName(const nsCString& userName,
                                           nsCString* const out_mappedName) const
 {
     // FS outputs can be arrays, but not structures.
 
     if (!fragDataMap.size()) {
         // No mappings map from validation, so just forward it.
         *out_mappedName = userName;
--- a/dom/canvas/WebGLProgram.h
+++ b/dom/canvas/WebGLProgram.h
@@ -33,17 +33,17 @@ class OwningUnsignedLongOrUint32ArrayOrB
 template<typename> class Sequence;
 } // namespace dom
 
 namespace webgl {
 
 struct AttribInfo final
 {
     const RefPtr<WebGLActiveInfo> mActiveInfo;
-    const uint32_t mLoc;
+    const GLint mLoc; // -1 for active built-ins
     const GLenum mBaseType;
 };
 
 struct UniformInfo final
 {
     typedef decltype(WebGLContext::mBound2DTextures) TexListT;
 
     const RefPtr<WebGLActiveInfo> mActiveInfo;
@@ -55,26 +55,26 @@ protected:
     GetTexList(WebGLActiveInfo* activeInfo);
 
 public:
     explicit UniformInfo(WebGLActiveInfo* activeInfo);
 };
 
 struct UniformBlockInfo final
 {
-    const nsCString mBaseUserName;
-    const nsCString mBaseMappedName;
+    const nsCString mUserName;
+    const nsCString mMappedName;
     const uint32_t mDataSize;
 
     const IndexedBufferBinding* mBinding;
 
-    UniformBlockInfo(WebGLContext* webgl, const nsACString& baseUserName,
-                     const nsACString& baseMappedName, uint32_t dataSize)
-        : mBaseUserName(baseUserName)
-        , mBaseMappedName(baseMappedName)
+    UniformBlockInfo(WebGLContext* webgl, const nsACString& userName,
+                     const nsACString& mappedName, uint32_t dataSize)
+        : mUserName(userName)
+        , mMappedName(mappedName)
         , mDataSize(dataSize)
         , mBinding(&webgl->mIndexedUniformBufferBindings[0])
     { }
 };
 
 struct LinkedProgramInfo final
     : public RefCounted<LinkedProgramInfo>
     , public SupportsWeakPtr<LinkedProgramInfo>
@@ -104,18 +104,16 @@ struct LinkedProgramInfo final
     std::map<nsCString, const nsCString> fragDataMap;
 
     explicit LinkedProgramInfo(WebGLProgram* prog);
     ~LinkedProgramInfo();
 
     bool FindAttrib(const nsCString& userName, const AttribInfo** const out_info) const;
     bool FindUniform(const nsCString& userName, nsCString* const out_mappedName,
                      size_t* const out_arrayIndex, UniformInfo** const out_info) const;
-    bool MapUniformBlockName(const nsCString& userName,
-                             nsCString* const out_mappedName) const;
     bool MapFragDataName(const nsCString& userName,
                          nsCString* const out_mappedName) const;
 };
 
 } // namespace webgl
 
 class WebGLProgram final
     : public nsWrapperCache
@@ -156,26 +154,25 @@ public:
 
     void LinkProgram();
     bool UseProgram() const;
     void ValidateProgram() const;
 
     ////////////////
 
     bool FindAttribUserNameByMappedName(const nsACString& mappedName,
-                                        nsDependentCString* const out_userName) const;
+                                        nsCString* const out_userName) const;
     bool FindVaryingByMappedName(const nsACString& mappedName,
                                  nsCString* const out_userName,
                                  bool* const out_isArray) const;
     bool FindUniformByMappedName(const nsACString& mappedName,
                                  nsCString* const out_userName,
                                  bool* const out_isArray) const;
-    bool FindUniformBlockByMappedName(const nsACString& mappedName,
-                                      nsCString* const out_userName,
-                                      bool* const out_isArray) const;
+    bool UnmapUniformBlockName(const nsCString& mappedName,
+                               nsCString* const out_userName) const;
 
     void TransformFeedbackVaryings(const dom::Sequence<nsString>& varyings,
                                    GLenum bufferMode);
     already_AddRefed<WebGLActiveInfo> GetTransformFeedbackVarying(GLuint index) const;
 
     void EnumerateFragOutputs(std::map<nsCString, const nsCString> &out_FragOutputs) const;
 
     bool IsLinked() const { return mMostRecentLinkInfo; }
--- a/dom/canvas/WebGLShader.cpp
+++ b/dom/canvas/WebGLShader.cpp
@@ -326,27 +326,27 @@ WebGLShader::BindAttribLocation(GLuint p
     if (mValidator)
         mValidator->FindAttribMappedNameByUserName(userNameStr, &mappedNameStr);
 
     mContext->gl->fBindAttribLocation(prog, index, mappedNameStr->c_str());
 }
 
 bool
 WebGLShader::FindAttribUserNameByMappedName(const nsACString& mappedName,
-                                            nsDependentCString* const out_userName) const
+                                            nsCString* const out_userName) const
 {
     if (!mValidator)
         return false;
 
     const std::string mappedNameStr(mappedName.BeginReading());
     const std::string* userNameStr;
     if (!mValidator->FindAttribUserNameByMappedName(mappedNameStr, &userNameStr))
         return false;
 
-    out_userName->Rebind(userNameStr->c_str());
+    *out_userName = userNameStr->c_str();
     return true;
 }
 
 bool
 WebGLShader::FindVaryingByMappedName(const nsACString& mappedName,
                                      nsCString* const out_userName,
                                      bool* const out_isArray) const
 {
@@ -375,30 +375,25 @@ WebGLShader::FindUniformByMappedName(con
     if (!mValidator->FindUniformByMappedName(mappedNameStr, &userNameStr, out_isArray))
         return false;
 
     *out_userName = userNameStr.c_str();
     return true;
 }
 
 bool
-WebGLShader::FindUniformBlockByMappedName(const nsACString& mappedName,
-                                          nsCString* const out_userName,
-                                          bool* const out_isArray) const
+WebGLShader::UnmapUniformBlockName(const nsACString& baseMappedName,
+                                   nsCString* const out_baseUserName) const
 {
-    if (!mValidator)
-        return false;
+    if (!mValidator) {
+        *out_baseUserName = baseMappedName;
+        return true;
+    }
 
-    const std::string mappedNameStr(mappedName.BeginReading(), mappedName.Length());
-    std::string userNameStr;
-    if (!mValidator->FindUniformBlockByMappedName(mappedNameStr, &userNameStr))
-        return false;
-
-    *out_userName = userNameStr.c_str();
-    return true;
+    return mValidator->UnmapUniformBlockName(baseMappedName, out_baseUserName);
 }
 
 void
 WebGLShader::EnumerateFragOutputs(std::map<nsCString, const nsCString> &out_FragOutputs) const
 {
     out_FragOutputs.clear();
 
     if (!mValidator) {
--- a/dom/canvas/WebGLShader.h
+++ b/dom/canvas/WebGLShader.h
@@ -47,26 +47,25 @@ public:
     void GetShaderTranslatedSource(nsAString* out) const;
     void ShaderSource(const nsAString& source);
 
     // Util funcs
     bool CanLinkTo(const WebGLShader* prev, nsCString* const out_log) const;
     size_t CalcNumSamplerUniforms() const;
     size_t NumAttributes() const;
     bool FindAttribUserNameByMappedName(const nsACString& mappedName,
-                                        nsDependentCString* const out_userName) const;
+                                        nsCString* const out_userName) const;
     bool FindVaryingByMappedName(const nsACString& mappedName,
                                  nsCString* const out_userName,
                                  bool* const out_isArray) const;
     bool FindUniformByMappedName(const nsACString& mappedName,
                                  nsCString* const out_userName,
                                  bool* const out_isArray) const;
-    bool FindUniformBlockByMappedName(const nsACString& mappedName,
-                                      nsCString* const out_userName,
-                                      bool* const out_isArray) const;
+    bool UnmapUniformBlockName(const nsACString& baseMappedName,
+                               nsCString* const out_baseUserName) const;
 
     void EnumerateFragOutputs(std::map<nsCString, const nsCString> &out_FragOutputs) const;
 
     bool IsCompiled() const {
         return mTranslationSuccessful && mCompilationSuccessful;
     }
 
 private:
--- a/dom/canvas/WebGLShaderValidator.cpp
+++ b/dom/canvas/WebGLShaderValidator.cpp
@@ -540,23 +540,25 @@ ShaderValidator::FindUniformByMappedName
             return true;
         }
     }
 
     return false;
 }
 
 bool
-ShaderValidator::FindUniformBlockByMappedName(const std::string& mappedName,
-                                              std::string* const out_userName) const
+ShaderValidator::UnmapUniformBlockName(const nsACString& baseMappedName,
+                                       nsCString* const out_baseUserName) const
 {
     const std::vector<sh::InterfaceBlock>& interfaces = *ShGetInterfaceBlocks(mHandle);
     for (const auto& interface : interfaces) {
-        if (mappedName == interface.mappedName) {
-            *out_userName = interface.name;
+        const nsDependentCString interfaceMappedName(interface.mappedName.data(),
+                                                     interface.mappedName.size());
+        if (baseMappedName == interfaceMappedName) {
+            *out_baseUserName = interface.name.data();
             return true;
         }
     }
 
     return false;
 }
 
 void
--- a/dom/canvas/WebGLShaderValidator.h
+++ b/dom/canvas/WebGLShaderValidator.h
@@ -56,18 +56,18 @@ public:
                                          const std::string** const out_mappedName) const;
 
     bool FindVaryingByMappedName(const std::string& mappedName,
                                  std::string* const out_userName,
                                  bool* const out_isArray) const;
     bool FindUniformByMappedName(const std::string& mappedName,
                                  std::string* const out_userName,
                                  bool* const out_isArray) const;
-    bool FindUniformBlockByMappedName(const std::string& mappedName,
-                                      std::string* const out_userName) const;
+    bool UnmapUniformBlockName(const nsACString& baseMappedName,
+                               nsCString* const out_baseUserName) const;
 
     void EnumerateFragOutputs(std::map<nsCString, const nsCString> &out_FragOutputs) const;
 
     bool ValidateTransformFeedback(const std::vector<nsString>& userNames,
                                    uint32_t maxComponents, nsCString* const out_errorText,
                                    std::vector<std::string>* const out_mappedNames);
 };