[Impeller] Get rid of redundant viewport and scissor bindings. (#35330)
diff --git a/impeller/renderer/backend/metal/render_pass_mtl.mm b/impeller/renderer/backend/metal/render_pass_mtl.mm
index 5f38a62..90f074e 100644
--- a/impeller/renderer/backend/metal/render_pass_mtl.mm
+++ b/impeller/renderer/backend/metal/render_pass_mtl.mm
@@ -299,6 +299,36 @@
return false;
}
+ void SetViewport(const Viewport& viewport) {
+ if (viewport_.has_value() && viewport_.value() == viewport) {
+ return;
+ }
+ [encoder_ setViewport:MTLViewport{
+ .originX = viewport.rect.origin.x,
+ .originY = viewport.rect.origin.y,
+ .width = viewport.rect.size.width,
+ .height = viewport.rect.size.height,
+ .znear = viewport.depth_range.z_near,
+ .zfar = viewport.depth_range.z_far,
+ }];
+ viewport_ = viewport;
+ }
+
+ void SetScissor(const IRect& scissor) {
+ if (scissor_.has_value() && scissor_.value() == scissor) {
+ return;
+ }
+ [encoder_
+ setScissorRect:MTLScissorRect{
+ .x = static_cast<NSUInteger>(scissor.origin.x),
+ .y = static_cast<NSUInteger>(scissor.origin.y),
+ .width = static_cast<NSUInteger>(scissor.size.width),
+ .height =
+ static_cast<NSUInteger>(scissor.size.height),
+ }];
+ scissor_ = scissor;
+ }
+
private:
struct BufferOffsetPair {
id<MTLBuffer> buffer = nullptr;
@@ -314,6 +344,8 @@
std::map<ShaderStage, BufferMap> buffers_;
std::map<ShaderStage, TextureMap> textures_;
std::map<ShaderStage, SamplerMap> samplers_;
+ std::optional<Viewport> viewport_;
+ std::optional<IRect> scissor_;
};
static bool Bind(PassBindingsCache& pass,
@@ -423,6 +455,11 @@
PipelineMTL::Cast(*command.pipeline).GetMTLRenderPipelineState());
pass_bindings.SetDepthStencilState(
PipelineMTL::Cast(*command.pipeline).GetMTLDepthStencilState());
+ pass_bindings.SetViewport(command.viewport.value_or<Viewport>(
+ {.rect = Rect::MakeSize(GetRenderTargetSize())}));
+ pass_bindings.SetScissor(
+ command.scissor.value_or(IRect::MakeSize(GetRenderTargetSize())));
+
[encoder setFrontFacingWinding:pipeline_desc.GetWindingOrder() ==
WindingOrder::kClockwise
? MTLWindingClockwise
@@ -430,27 +467,6 @@
[encoder setCullMode:ToMTLCullMode(pipeline_desc.GetCullMode())];
[encoder setStencilReferenceValue:command.stencil_reference];
- auto v = command.viewport.value_or<Viewport>(
- {.rect = Rect::MakeSize(GetRenderTargetSize())});
- MTLViewport viewport = {
- .originX = v.rect.origin.x,
- .originY = v.rect.origin.y,
- .width = v.rect.size.width,
- .height = v.rect.size.height,
- .znear = v.depth_range.z_near,
- .zfar = v.depth_range.z_far,
- };
- [encoder setViewport:viewport];
-
- auto s = command.scissor.value_or(IRect::MakeSize(GetRenderTargetSize()));
- MTLScissorRect scissor = {
- .x = static_cast<NSUInteger>(s.origin.x),
- .y = static_cast<NSUInteger>(s.origin.y),
- .width = static_cast<NSUInteger>(s.size.width),
- .height = static_cast<NSUInteger>(s.size.height),
- };
- [encoder setScissorRect:scissor];
-
if (!bind_stage_resources(command.vertex_bindings, ShaderStage::kVertex)) {
return false;
}
diff --git a/impeller/renderer/formats.h b/impeller/renderer/formats.h
index ebf318f..65509c6 100644
--- a/impeller/renderer/formats.h
+++ b/impeller/renderer/formats.h
@@ -184,11 +184,19 @@
struct DepthRange {
Scalar z_near = 0.0;
Scalar z_far = 1.0;
+
+ constexpr bool operator==(const DepthRange& other) const {
+ return z_near == other.z_near && z_far == other.z_far;
+ }
};
struct Viewport {
Rect rect;
DepthRange depth_range;
+
+ constexpr bool operator==(const Viewport& other) const {
+ return rect == other.rect && depth_range == other.depth_range;
+ }
};
enum class MinMagFilter {