Skip to content

Commit

Permalink
Metal: avoid redundant scissor rect state changes (#8207)
Browse files Browse the repository at this point in the history
  • Loading branch information
bejado authored Oct 18, 2024
1 parent ba680cf commit a494f9f
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 5 deletions.
1 change: 1 addition & 0 deletions filament/backend/src/metal/MetalContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ struct MetalContext {
CullModeStateTracker cullModeState;
WindingStateTracker windingState;
DepthClampStateTracker depthClampState;
ScissorRectStateTracker scissorRectState;
Handle<HwRenderPrimitive> currentRenderPrimitive;

// State caches.
Expand Down
7 changes: 6 additions & 1 deletion filament/backend/src/metal/MetalDriver.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -1953,7 +1954,11 @@
.height = static_cast<NSUInteger>(bottom - top)
};

[mContext->currentRenderPassEncoder setScissorRect:scissorRect];
auto& srs = mContext->scissorRectState;
srs.updateState(scissorRect);
if (srs.stateChanged()) {
[mContext->currentRenderPassEncoder setScissorRect:scissorRect];
}
}

void MetalDriver::beginTimerQuery(Handle<HwTimerQuery> tqh) {
Expand Down
16 changes: 12 additions & 4 deletions filament/backend/src/metal/MetalState.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,17 +204,16 @@ 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<typename StateType>
template <typename StateType, typename StateEqual = std::equal_to<StateType>>
class StateTracker {

public:

// Call to force the state to dirty at the beginning of each frame, as all state must be
// re-bound.
void invalidate() noexcept { mStateDirty = true; }

void updateState(const StateType& newState) noexcept {
if (mCurrentState != newState) {
if (!StateEqual()(mCurrentState, newState)) {
mCurrentState = newState;
mStateDirty = true;
}
Expand All @@ -235,7 +234,6 @@ class StateTracker {

bool mStateDirty = true;
StateType mCurrentState = {};

};

// Pipeline state
Expand Down Expand Up @@ -343,6 +341,16 @@ using DepthStencilStateTracker = StateTracker<DepthStencilState>;
using DepthStencilStateCache = StateCache<DepthStencilState, id<MTLDepthStencilState>,
DepthStateCreator>;

struct MtlScissorRectEqual {
bool operator()(const MTLScissorRect& lhs, const MTLScissorRect& rhs) const {
return lhs.height == rhs.height &&
lhs.width == rhs.width &&
lhs.x == rhs.x &&
lhs.y == rhs.y;
}
};
using ScissorRectStateTracker = StateTracker<MTLScissorRect, MtlScissorRectEqual>;

// Uniform buffers

class MetalBufferObject;
Expand Down

0 comments on commit a494f9f

Please sign in to comment.