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 
6 
7 #include <utility>
8 
9 #include "flutter/fml/status.h"
12 #include "impeller/core/formats.h"
17 
18 namespace impeller {
19 
21  const ContentContext& renderer,
22  EntityPassTarget& pass_target,
23  uint32_t pass_texture_reads,
24  uint32_t entity_count,
25  std::optional<RenderPassResult> collapsed_parent_pass)
26  : renderer_(renderer),
27  pass_target_(pass_target),
28  entity_count_(entity_count),
29  is_collapsed_(collapsed_parent_pass.has_value()) {
30  if (collapsed_parent_pass.has_value()) {
31  pass_ = collapsed_parent_pass.value().pass;
32  }
33 }
34 
36  if (!is_collapsed_) {
37  EndPass();
38  }
39 }
40 
42  return pass_target_.IsValid();
43 }
44 
46  return pass_ != nullptr;
47 }
48 
49 std::shared_ptr<Texture> InlinePassContext::GetTexture() {
50  if (!IsValid()) {
51  return nullptr;
52  }
53  return pass_target_.GetRenderTarget().GetRenderTargetTexture();
54 }
55 
57  if (!IsActive()) {
58  return true;
59  }
60  FML_DCHECK(command_buffer_);
61 
62  if (!pass_->EncodeCommands()) {
63  VALIDATION_LOG << "Failed to encode and submit command buffer while ending "
64  "render pass.";
65  return false;
66  }
67 
68  const std::shared_ptr<Texture>& target_texture =
70  if (target_texture->GetMipCount() > 1) {
71  fml::Status mip_status = AddMipmapGeneration(
72  command_buffer_, renderer_.GetContext(), target_texture);
73  if (!mip_status.ok()) {
74  return false;
75  }
76  }
77  if (!renderer_.GetContext()
78  ->GetCommandQueue()
79  ->Submit({std::move(command_buffer_)})
80  .ok()) {
81  return false;
82  }
83 
84  pass_ = nullptr;
85  command_buffer_ = nullptr;
86 
87  return true;
88 }
89 
91  return pass_target_;
92 }
93 
95  uint32_t pass_depth) {
96  if (IsActive()) {
97  return {.pass = pass_};
98  }
99 
100  /// Create a new render pass if one isn't active. This path will run the first
101  /// time this method is called, but it'll also run if the pass has been
102  /// previously ended via `EndPass`.
103 
104  command_buffer_ = renderer_.GetContext()->CreateCommandBuffer();
105  if (!command_buffer_) {
106  VALIDATION_LOG << "Could not create command buffer.";
107  return {};
108  }
109 
110  if (pass_target_.GetRenderTarget().GetColorAttachments().empty()) {
111  VALIDATION_LOG << "Color attachment unexpectedly missing from the "
112  "EntityPass render target.";
113  return {};
114  }
115 
116  command_buffer_->SetLabel(
117  "EntityPass Command Buffer: Depth=" + std::to_string(pass_depth) +
118  " Count=" + std::to_string(pass_count_));
119 
120  RenderPassResult result;
121  {
122  // If the pass target has a resolve texture, then we're using MSAA.
123  bool is_msaa = pass_target_.GetRenderTarget()
125  .find(0)
126  ->second.resolve_texture != nullptr;
127  if (pass_count_ > 0 && is_msaa) {
128  result.backdrop_texture =
129  pass_target_.Flip(*renderer_.GetContext()->GetResourceAllocator());
130  if (!result.backdrop_texture) {
131  VALIDATION_LOG << "Could not flip the EntityPass render target.";
132  }
133  }
134  }
135 
136  // Find the color attachment a second time, since the target may have just
137  // flipped.
138  auto color0 =
139  pass_target_.GetRenderTarget().GetColorAttachments().find(0)->second;
140  bool is_msaa = color0.resolve_texture != nullptr;
141 
142  if (pass_count_ > 0) {
143  // When MSAA is being used, we end up overriding the entire backdrop by
144  // drawing the previous pass texture, and so we don't have to clear it and
145  // can use kDontCare.
146  color0.load_action = is_msaa ? LoadAction::kDontCare : LoadAction::kLoad;
147  } else {
148  color0.load_action = LoadAction::kClear;
149  }
150 
151  color0.store_action =
153 
155  auto depth = pass_target_.GetRenderTarget().GetDepthAttachment();
156  if (!depth.has_value()) {
157  VALIDATION_LOG << "Depth attachment unexpectedly missing from the "
158  "EntityPass render target.";
159  return {};
160  }
161  depth->load_action = LoadAction::kClear;
162  depth->store_action = StoreAction::kDontCare;
163  pass_target_.target_.SetDepthAttachment(depth.value());
164  }
165 
166  auto depth = pass_target_.GetRenderTarget().GetDepthAttachment();
167  auto stencil = pass_target_.GetRenderTarget().GetStencilAttachment();
168  if (!depth.has_value() || !stencil.has_value()) {
169  VALIDATION_LOG << "Stencil/Depth attachment unexpectedly missing from the "
170  "EntityPass render target.";
171  return {};
172  }
173  stencil->load_action = LoadAction::kClear;
174  stencil->store_action = StoreAction::kDontCare;
175  depth->load_action = LoadAction::kClear;
176  depth->store_action = StoreAction::kDontCare;
177  pass_target_.target_.SetDepthAttachment(depth);
178  pass_target_.target_.SetStencilAttachment(stencil.value());
179  pass_target_.target_.SetColorAttachment(color0, 0);
180 
181  pass_ = command_buffer_->CreateRenderPass(pass_target_.GetRenderTarget());
182  if (!pass_) {
183  VALIDATION_LOG << "Could not create render pass.";
184  return {};
185  }
186  // Commands are fairly large (500B) objects, so re-allocation of the command
187  // buffer while encoding can add a surprising amount of overhead. We make a
188  // conservative npot estimate to avoid this case.
189  pass_->ReserveCommands(Allocation::NextPowerOfTwoSize(entity_count_));
190  pass_->SetLabel(
191  "EntityPass Render Pass: Depth=" + std::to_string(pass_depth) +
192  " Count=" + std::to_string(pass_count_));
193 
194  result.pass = pass_;
195  result.just_created = true;
196 
197  if (!renderer_.GetContext()->GetCapabilities()->SupportsReadFromResolve() &&
198  result.backdrop_texture ==
199  result.pass->GetRenderTarget().GetRenderTargetTexture()) {
200  VALIDATION_LOG << "EntityPass backdrop restore configuration is not valid "
201  "for the current graphics backend.";
202  }
203 
204  ++pass_count_;
205  return result;
206 }
207 
209  return pass_count_;
210 }
211 
212 } // namespace impeller
impeller::StoreAction::kMultisampleResolve
@ kMultisampleResolve
impeller::LoadAction::kLoad
@ kLoad
impeller::AddMipmapGeneration
fml::Status AddMipmapGeneration(const std::shared_ptr< CommandBuffer > &command_buffer, const std::shared_ptr< Context > &context, const std::shared_ptr< Texture > &texture)
Adds a blit command to the render pass.
Definition: texture_mipmap.cc:11
impeller::EntityPassTarget::IsValid
bool IsValid() const
Definition: entity_pass_target.cc:72
allocation.h
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:169
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:198
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:22
impeller::ContentContext::kEnableStencilThenCover
static constexpr bool kEnableStencilThenCover
Definition: content_context.h:411
impeller::InlinePassContext::GetPassCount
uint32_t GetPassCount() const
Definition: inline_pass_context.cc:208
impeller::LoadAction::kClear
@ kClear
impeller::RenderTarget::GetDepthAttachment
const std::optional< DepthAttachment > & GetDepthAttachment() const
Definition: render_target.cc:203
impeller::RenderTarget::GetRenderTargetTexture
std::shared_ptr< Texture > GetRenderTargetTexture() const
Definition: render_target.cc:144
impeller::InlinePassContext::IsActive
bool IsActive() const
Definition: inline_pass_context.cc:45
impeller::ContentContext::GetContext
std::shared_ptr< Context > GetContext() const
Definition: content_context.cc:564
impeller::InlinePassContext::GetRenderPass
RenderPassResult GetRenderPass(uint32_t pass_depth)
Definition: inline_pass_context.cc:94
texture_mipmap.h
impeller::InlinePassContext::RenderPassResult::just_created
bool just_created
Definition: inline_pass_context.h:20
impeller::InlinePassContext::GetTexture
std::shared_ptr< Texture > GetTexture()
Definition: inline_pass_context.cc:49
impeller::StoreAction::kStore
@ kStore
impeller::InlinePassContext::EndPass
bool EndPass()
Definition: inline_pass_context.cc:56
entity_pass_target.h
impeller::InlinePassContext::InlinePassContext
InlinePassContext(const ContentContext &renderer, 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:20
impeller::InlinePassContext::IsValid
bool IsValid() const
Definition: inline_pass_context.cc:41
impeller::InlinePassContext::GetPassTarget
EntityPassTarget & GetPassTarget() const
Definition: inline_pass_context.cc:90
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:73
command_buffer.h
content_context.h
impeller::RenderTarget::SetStencilAttachment
RenderTarget & SetStencilAttachment(std::optional< StencilAttachment > attachment)
Definition: render_target.cc:188
impeller::LoadAction::kDontCare
@ kDontCare
impeller::InlinePassContext::~InlinePassContext
~InlinePassContext()
Definition: inline_pass_context.cc:35
impeller::RenderTarget::GetStencilAttachment
const std::optional< StencilAttachment > & GetStencilAttachment() const
Definition: render_target.cc:207
impeller::InlinePassContext::RenderPassResult::pass
std::shared_ptr< RenderPass > pass
Definition: inline_pass_context.h:21
impeller::RenderTarget::SetDepthAttachment
RenderTarget & SetDepthAttachment(std::optional< DepthAttachment > attachment)
Definition: render_target.cc:178
impeller
Definition: aiks_blur_unittests.cc:20
impeller::EntityPassTarget::GetRenderTarget
const RenderTarget & GetRenderTarget() const
Definition: entity_pass_target.cc:68
impeller::ContentContext
Definition: content_context.h:392
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