Bug 1325699 (flattened) - Fix uniform block handling. - r=daoshengmu a=lizzard
authorJeff Gilbert <jgilbert@mozilla.com>
Fri, 23 Dec 2016 13:29:07 -0800
changeset 353263 b213de949cddebe0a123654be580ba114b951020
parent 353262 cc389c3a0973b01da870c47734d69ecf81f952a2
child 353264 20356afd76546e8b9dfc4bb96d050df414aa8351
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdaoshengmu, lizzard
bugs1325699
milestone52.0a2
Bug 1325699 (flattened) - Fix uniform block handling. - r=daoshengmu a=lizzard Flattened with: * Handle -1 attrib locations. - r=daoshengmu MozReview-Commit-ID: LWj9azbh7Y2
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);
 };