Metal: avoid redundant scissor rect state changes (#8207)
This commit is contained in:
@@ -161,6 +161,7 @@ struct MetalContext {
|
||||
CullModeStateTracker cullModeState;
|
||||
WindingStateTracker windingState;
|
||||
DepthClampStateTracker depthClampState;
|
||||
ScissorRectStateTracker scissorRectState;
|
||||
Handle<HwRenderPrimitive> currentRenderPrimitive;
|
||||
|
||||
// State caches.
|
||||
|
||||
@@ -1227,6 +1227,7 @@ void MetalDriver::beginRenderPass(Handle<HwRenderTarget> rth,
|
||||
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 @@ void MetalDriver::scissor(Viewport scissorBox) {
|
||||
.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) {
|
||||
|
||||
@@ -204,9 +204,8 @@ private:
|
||||
// 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
|
||||
@@ -214,7 +213,7 @@ public:
|
||||
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 @@ private:
|
||||
|
||||
bool mStateDirty = true;
|
||||
StateType mCurrentState = {};
|
||||
|
||||
};
|
||||
|
||||
// Pipeline state
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user