From 8115d1dafa1884a8248a779db4b7ea94722441f4 Mon Sep 17 00:00:00 2001 From: Brandon DeRosier Date: Wed, 24 Apr 2024 13:35:09 -0700 Subject: [PATCH] [Impeller] Cleanup legacy StencilModes and document overdraw prevention. --- impeller/entity/contents/clip_contents.cc | 5 ++- .../entity/contents/color_source_contents.h | 2 +- impeller/entity/contents/content_context.cc | 25 ++++-------- impeller/entity/contents/content_context.h | 38 +++++++++++-------- .../renderer/compute_subgroup_unittests.cc | 6 +-- 5 files changed, 37 insertions(+), 39 deletions(-) diff --git a/impeller/entity/contents/clip_contents.cc b/impeller/entity/contents/clip_contents.cc index 966070b84fedf..f13f452734732 100644 --- a/impeller/entity/contents/clip_contents.cc +++ b/impeller/entity/contents/clip_contents.cc @@ -133,7 +133,7 @@ bool ClipContents::Render(const ContentContext& renderer, case GeometryResult::Mode::kPreventOverdraw: pass.SetCommandLabel("Clip stencil preparation (Increment)"); options.stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipIncrement; + ContentContextOptions::StencilMode::kOverdrawPreventionIncrement; break; } pass.SetPipeline(renderer.GetClipPipeline(options)); @@ -235,7 +235,8 @@ bool ClipRestoreContents::Render(const ContentContext& renderer, pass.SetCommandLabel("Restore Clip"); auto options = OptionsFromPass(pass); options.blend_mode = BlendMode::kDestination; - options.stencil_mode = ContentContextOptions::StencilMode::kLegacyClipRestore; + options.stencil_mode = + ContentContextOptions::StencilMode::kOverdrawPreventionRestore; options.primitive_type = PrimitiveType::kTriangleStrip; pass.SetPipeline(renderer.GetClipPipeline(options)); pass.SetStencilReference(0); diff --git a/impeller/entity/contents/color_source_contents.h b/impeller/entity/contents/color_source_contents.h index 84a7e9a65a437..cb5a6d62eaa46 100644 --- a/impeller/entity/contents/color_source_contents.h +++ b/impeller/entity/contents/color_source_contents.h @@ -195,7 +195,7 @@ class ColorSourceContents : public Contents { // the stencil buffer (happens below in this method). if (geometry_result.mode == GeometryResult::Mode::kPreventOverdraw) { options.stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipIncrement; + ContentContextOptions::StencilMode::kOverdrawPreventionIncrement; } pass.SetStencilReference(0); diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index b6e6dde5b5806..b11c15f2498de 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -193,25 +193,15 @@ void ContentContextOptions::ApplyToPipelineDescriptor( front_stencil.stencil_failure = StencilOperation::kSetToReferenceValue; desc.SetStencilAttachmentDescriptors(front_stencil); break; - case StencilMode::kLegacyClipRestore: - front_stencil.stencil_compare = CompareFunction::kLess; - front_stencil.depth_stencil_pass = - StencilOperation::kSetToReferenceValue; - desc.SetStencilAttachmentDescriptors(front_stencil); - break; - case StencilMode::kLegacyClipIncrement: + case StencilMode::kOverdrawPreventionIncrement: front_stencil.stencil_compare = CompareFunction::kEqual; front_stencil.depth_stencil_pass = StencilOperation::kIncrementClamp; desc.SetStencilAttachmentDescriptors(front_stencil); break; - case StencilMode::kLegacyClipDecrement: - front_stencil.stencil_compare = CompareFunction::kEqual; - front_stencil.depth_stencil_pass = StencilOperation::kDecrementClamp; - desc.SetStencilAttachmentDescriptors(front_stencil); - break; - case StencilMode::kLegacyClipCompare: - front_stencil.stencil_compare = CompareFunction::kEqual; - front_stencil.depth_stencil_pass = StencilOperation::kKeep; + case StencilMode::kOverdrawPreventionRestore: + front_stencil.stencil_compare = CompareFunction::kLess; + front_stencil.depth_stencil_pass = + StencilOperation::kSetToReferenceValue; desc.SetStencilAttachmentDescriptors(front_stencil); break; } @@ -617,9 +607,8 @@ void ContentContext::InitializeCommonlyUsedShadersIfNeeded() const { options.blend_mode = BlendMode::kDestination; options.primitive_type = PrimitiveType::kTriangleStrip; for (const auto stencil_mode : - {ContentContextOptions::StencilMode::kLegacyClipIncrement, - ContentContextOptions::StencilMode::kLegacyClipDecrement, - ContentContextOptions::StencilMode::kLegacyClipRestore}) { + {ContentContextOptions::StencilMode::kOverdrawPreventionIncrement, + ContentContextOptions::StencilMode::kOverdrawPreventionRestore}) { options.stencil_mode = stencil_mode; CreateIfNeeded(clip_pipelines_, options); } diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index 9e3011674e434..48a730b0f2069 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -273,10 +273,11 @@ using TiledTextureExternalPipeline = /// but they shouldn't require e.g. 10s of thousands. struct ContentContextOptions { enum class StencilMode : uint8_t { - /// Turn the stencil test off. Used when drawing without stencil-then-cover. + /// Turn the stencil test off. Used when drawing without stencil-then-cover + /// or overdraw prevention. kIgnore, - // Operations used for stencil-then-cover + // Operations used for stencil-then-cover. /// Draw the stencil for the NonZero fill path rule. /// @@ -302,24 +303,31 @@ struct ContentContextOptions { /// The stencil ref should always be 0 on commands using this mode. kCoverCompareInverted, - // Operations to control the legacy clip implementation, which forms a - // heightmap on the stencil buffer. - - /// Slice the clip heightmap to a new maximum height. - kLegacyClipRestore, - /// Increment the stencil heightmap. - kLegacyClipIncrement, - /// Decrement the stencil heightmap (used for difference clipping only). - kLegacyClipDecrement, - /// Used for applying clips to all non-clip draw calls. - kLegacyClipCompare, + // Operations used for the "overdraw prevention" mechanism. This is used for + // drawing strokes. + + /// For each fragment, increment the stencil value if it's currently zero. + /// Discard fragments when the value is non-zero. This prevents + /// self-overlapping strokes from drawing over themselves. + /// + /// Note that this is done for rendering correctness, not performance. If a + /// stroke is drawn with a backdrop-reliant blend and self-intersects, then + /// the intersected geometry will render incorrectly when overdrawn because + /// we don't adjust the geometry prevent self-intersection. + /// + /// The stencil ref should always be 0 on commands using this mode. + kOverdrawPreventionIncrement, + /// Reset the stencil to a new maximum value specified by the ref (currently + /// always 0). + /// + /// The stencil ref should always be 0 on commands using this mode. + kOverdrawPreventionRestore, }; SampleCount sample_count = SampleCount::kCount1; BlendMode blend_mode = BlendMode::kSourceOver; CompareFunction depth_compare = CompareFunction::kAlways; - StencilMode stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipCompare; + StencilMode stencil_mode = ContentContextOptions::StencilMode::kIgnore; PrimitiveType primitive_type = PrimitiveType::kTriangle; PixelFormat color_attachment_pixel_format = PixelFormat::kUnknown; bool has_depth_stencil_attachments = true; diff --git a/impeller/renderer/compute_subgroup_unittests.cc b/impeller/renderer/compute_subgroup_unittests.cc index dd657b1a62474..c34a531893c05 100644 --- a/impeller/renderer/compute_subgroup_unittests.cc +++ b/impeller/renderer/compute_subgroup_unittests.cc @@ -145,7 +145,7 @@ TEST_P(ComputeSubgroupTest, PathPlayground) { options.primitive_type = PrimitiveType::kTriangleStrip; options.stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipIncrement; + ContentContextOptions::StencilMode::kOverdrawPreventionIncrement; pass.SetPipeline(renderer.GetSolidFillPipeline(options)); @@ -343,7 +343,7 @@ TEST_P(ComputeSubgroupTest, LargePath) { options.primitive_type = PrimitiveType::kTriangleStrip; options.stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipIncrement; + ContentContextOptions::StencilMode::kOverdrawPreventionIncrement; pass.SetPipeline(renderer.GetSolidFillPipeline(options)); @@ -422,7 +422,7 @@ TEST_P(ComputeSubgroupTest, QuadAndCubicInOnePath) { options.primitive_type = PrimitiveType::kTriangleStrip; options.stencil_mode = - ContentContextOptions::StencilMode::kLegacyClipIncrement; + ContentContextOptions::StencilMode::kOverdrawPreventionIncrement; pass.SetPipeline(renderer.GetSolidFillPipeline(options));