| Flutter Impeller |

inline_pass_context.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/entity/inline_pass_context.h"
6
7 #include <utility>
8
9 #include "impeller/base/validation.h"
10 #include "impeller/core/formats.h"
11 #include "impeller/core/texture_descriptor.h"
12 #include "impeller/entity/entity_pass_target.h"
13 #include "impeller/renderer/command_buffer.h"
14
15 namespace impeller {
16
17 InlinePassContext::InlinePassContext(
18 std::shared_ptr<Context> context,
19 EntityPassTarget& pass_target,
20 uint32_t pass_texture_reads,
21 uint32_t entity_count,
22 std::optional<RenderPassResult> collapsed_parent_pass)
23 : context_(std::move(context)),
24 pass_target_(pass_target),
25 entity_count_(entity_count),
26 is_collapsed_(collapsed_parent_pass.has_value()) {
27 if (collapsed_parent_pass.has_value()) {
28 pass_ = collapsed_parent_pass.value().pass;
29 }
30 }
31
32 InlinePassContext::~InlinePassContext() {
33 if (!is_collapsed_) {
34 EndPass();
35 }
36 }
37
38 bool InlinePassContext::IsValid() const {
39 return pass_target_.IsValid();
40 }
41
42 bool InlinePassContext::IsActive() const {
43 return pass_ != nullptr;
44 }
45
46 std::shared_ptr<Texture> InlinePassContext::GetTexture() {
47 if (!IsValid()) {
48 return nullptr;
49 }
50 return pass_target_.GetRenderTarget().GetRenderTargetTexture();
51 }
52
53 bool InlinePassContext::EndPass() {
54 if (!IsActive()) {
55 return true;
56 }
57
58 if (command_buffer_) {
59 if (!command_buffer_->EncodeAndSubmit(pass_)) {
60 VALIDATION_LOG
61 << "Failed to encode and submit command buffer while ending "
62 "render pass.";
63 return false;
64 }
65 }
66
67 pass_ = nullptr;
68 command_buffer_ = nullptr;
69
70 return true;
71 }
72
73 EntityPassTarget& InlinePassContext::GetPassTarget() const {
74 return pass_target_;
75 }
76
77 InlinePassContext::RenderPassResult InlinePassContext::GetRenderPass(
78 uint32_t pass_depth) {
79 if (IsActive()) {
80 return {.pass = pass_};
81 }
82
83 /// Create a new render pass if one isn't active. This path will run the first
84 /// time this method is called, but it'll also run if the pass has been
85 /// previously ended via `EndPass`.
86
87 command_buffer_ = context_->CreateCommandBuffer();
88 if (!command_buffer_) {
89 VALIDATION_LOG << "Could not create command buffer.";
90 return {};
91 }
92
93 if (pass_target_.GetRenderTarget().GetColorAttachments().empty()) {
94 VALIDATION_LOG << "Color attachment unexpectedly missing from the "
95 "EntityPass render target.";
96 return {};
97 }
98
99 command_buffer_->SetLabel(
100 "EntityPass Command Buffer: Depth=" + std::to_string(pass_depth) +
101 " Count=" + std::to_string(pass_count_));
102
103 RenderPassResult result;
104 {
105 // If the pass target has a resolve texture, then we're using MSAA.
106 bool is_msaa = pass_target_.GetRenderTarget()
107 .GetColorAttachments()
108 .find(0)
109 ->second.resolve_texture != nullptr;
110 if (pass_count_ > 0 && is_msaa) {
111 result.backdrop_texture =
112 pass_target_.Flip(*context_->GetResourceAllocator());
113 if (!result.backdrop_texture) {
114 VALIDATION_LOG << "Could not flip the EntityPass render target.";
115 }
116 }
117 }
118
119 // Find the color attachment a second time, since the target may have just
120 // flipped.
121 auto color0 =
122 pass_target_.GetRenderTarget().GetColorAttachments().find(0)->second;
123 bool is_msaa = color0.resolve_texture != nullptr;
124
125 if (pass_count_ > 0) {
126 // When MSAA is being used, we end up overriding the entire backdrop by
127 // drawing the previous pass texture, and so we don't have to clear it and
128 // can use kDontCare.
129 color0.load_action = is_msaa ? LoadAction::kDontCare : LoadAction::kLoad;
130 } else {
131 color0.load_action = LoadAction::kClear;
132 }
133
134 color0.store_action =
135 is_msaa ? StoreAction::kMultisampleResolve : StoreAction::kStore;
136
137 auto stencil = pass_target_.GetRenderTarget().GetStencilAttachment();
138 if (!stencil.has_value()) {
139 VALIDATION_LOG << "Stencil attachment unexpectedly missing from the "
140 "EntityPass render target.";
141 return {};
142 }
143
144 stencil->load_action = LoadAction::kClear;
145 stencil->store_action = StoreAction::kDontCare;
146 pass_target_.target_.SetStencilAttachment(stencil.value());
147 pass_target_.target_.SetColorAttachment(color0, 0);
148
149 pass_ = command_buffer_->CreateRenderPass(pass_target_.GetRenderTarget());
150 if (!pass_) {
151 VALIDATION_LOG << "Could not create render pass.";
152 return {};
153 }
154 // Commands are fairly large (500B) objects, so re-allocation of the command
155 // buffer while encoding can add a surprising amount of overhead. We make a
156 // conservative npot estimate to avoid this case.
157 pass_->ReserveCommands(Allocation::NextPowerOfTwoSize(entity_count_));
158 pass_->SetLabel(
159 "EntityPass Render Pass: Depth=" + std::to_string(pass_depth) +
160 " Count=" + std::to_string(pass_count_));
161
162 result.pass = pass_;
163
164 if (!context_->GetCapabilities()->SupportsReadFromResolve() &&
165 result.backdrop_texture ==
166 result.pass->GetRenderTarget().GetRenderTargetTexture()) {
167 VALIDATION_LOG << "EntityPass backdrop restore configuration is not valid "
168 "for the current graphics backend.";
169 }
170
171 ++pass_count_;
172 return result;
173 }
174
175 uint32_t InlinePassContext::GetPassCount() const {
176 return pass_count_;
177 }
178
179 } // namespace impeller
impeller::StoreAction::kMultisampleResolve
@ kMultisampleResolve
impeller::LoadAction::kLoad
@ kLoad
impeller::EntityPassTarget::IsValid
bool IsValid() const
Definition: entity_pass_target.cc:72
impeller::Allocation::NextPowerOfTwoSize
static uint32_t NextPowerOfTwoSize(uint32_t x)
Definition: allocation.cc:41
impeller::RenderTarget::SetColorAttachment
RenderTarget & SetColorAttachment(const ColorAttachment &attachment, size_t index)
Definition: render_target.cc:180
texture_descriptor.h
formats.h
impeller::StoreAction::kDontCare
@ kDontCare
impeller::EntityPassTarget
Definition: entity_pass_target.h:15
impeller::RenderTarget::GetColorAttachments
const std::map< size_t, ColorAttachment > & GetColorAttachments() const
Definition: render_target.cc:209
impeller::InlinePassContext::RenderPassResult
Definition: inline_pass_context.h:19
validation.h
impeller::InlinePassContext::RenderPassResult::backdrop_texture
std::shared_ptr< Texture > backdrop_texture
Definition: inline_pass_context.h:21
impeller::InlinePassContext::GetPassCount
uint32_t GetPassCount() const
Definition: inline_pass_context.cc:175
impeller::LoadAction::kClear
@ kClear
impeller::RenderTarget::GetRenderTargetTexture
std::shared_ptr< Texture > GetRenderTargetTexture() const
Definition: render_target.cc:155
impeller::InlinePassContext::IsActive
bool IsActive() const
Definition: inline_pass_context.cc:42
impeller::InlinePassContext::GetRenderPass
RenderPassResult GetRenderPass(uint32_t pass_depth)
Definition: inline_pass_context.cc:77
impeller::InlinePassContext::GetTexture
std::shared_ptr< Texture > GetTexture()
Definition: inline_pass_context.cc:46
impeller::StoreAction::kStore
@ kStore
impeller::InlinePassContext::EndPass
bool EndPass()
Definition: inline_pass_context.cc:53
entity_pass_target.h
impeller::InlinePassContext::IsValid
bool IsValid() const
Definition: inline_pass_context.cc:38
impeller::InlinePassContext::InlinePassContext
InlinePassContext(std::shared_ptr< Context > context, EntityPassTarget &pass_target, uint32_t pass_texture_reads, uint32_t entity_count, std::optional< RenderPassResult > collapsed_parent_pass=std::nullopt)
Definition: inline_pass_context.cc:17
impeller::InlinePassContext::GetPassTarget
EntityPassTarget & GetPassTarget() const
Definition: inline_pass_context.cc:73
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:67
command_buffer.h
impeller::RenderTarget::SetStencilAttachment
RenderTarget & SetStencilAttachment(std::optional< StencilAttachment > attachment)
Definition: render_target.cc:199
std
Definition: comparable.h:95
impeller::LoadAction::kDontCare
@ kDontCare
impeller::InlinePassContext::~InlinePassContext
~InlinePassContext()
Definition: inline_pass_context.cc:32
impeller::RenderTarget::GetStencilAttachment
const std::optional< StencilAttachment > & GetStencilAttachment() const
Definition: render_target.cc:218
impeller::InlinePassContext::RenderPassResult::pass
std::shared_ptr< RenderPass > pass
Definition: inline_pass_context.h:20
impeller
Definition: aiks_context.cc:10
impeller::EntityPassTarget::GetRenderTarget
const RenderTarget & GetRenderTarget() const
Definition: entity_pass_target.cc:68
inline_pass_context.h
impeller::EntityPassTarget::Flip
std::shared_ptr< Texture > Flip(Allocator &allocator)
Flips the backdrop and returns a readable texture that can be bound/sampled to restore the previous p...
Definition: entity_pass_target.cc:20