Skip to content

Commit d58d7d9

Browse files
authored
[Impeller] Document EntityPass, make positioning less confusing (#40636)
1 parent d21f657 commit d58d7d9

File tree

2 files changed

+140
-38
lines changed

2 files changed

+140
-38
lines changed

impeller/entity/entity_pass.cc

Lines changed: 68 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,15 @@ bool EntityPass::Render(ContentContext& renderer,
211211
auto offscreen_target =
212212
CreateRenderTarget(renderer, render_target.GetRenderTargetSize(), true);
213213

214-
if (!OnRender(
215-
renderer, offscreen_target.GetRenderTarget().GetRenderTargetSize(),
216-
offscreen_target, Point(), Point(), 0, stencil_coverage_stack)) {
214+
if (!OnRender(renderer, // renderer
215+
offscreen_target.GetRenderTarget()
216+
.GetRenderTargetSize(), // root_pass_size
217+
offscreen_target, // pass_target
218+
Point(), // global_pass_position
219+
Point(), // local_pass_position
220+
0, // pass_depth
221+
stencil_coverage_stack // stencil_coverage_stack
222+
)) {
217223
return false;
218224
}
219225

@@ -267,16 +273,22 @@ bool EntityPass::Render(ContentContext& renderer,
267273
render_target,
268274
renderer.GetDeviceCapabilities().SupportsReadFromResolve());
269275

270-
return OnRender(renderer, render_target.GetRenderTargetSize(), pass_target,
271-
Point(), Point(), 0, stencil_coverage_stack);
276+
return OnRender( //
277+
renderer, // renderer
278+
render_target.GetRenderTargetSize(), // root_pass_size
279+
pass_target, // pass_target
280+
Point(), // global_pass_position
281+
Point(), // local_pass_position
282+
0, // pass_depth
283+
stencil_coverage_stack); // stencil_coverage_stack
272284
}
273285

274286
EntityPass::EntityResult EntityPass::GetEntityForElement(
275287
const EntityPass::Element& element,
276288
ContentContext& renderer,
277289
InlinePassContext& pass_context,
278290
ISize root_pass_size,
279-
Point position,
291+
Point global_pass_position,
280292
uint32_t pass_depth,
281293
StencilCoverageStack& stencil_coverage_stack,
282294
size_t stencil_depth_floor) const {
@@ -288,12 +300,12 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
288300

289301
if (const auto& entity = std::get_if<Entity>(&element)) {
290302
element_entity = *entity;
291-
if (!position.IsZero()) {
303+
if (!global_pass_position.IsZero()) {
292304
// If the pass image is going to be rendered with a non-zero position,
293305
// apply the negative translation to entity copies before rendering them
294306
// so that they'll end up rendering to the correct on-screen position.
295307
element_entity.SetTransformation(
296-
Matrix::MakeTranslation(Vector3(-position)) *
308+
Matrix::MakeTranslation(Vector3(-global_pass_position)) *
297309
element_entity.GetTransformation());
298310
}
299311
}
@@ -313,10 +325,18 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
313325
if (!subpass->backdrop_filter_proc_.has_value() &&
314326
subpass->delegate_->CanCollapseIntoParentPass(subpass)) {
315327
// Directly render into the parent target and move on.
316-
if (!subpass->OnRender(renderer, root_pass_size,
317-
pass_context.GetPassTarget(), position, position,
318-
pass_depth, stencil_coverage_stack, stencil_depth_,
319-
nullptr, pass_context.GetRenderPass(pass_depth))) {
328+
if (!subpass->OnRender(
329+
renderer, // renderer
330+
root_pass_size, // root_pass_size
331+
pass_context.GetPassTarget(), // pass_target
332+
global_pass_position, // global_pass_position
333+
Point(), // local_pass_position
334+
pass_depth, // pass_depth
335+
stencil_coverage_stack, // stencil_coverage_stack
336+
stencil_depth_, // stencil_depth_floor
337+
nullptr, // backdrop_filter_contents
338+
pass_context.GetRenderPass(pass_depth) // collapsed_parent_pass
339+
)) {
320340
return EntityPass::EntityResult::Failure();
321341
}
322342
return EntityPass::EntityResult::Skip();
@@ -340,14 +360,15 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
340360
auto subpass_coverage =
341361
GetSubpassCoverage(*subpass, Rect::MakeSize(root_pass_size));
342362
if (subpass->cover_whole_screen_) {
343-
subpass_coverage = Rect(position, Size(pass_context.GetPassTarget()
344-
.GetRenderTarget()
345-
.GetRenderTargetSize()));
363+
subpass_coverage =
364+
Rect(global_pass_position, Size(pass_context.GetPassTarget()
365+
.GetRenderTarget()
366+
.GetRenderTargetSize()));
346367
}
347368
if (backdrop_filter_contents) {
348369
auto backdrop_coverage = backdrop_filter_contents->GetCoverage(Entity{});
349370
if (backdrop_coverage.has_value()) {
350-
backdrop_coverage->origin += position;
371+
backdrop_coverage->origin += global_pass_position;
351372

352373
subpass_coverage =
353374
subpass_coverage.has_value()
@@ -379,7 +400,8 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
379400
auto offscreen_texture_contents =
380401
subpass->delegate_->CreateContentsForSubpassTarget(
381402
subpass_texture,
382-
Matrix::MakeTranslation(Vector3{-position}) * subpass->xformation_);
403+
Matrix::MakeTranslation(Vector3{-global_pass_position}) *
404+
subpass->xformation_);
383405

384406
if (!offscreen_texture_contents) {
385407
// This is an error because the subpass delegate said the pass couldn't
@@ -395,18 +417,25 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
395417

396418
// Stencil textures aren't shared between EntityPasses (as much of the
397419
// time they are transient).
398-
if (!subpass->OnRender(renderer, root_pass_size, subpass_target,
399-
subpass_coverage->origin, position, ++pass_depth,
400-
stencil_coverage_stack, subpass->stencil_depth_,
401-
backdrop_filter_contents)) {
420+
if (!subpass->OnRender(renderer, // renderer
421+
root_pass_size, // root_pass_size
422+
subpass_target, // pass_target
423+
subpass_coverage->origin, // global_pass_position
424+
subpass_coverage->origin -
425+
global_pass_position, // local_pass_position
426+
++pass_depth, // pass_depth
427+
stencil_coverage_stack, // stencil_coverage_stack
428+
subpass->stencil_depth_, // stencil_depth_floor
429+
backdrop_filter_contents // backdrop_filter_contents
430+
)) {
402431
return EntityPass::EntityResult::Failure();
403432
}
404433

405434
element_entity.SetContents(std::move(offscreen_texture_contents));
406435
element_entity.SetStencilDepth(subpass->stencil_depth_);
407436
element_entity.SetBlendMode(subpass->blend_mode_);
408-
element_entity.SetTransformation(
409-
Matrix::MakeTranslation(Vector3(subpass_coverage->origin - position)));
437+
element_entity.SetTransformation(Matrix::MakeTranslation(
438+
Vector3(subpass_coverage->origin - global_pass_position)));
410439
} else {
411440
FML_UNREACHABLE();
412441
}
@@ -417,8 +446,8 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
417446
bool EntityPass::OnRender(ContentContext& renderer,
418447
ISize root_pass_size,
419448
EntityPassTarget& pass_target,
420-
Point position,
421-
Point parent_position,
449+
Point global_pass_position,
450+
Point local_pass_position,
422451
uint32_t pass_depth,
423452
StencilCoverageStack& stencil_coverage_stack,
424453
size_t stencil_depth_floor,
@@ -437,7 +466,7 @@ bool EntityPass::OnRender(ContentContext& renderer,
437466

438467
auto render_element = [&stencil_depth_floor, &pass_context, &pass_depth,
439468
&renderer, &stencil_coverage_stack,
440-
&position](Entity& element_entity) {
469+
&global_pass_position](Entity& element_entity) {
441470
auto result = pass_context.GetRenderPass(pass_depth);
442471

443472
if (!result.pass) {
@@ -469,7 +498,7 @@ bool EntityPass::OnRender(ContentContext& renderer,
469498
if (current_stencil_coverage.has_value()) {
470499
// Entity transforms are relative to the current pass position, so we need
471500
// to check stencil coverage in the same space.
472-
current_stencil_coverage->origin -= position;
501+
current_stencil_coverage->origin -= global_pass_position;
473502
}
474503

475504
if (!element_entity.ShouldRender(current_stencil_coverage)) {
@@ -479,7 +508,7 @@ bool EntityPass::OnRender(ContentContext& renderer,
479508
auto stencil_coverage =
480509
element_entity.GetStencilCoverage(current_stencil_coverage);
481510
if (stencil_coverage.coverage.has_value()) {
482-
stencil_coverage.coverage->origin += position;
511+
stencil_coverage.coverage->origin += global_pass_position;
483512
}
484513

485514
switch (stencil_coverage.type) {
@@ -517,7 +546,7 @@ bool EntityPass::OnRender(ContentContext& renderer,
517546
: std::nullopt;
518547
if (restore_coverage.has_value()) {
519548
// Make the coverage rectangle relative to the current pass.
520-
restore_coverage->origin -= position;
549+
restore_coverage->origin -= global_pass_position;
521550
}
522551
stencil_coverage_stack.resize(restoration_depth + 1);
523552

@@ -549,16 +578,22 @@ bool EntityPass::OnRender(ContentContext& renderer,
549578
Entity backdrop_entity;
550579
backdrop_entity.SetContents(std::move(backdrop_filter_contents));
551580
backdrop_entity.SetTransformation(
552-
Matrix::MakeTranslation(Vector3(parent_position - position)));
581+
Matrix::MakeTranslation(Vector3(local_pass_position)));
553582
backdrop_entity.SetStencilDepth(stencil_depth_floor);
554583

555584
render_element(backdrop_entity);
556585
}
557586

558587
for (const auto& element : elements_) {
559-
EntityResult result = GetEntityForElement(
560-
element, renderer, pass_context, root_pass_size, position, pass_depth,
561-
stencil_coverage_stack, stencil_depth_floor);
588+
EntityResult result =
589+
GetEntityForElement(element, // element
590+
renderer, // renderer
591+
pass_context, // pass_context
592+
root_pass_size, // root_pass_size
593+
global_pass_position, // global_pass_position
594+
pass_depth, // pass_depth
595+
stencil_coverage_stack, // stencil_coverage_stack
596+
stencil_depth_floor); // stencil_depth_floor
562597

563598
switch (result.status) {
564599
case EntityResult::kSuccess:

impeller/entity/entity_pass.h

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,17 @@ class ContentContext;
2525

2626
class EntityPass {
2727
public:
28+
/// Elements are renderable items in the `EntityPass`. Each can either be an
29+
/// `Entity` or a child `EntityPass`.
30+
///
31+
/// When the element is a child `EntityPass`, it may be rendered to an
32+
/// offscreen texture and converted into an `Entity` that draws the texture
33+
/// into the current pass, or its children may be collapsed into the current
34+
///
35+
/// `EntityPass`. Elements are converted to Entities in
36+
/// `GetEntityForElement()`.
2837
using Element = std::variant<Entity, std::unique_ptr<EntityPass>>;
38+
2939
using BackdropFilterProc = std::function<std::shared_ptr<FilterContents>(
3040
FilterInput::Ref,
3141
const Matrix& effect_transform,
@@ -104,7 +114,7 @@ class EntityPass {
104114
/// error while resolving the Entity.
105115
Status status = kFailure;
106116

107-
static EntityResult Success(Entity e) { return {e, kSuccess}; }
117+
static EntityResult Success(const Entity& e) { return {e, kSuccess}; }
108118
static EntityResult Failure() { return {{}, kFailure}; }
109119
static EntityResult Skip() { return {{}, kSkip}; }
110120
};
@@ -113,23 +123,80 @@ class EntityPass {
113123
ContentContext& renderer,
114124
InlinePassContext& pass_context,
115125
ISize root_pass_size,
116-
Point position,
126+
Point global_pass_position,
117127
uint32_t pass_depth,
118128
StencilCoverageStack& stencil_coverage_stack,
119129
size_t stencil_depth_floor) const;
120130

131+
/// @brief OnRender is the internal command recording routine for
132+
/// `EntityPass`. Its job is to walk through each `Element` which
133+
/// was appended to the scene (either an `Entity` via `AddEntity()`
134+
/// or a child `EntityPass` via `AddSubpass()`) and render them to
135+
/// the given `pass_target`.
136+
/// @param[in] renderer The Contents context, which manages
137+
/// pipeline state.
138+
/// @param[in] root_pass_size The size of the texture being
139+
/// rendered into at the root of the
140+
/// `EntityPass` tree. This is the size
141+
/// of the `RenderTarget` color
142+
/// attachment passed to the public
143+
/// `EntityPass::Render` method.
144+
/// @param[out] pass_target Stores the render target that should
145+
/// be used for rendering.
146+
/// @param[in] global_pass_position The position that this `EntityPass`
147+
/// will be drawn to the parent pass
148+
/// relative to the root pass origin.
149+
/// Used for offsetting drawn `Element`s,
150+
/// whose origins are all in root
151+
/// pass/screen space,
152+
/// @param[in] local_pass_position The position that this `EntityPass`
153+
/// will be drawn to the parent pass
154+
/// relative to the parent pass origin.
155+
/// Used for positioning backdrop
156+
/// filters.
157+
/// @param[in] pass_depth The tree depth of the `EntityPass` at
158+
/// render time. Only used for labeling
159+
/// and debugging purposes. This can vary
160+
/// depending on whether passes are
161+
/// collapsed or not.
162+
/// @param[in] stencil_coverage_stack A global stack of coverage rectangles
163+
/// for the stencil buffer at each depth.
164+
/// Higher depths are more restrictive.
165+
/// Used to cull Elements that we
166+
/// know won't result in a visible
167+
/// change.
168+
/// @param[in] stencil_depth_floor The stencil depth that a value of
169+
/// zero corresponds to in the given
170+
/// `pass_target` stencil buffer.
171+
/// When new `pass_target`s are created
172+
/// for subpasses, their stencils are
173+
/// initialized at zero, and so this
174+
/// value is used to offset Entity clip
175+
/// depths to match the stencil.
176+
/// @param[in] backdrop_filter_contents Optional. Is supplied, this contents
177+
/// is rendered prior to anything else in
178+
/// the `EntityPass`, offset by the
179+
/// `local_pass_position`.
180+
/// @param[in] collapsed_parent_pass Optional. If supplied, this
181+
/// `InlinePassContext` state is used to
182+
/// begin rendering elements instead of
183+
/// creating a new `RenderPass`. This
184+
/// "collapses" the Elements into the
185+
/// parent pass.
121186
bool OnRender(ContentContext& renderer,
122187
ISize root_pass_size,
123-
EntityPassTarget& render_target,
124-
Point position,
125-
Point parent_position,
188+
EntityPassTarget& pass_target,
189+
Point global_pass_position,
190+
Point local_pass_position,
126191
uint32_t pass_depth,
127192
StencilCoverageStack& stencil_coverage_stack,
128193
size_t stencil_depth_floor = 0,
129194
std::shared_ptr<Contents> backdrop_filter_contents = nullptr,
130195
std::optional<InlinePassContext::RenderPassResult>
131196
collapsed_parent_pass = std::nullopt) const;
132197

198+
/// The list of renderable items in the scene. Each of these items is
199+
/// evaluated and recorded to an `EntityPassTarget` by the `OnRender` method.
133200
std::vector<Element> elements_;
134201

135202
EntityPass* superpass_ = nullptr;

0 commit comments

Comments
 (0)