From 0bf2cec886ecc3a32d2746c180c16521287a2019 Mon Sep 17 00:00:00 2001 From: Benjamin Doherty Date: Thu, 17 Oct 2024 13:44:32 -0400 Subject: [PATCH 1/2] Metal: avoid redundant scissor rect state changes --- filament/backend/src/metal/MetalContext.h | 1 + filament/backend/src/metal/MetalDriver.mm | 7 ++++++- filament/backend/src/metal/MetalState.h | 16 ++++++++++++---- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/filament/backend/src/metal/MetalContext.h b/filament/backend/src/metal/MetalContext.h index ef1175fa688d..e8acf71fbc6b 100644 --- a/filament/backend/src/metal/MetalContext.h +++ b/filament/backend/src/metal/MetalContext.h @@ -161,6 +161,7 @@ struct MetalContext { CullModeStateTracker cullModeState; WindingStateTracker windingState; DepthClampStateTracker depthClampState; + ScissorRectStateTracker scissorRectState; Handle currentRenderPrimitive; // State caches. diff --git a/filament/backend/src/metal/MetalDriver.mm b/filament/backend/src/metal/MetalDriver.mm index fb17e99c76b4..8528bb77d0c0 100644 --- a/filament/backend/src/metal/MetalDriver.mm +++ b/filament/backend/src/metal/MetalDriver.mm @@ -1227,6 +1227,7 @@ mContext->depthStencilState.invalidate(); mContext->cullModeState.invalidate(); mContext->windingState.invalidate(); + mContext->scissorRectState.invalidate(); mContext->currentPolygonOffset = {0.0f, 0.0f}; mContext->finalizedDescriptorSets.clear(); @@ -1953,7 +1954,11 @@ .height = static_cast(bottom - top) }; - [mContext->currentRenderPassEncoder setScissorRect:scissorRect]; + auto& srs = mContext->scissorRectState; + srs.updateState(scissorRect); + if (srs.stateChanged()) { + [mContext->currentRenderPassEncoder setScissorRect:scissorRect]; + } } void MetalDriver::beginTimerQuery(Handle tqh) { diff --git a/filament/backend/src/metal/MetalState.h b/filament/backend/src/metal/MetalState.h index 1e14cddc2581..d969d2695e20 100644 --- a/filament/backend/src/metal/MetalState.h +++ b/filament/backend/src/metal/MetalState.h @@ -204,9 +204,8 @@ class StateCache { // Different kinds of state, like pipeline state, uniform buffer state, etc., are passed to the // current Metal command encoder and persist throughout the lifetime of the encoder (a frame). // StateTracker is used to prevent calling redundant state change methods. -template +template > class StateTracker { - public: // Call to force the state to dirty at the beginning of each frame, as all state must be @@ -214,7 +213,7 @@ class StateTracker { void invalidate() noexcept { mStateDirty = true; } void updateState(const StateType& newState) noexcept { - if (mCurrentState != newState) { + if (!StateEqual()(mCurrentState, newState)) { mCurrentState = newState; mStateDirty = true; } @@ -235,7 +234,6 @@ class StateTracker { bool mStateDirty = true; StateType mCurrentState = {}; - }; // Pipeline state @@ -343,6 +341,16 @@ using DepthStencilStateTracker = StateTracker; using DepthStencilStateCache = StateCache, DepthStateCreator>; +struct MtlScissorRectEqual { + bool operator()(MTLScissorRect lhs, MTLScissorRect rhs) const { + return lhs.height == rhs.height && + lhs.width == rhs.width && + lhs.x == rhs.x && + lhs.y == rhs.y; + } +}; +using ScissorRectStateTracker = StateTracker; + // Uniform buffers class MetalBufferObject; From a3ad02ab6b32063be4bab18a197fba611bfe05db Mon Sep 17 00:00:00 2001 From: Benjamin Doherty Date: Fri, 18 Oct 2024 11:06:39 -0400 Subject: [PATCH 2/2] Use const& --- filament/backend/src/metal/MetalState.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filament/backend/src/metal/MetalState.h b/filament/backend/src/metal/MetalState.h index d969d2695e20..c861cd8cfc95 100644 --- a/filament/backend/src/metal/MetalState.h +++ b/filament/backend/src/metal/MetalState.h @@ -342,7 +342,7 @@ using DepthStencilStateCache = StateCache; struct MtlScissorRectEqual { - bool operator()(MTLScissorRect lhs, MTLScissorRect rhs) const { + bool operator()(const MTLScissorRect& lhs, const MTLScissorRect& rhs) const { return lhs.height == rhs.height && lhs.width == rhs.width && lhs.x == rhs.x &&