Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 48 additions & 23 deletions impeller/entity/entity_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -253,14 +253,12 @@ void EntityPass::AddSubpassInline(std::unique_ptr<EntityPass> pass) {
pass->advanced_blend_reads_from_pass_texture_;
}

static RenderTarget::AttachmentConfig GetDefaultStencilConfig(bool readable) {
return RenderTarget::AttachmentConfig{
.storage_mode = readable ? StorageMode::kDevicePrivate
: StorageMode::kDeviceTransient,
.load_action = LoadAction::kDontCare,
.store_action = StoreAction::kDontCare,
};
}
static const constexpr RenderTarget::AttachmentConfig kDefaultStencilConfig =
RenderTarget::AttachmentConfig{
.storage_mode = StorageMode::kDeviceTransient,
.load_action = LoadAction::kDontCare,
.store_action = StoreAction::kDontCare,
};

static EntityPassTarget CreateRenderTarget(ContentContext& renderer,
ISize size,
Expand All @@ -285,8 +283,8 @@ static EntityPassTarget CreateRenderTarget(ContentContext& renderer,
.resolve_storage_mode = StorageMode::kDevicePrivate,
.load_action = LoadAction::kDontCare,
.store_action = StoreAction::kMultisampleResolve,
.clear_color = clear_color}, // color_attachment_config
GetDefaultStencilConfig(readable) // stencil_attachment_config
.clear_color = clear_color}, // color_attachment_config
kDefaultStencilConfig // stencil_attachment_config

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be able to remove the readable param from CreateRenderTarget now

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

);
} else {
target = RenderTarget::CreateOffscreen(
Expand All @@ -299,8 +297,8 @@ static EntityPassTarget CreateRenderTarget(ContentContext& renderer,
.load_action = LoadAction::kDontCare,
.store_action = StoreAction::kDontCare,
.clear_color = clear_color,
}, // color_attachment_config
GetDefaultStencilConfig(readable) // stencil_attachment_config
}, // color_attachment_config
kDefaultStencilConfig // stencil_attachment_config
);
}

Expand Down Expand Up @@ -465,8 +463,7 @@ bool EntityPass::Render(ContentContext& renderer,
*renderer.GetContext(), *renderer.GetRenderTargetCache(),
color0.texture->GetSize(),
renderer.GetContext()->GetCapabilities()->SupportsOffscreenMSAA(),
"ImpellerOnscreen",
GetDefaultStencilConfig(reads_from_onscreen_backdrop));
"ImpellerOnscreen", kDefaultStencilConfig);
}

// Set up the clear color of the root pass.
Expand Down Expand Up @@ -503,10 +500,10 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
//--------------------------------------------------------------------------
/// Setup entity element.
///

if (const auto& entity = std::get_if<Entity>(&element)) {
element_entity = *entity;
element_entity.SetCapture(capture.CreateChild("Entity"));

if (!global_pass_position.IsZero()) {
// If the pass image is going to be rendered with a non-zero position,
// apply the negative translation to entity copies before rendering them
Expand All @@ -515,16 +512,15 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
Matrix::MakeTranslation(Vector3(-global_pass_position)) *
element_entity.GetTransformation());
}
return EntityPass::EntityResult::Success(element_entity);
}

//--------------------------------------------------------------------------
/// Setup subpass element.
///

else if (const auto& subpass_ptr =
std::get_if<std::unique_ptr<EntityPass>>(&element)) {
if (const auto& subpass_ptr =
std::get_if<std::unique_ptr<EntityPass>>(&element)) {
auto subpass = subpass_ptr->get();

if (subpass->delegate_->CanElide()) {
return EntityPass::EntityResult::Skip();
}
Expand Down Expand Up @@ -696,11 +692,10 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
element_entity.SetTransformation(subpass_texture_capture.AddMatrix(
"Transform", Matrix::MakeTranslation(Vector3(subpass_coverage->origin -
global_pass_position))));
} else {
FML_UNREACHABLE();
}

return EntityPass::EntityResult::Success(element_entity);
return EntityPass::EntityResult::Success(element_entity);
}
FML_UNREACHABLE();
}

bool EntityPass::RenderElement(Entity& element_entity,
Expand All @@ -724,6 +719,15 @@ bool EntityPass::RenderElement(Entity& element_entity,
// blit the non-MSAA resolve texture of the previous pass to MSAA textures
// (let alone a transient one).
if (result.backdrop_texture) {
// Restore any clips that were recorded before the backdrop filter was
// applied.
auto& replay_entities = clip_replay_->GetReplayEntities();
for (const auto& entity : replay_entities) {
if (!entity.Render(renderer, *result.pass)) {
VALIDATION_LOG << "Failed to render entity for clip restore.";
}
}

auto size_rect = Rect::MakeSize(result.pass->GetRenderTargetSize());
auto msaa_backdrop_contents = TextureContents::MakeRect(size_rect);
msaa_backdrop_contents->SetStencilEnabled(false);
Expand Down Expand Up @@ -836,6 +840,7 @@ bool EntityPass::RenderElement(Entity& element_entity,
#endif

element_entity.SetClipDepth(element_entity.GetClipDepth() - clip_depth_floor);
clip_replay_->RecordEntity(element_entity, clip_coverage.type);
if (!element_entity.Render(renderer, *result.pass)) {
VALIDATION_LOG << "Failed to render entity.";
return false;
Expand Down Expand Up @@ -1180,4 +1185,24 @@ void EntityPass::SetEnableOffscreenCheckerboard(bool enabled) {
enable_offscreen_debug_checkerboard_ = enabled;
}

EntityPassClipReplay::EntityPassClipReplay() {}

void EntityPassClipReplay::RecordEntity(const Entity& entity,
Contents::ClipCoverage::Type type) {
switch (type) {
case Contents::ClipCoverage::Type::kNoChange:
return;
case Contents::ClipCoverage::Type::kAppend:
rendered_clip_entities_.push_back(entity);
break;
case Contents::ClipCoverage::Type::kRestore:
rendered_clip_entities_.pop_back();
break;
}
}

const std::vector<Entity>& EntityPassClipReplay::GetReplayEntities() const {
return rendered_clip_entities_;
}

} // namespace impeller
23 changes: 23 additions & 0 deletions impeller/entity/entity_pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
namespace impeller {

class ContentContext;
class EntityPassClipReplay;

class EntityPass {
public:
Expand Down Expand Up @@ -285,6 +286,8 @@ class EntityPass {
bool flood_clip_ = false;
bool enable_offscreen_debug_checkerboard_ = false;
std::optional<Rect> bounds_limit_;
std::unique_ptr<EntityPassClipReplay> clip_replay_ =
std::make_unique<EntityPassClipReplay>();

/// These values are incremented whenever something is added to the pass that
/// requires reading from the backdrop texture. Currently, this can happen in
Expand All @@ -309,4 +312,24 @@ class EntityPass {
EntityPass& operator=(const EntityPass&) = delete;
};

/// @brief A class that tracks all clips that have been recorded in the current
/// entity pass stencil.
///
/// These clips are replayed when restoring the backdrop so that the
/// stencil buffer is left in an identical state.
class EntityPassClipReplay {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EntityPassClipRecorder?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is much better

public:
EntityPassClipReplay();

~EntityPassClipReplay() = default;

/// @brief Record the entity based on the provided coverage [type].
void RecordEntity(const Entity& entity, Contents::ClipCoverage::Type type);

const std::vector<Entity>& GetReplayEntities() const;

private:
std::vector<Entity> rendered_clip_entities_;
};

} // namespace impeller
13 changes: 2 additions & 11 deletions impeller/entity/inline_pass_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ InlinePassContext::InlinePassContext(
std::optional<RenderPassResult> collapsed_parent_pass)
: context_(std::move(context)),
pass_target_(pass_target),
total_pass_reads_(pass_texture_reads),
is_collapsed_(collapsed_parent_pass.has_value()) {
if (collapsed_parent_pass.has_value()) {
pass_ = collapsed_parent_pass.value().pass;
Expand Down Expand Up @@ -140,17 +139,9 @@ InlinePassContext::RenderPassResult InlinePassContext::GetRenderPass(
return {};
}

// Only clear the stencil if this is the very first pass of the
// layer.
stencil->load_action =
pass_count_ > 0 ? LoadAction::kLoad : LoadAction::kClear;
// If we're on the last pass of the layer, there's no need to store the
// stencil because nothing needs to read it.
stencil->store_action = pass_count_ == total_pass_reads_
? StoreAction::kDontCare
: StoreAction::kStore;
stencil->load_action = LoadAction::kClear;
stencil->store_action = StoreAction::kDontCare;
pass_target_.target_.SetStencilAttachment(stencil.value());

pass_target_.target_.SetColorAttachment(color0, 0);

pass_ = command_buffer_->CreateRenderPass(pass_target_.GetRenderTarget());
Expand Down
2 changes: 1 addition & 1 deletion impeller/entity/inline_pass_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class InlinePassContext {
std::shared_ptr<CommandBuffer> command_buffer_;
std::shared_ptr<RenderPass> pass_;
uint32_t pass_count_ = 0;
uint32_t total_pass_reads_ = 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good riddance...


// Whether this context is collapsed into a parent entity pass.
bool is_collapsed_ = false;

Expand Down