From 186c6dca7d4930f28a54f00e5cf5459bf4bb896e Mon Sep 17 00:00:00 2001 From: Kelsey Gilbert Date: Tue, 15 Nov 2022 04:11:16 +0000 Subject: [PATCH] Bug 1800301 - Reduce allocs and ptr-chasing in ScopedResolveTexturesForDraw. r=gfx-reviewers,lsalzman + Add inlining_vector, like AutoTArray, but using std::vector for familiarity and safety. Differential Revision: https://phabricator.services.mozilla.com/D162059 --- dom/canvas/WebGLContext.h | 5 ----- dom/canvas/WebGLContextDraw.cpp | 36 +++++++++++++++++++++------------ dom/canvas/WebGLContextGL.cpp | 3 +-- dom/canvas/WebGLContextValidate.cpp | 2 ++ dom/canvas/WebGLProgram.h | 2 +- dom/canvas/WebGLTypes.h | 40 +++++++++++++++++++++++++++++++++++++ 6 files changed, 67 insertions(+), 21 deletions(-) diff --git a/dom/canvas/WebGLContext.h b/dom/canvas/WebGLContext.h index b191a2f133a1..77b9270941b1 100644 --- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -315,11 +315,6 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr { std::unique_ptr mIncompleteTexOverride; - // Reuse, to avoid reallocing data for this, as this is showing up in - // profiles. - std::unordered_map - mReuseable_ScopedResolveTexturesForDraw_samplerByTexUnit; - public: class FuncScope; diff --git a/dom/canvas/WebGLContextDraw.cpp b/dom/canvas/WebGLContextDraw.cpp index e2bed5cbe59d..1891b833416a 100644 --- a/dom/canvas/WebGLContextDraw.cpp +++ b/dom/canvas/WebGLContextDraw.cpp @@ -79,11 +79,11 @@ ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw( : mWebGL(webgl) { const auto& fb = mWebGL->mBoundDrawFramebuffer; - auto& samplerByTexUnit = - mWebGL->mReuseable_ScopedResolveTexturesForDraw_samplerByTexUnit; - if (!samplerByTexUnit.empty()) { - samplerByTexUnit.clear(); - } + struct SamplerByTexUnit { + uint8_t texUnit; + const webgl::SamplerUniformInfo* sampler; + }; + inlining_vector samplerByTexUnit; MOZ_ASSERT(mWebGL->mActiveProgramLinkInfo); const auto& samplerUniforms = mWebGL->mActiveProgramLinkInfo->samplerUniforms; @@ -96,11 +96,20 @@ ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw( MOZ_ASSERT(texUnit < texList.Length()); { - auto& prevSamplerForTexUnit = samplerByTexUnit[texUnit]; + decltype(SamplerByTexUnit::sampler) prevSamplerForTexUnit = nullptr; + for (const auto& cur : samplerByTexUnit) { + if (cur.texUnit == texUnit) { + prevSamplerForTexUnit = cur.sampler; + } + } if (!prevSamplerForTexUnit) { prevSamplerForTexUnit = &uniform; + samplerByTexUnit.push_back( + SamplerByTexUnit{texUnit, prevSamplerForTexUnit}); } - if (&uniform.texListForType != &prevSamplerForTexUnit->texListForType) { + + if (MOZ_UNLIKELY(&uniform.texListForType != + &prevSamplerForTexUnit->texListForType)) { // Pointing to different tex lists means different types! const auto linkInfo = mWebGL->mActiveProgramLinkInfo; const auto LocInfoBySampler = [&](const webgl::SamplerUniformInfo* p) @@ -132,11 +141,11 @@ ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw( const auto& sampler = mWebGL->mBoundSamplers[texUnit]; const auto& samplingInfo = tex->GetSampleableInfo(sampler.get()); - if (!samplingInfo) { // There was an error. + if (MOZ_UNLIKELY(!samplingInfo)) { // There was an error. *out_error = true; return; } - if (!samplingInfo->IsComplete()) { + if (MOZ_UNLIKELY(!samplingInfo->IsComplete())) { if (samplingInfo->incompleteReason) { const auto& targetName = GetEnumName(tex->Target().get()); mWebGL->GenerateWarning("%s at unit %u is incomplete: %s", targetName, @@ -148,7 +157,7 @@ ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw( // We have more validation to do if we're otherwise complete: const auto& texBaseType = samplingInfo->usage->format->baseType; - if (texBaseType != uniformBaseType) { + if (MOZ_UNLIKELY(texBaseType != uniformBaseType)) { const auto& targetName = GetEnumName(tex->Target().get()); const auto& srcType = ToString(texBaseType); const auto& dstType = ToString(uniformBaseType); @@ -160,7 +169,8 @@ ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw( return; } - if (uniform.isShadowSampler != samplingInfo->isDepthTexCompare) { + if (MOZ_UNLIKELY(uniform.isShadowSampler != + samplingInfo->isDepthTexCompare)) { const auto& targetName = GetEnumName(tex->Target().get()); mWebGL->ErrorInvalidOperation( "%s at unit %u is%s a depth texture" @@ -173,8 +183,8 @@ ScopedResolveTexturesForDraw::ScopedResolveTexturesForDraw( return; } - if (!ValidateNoSamplingFeedback(*tex, samplingInfo->levels, fb.get(), - texUnit)) { + if (MOZ_UNLIKELY(!ValidateNoSamplingFeedback(*tex, samplingInfo->levels, + fb.get(), texUnit))) { *out_error = true; return; } diff --git a/dom/canvas/WebGLContextGL.cpp b/dom/canvas/WebGLContextGL.cpp index 10b1f576ad68..de599148169e 100644 --- a/dom/canvas/WebGLContextGL.cpp +++ b/dom/canvas/WebGLContextGL.cpp @@ -15,7 +15,6 @@ #include "WebGLQuery.h" #include "WebGLRenderbuffer.h" #include "WebGLTexture.h" -#include "WebGLExtensions.h" #include "WebGLVertexArray.h" #include "nsDebug.h" @@ -1356,7 +1355,7 @@ void WebGLContext::UniformData( auto destIndex = locInfo->indexIntoUniform; for (const auto& val : Range(srcBegin, elemCount)) { if (destIndex >= texUnits.size()) break; - texUnits[destIndex] = val; + texUnits.at(destIndex) = AssertedCast(val); destIndex += 1; } } diff --git a/dom/canvas/WebGLContextValidate.cpp b/dom/canvas/WebGLContextValidate.cpp index 1a2e673d0b22..f01ed06a3616 100644 --- a/dom/canvas/WebGLContextValidate.cpp +++ b/dom/canvas/WebGLContextValidate.cpp @@ -202,6 +202,8 @@ static webgl::Limits MakeLimits(const WebGLContext& webgl) { // GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value. gl.GetUIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &limits.maxTexUnits); + limits.maxTexUnits = std::min( + limits.maxTexUnits, uint32_t{UINT8_MAX}); // We want to use uint8_t. gl.GetUIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &limits.maxTex2dSize); gl.GetUIntegerv(LOCAL_GL_MAX_CUBE_MAP_TEXTURE_SIZE, &limits.maxTexCubeSize); diff --git a/dom/canvas/WebGLProgram.h b/dom/canvas/WebGLProgram.h index fc7d97987abc..ad4dc6ef7212 100644 --- a/dom/canvas/WebGLProgram.h +++ b/dom/canvas/WebGLProgram.h @@ -78,7 +78,7 @@ struct SamplerUniformInfo final { const decltype(WebGLContext::mBound2DTextures)& texListForType; const webgl::TextureBaseType texBaseType; const bool isShadowSampler; - std::vector texUnits; + inlining_vector texUnits; }; struct LocationInfo final { diff --git a/dom/canvas/WebGLTypes.h b/dom/canvas/WebGLTypes.h index ebfc534eff1d..0e4a59cd8613 100644 --- a/dom/canvas/WebGLTypes.h +++ b/dom/canvas/WebGLTypes.h @@ -6,6 +6,7 @@ #ifndef WEBGLTYPES_H_ #define WEBGLTYPES_H_ +#include #include #include #include @@ -1200,6 +1201,45 @@ union UniformDataVal { } // namespace webgl +// - + +template +struct InliningAllocator { + using value_type = T; + + template + struct rebind { + typedef InliningAllocator other; + }; + + private: + std::array mInlined = {}; + + public: + InliningAllocator() = default; + InliningAllocator(const InliningAllocator&) = delete; + InliningAllocator(InliningAllocator&&) = delete; + InliningAllocator& operator=(const InliningAllocator&) = delete; + InliningAllocator& operator=(InliningAllocator&&) = delete; + + T* allocate(const size_t n) { + T* p = nullptr; + if (n <= mInlined.size()) { + p = mInlined.data(); // You better be using memmove not memcpy! + } else { + p = new T[n]; + } + return p; + } + void deallocate(T* const p, size_t) { + if (p != mInlined.data()) { + delete[] p; + } + } +}; +template +using inlining_vector = std::vector>; + } // namespace mozilla #endif -- 2.11.4.GIT