Flutter Impeller
impeller::RuntimeEffectContents Class Referencefinal

#include <runtime_effect_contents.h>

Inheritance diagram for impeller::RuntimeEffectContents:
impeller::ColorSourceContents impeller::Contents

Classes

struct  TextureInput
 

Public Member Functions

void SetRuntimeStage (std::shared_ptr< RuntimeStage > runtime_stage)
 
void SetUniformData (std::shared_ptr< std::vector< uint8_t >> uniform_data)
 
void SetTextureInputs (std::vector< TextureInput > texture_inputs)
 
bool CanInheritOpacity (const Entity &entity) const override
 Whether or not this contents can accept the opacity peephole optimization. More...
 
bool Render (const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
 
- Public Member Functions inherited from impeller::ColorSourceContents
 ColorSourceContents ()
 
 ~ColorSourceContents () override
 
void SetGeometry (std::shared_ptr< Geometry > geometry)
 Set the geometry that this contents will use to render. More...
 
const std::shared_ptr< Geometry > & GetGeometry () const
 Get the geometry that this contents will use to render. More...
 
void SetEffectTransform (Matrix matrix)
 Set the effect transform for this color source. More...
 
const MatrixGetInverseEffectTransform () const
 Set the inverted effect transform for this color source. More...
 
void SetOpacityFactor (Scalar opacity)
 Set the opacity factor for this color source. More...
 
Scalar GetOpacityFactor () const
 Get the opacity factor for this color source. More...
 
virtual bool IsSolidColor () const
 
std::optional< RectGetCoverage (const Entity &entity) const override
 Get the area of the render pass that will be affected when this contents is rendered. More...
 
void SetInheritedOpacity (Scalar opacity) override
 Inherit the provided opacity. More...
 
- Public Member Functions inherited from impeller::Contents
 Contents ()
 
virtual ~Contents ()
 
virtual void PopulateGlyphAtlas (const std::shared_ptr< LazyGlyphAtlas > &lazy_glyph_atlas, Scalar scale)
 Add any text data to the specified lazy atlas. The scale parameter must be used again later when drawing the text. More...
 
void SetCoverageHint (std::optional< Rect > coverage_hint)
 Hint that specifies the coverage area of this Contents that will actually be used during rendering. This is for optimization purposes only and can not be relied on as a clip. May optionally affect the result of GetCoverage(). More...
 
const std::optional< Rect > & GetCoverageHint () const
 
virtual bool IsOpaque () const
 Whether this Contents only emits opaque source colors from the fragment stage. This value does not account for any entity properties (e.g. the blend mode), clips/visibility culling, or inherited opacity. More...
 
virtual ClipCoverage GetClipCoverage (const Entity &entity, const std::optional< Rect > &current_clip_coverage) const
 Given the current pass space bounding rectangle of the clip buffer, return the expected clip coverage after this draw call. This should only be implemented for contents that may write to the clip buffer. More...
 
virtual std::optional< SnapshotRenderToSnapshot (const ContentContext &renderer, const Entity &entity, std::optional< Rect > coverage_limit=std::nullopt, const std::optional< SamplerDescriptor > &sampler_descriptor=std::nullopt, bool msaa_enabled=true, const std::string &label="Snapshot") const
 Render this contents to a snapshot, respecting the entity's transform, path, clip depth, and blend mode. The result texture size is always the size of GetCoverage(entity). More...
 
virtual bool ShouldRender (const Entity &entity, const std::optional< Rect > clip_coverage) const
 
std::optional< SizeGetColorSourceSize () const
 Return the color source's intrinsic size, if available. More...
 
void SetColorSourceSize (Size size)
 
virtual std::optional< ColorAsBackgroundColor (const Entity &entity, ISize target_size) const
 Returns a color if this Contents will flood the given target_size with a color. This output color is the "Source" color that will be used for the Entity's blend operation. More...
 
virtual const FilterContentsAsFilter () const
 Cast to a filter. Returns nullptr if this Contents is not a filter. More...
 
virtual bool ApplyColorFilter (const ColorFilterProc &color_filter_proc)
 If possible, applies a color filter to this contents inputs on the CPU. More...
 

Additional Inherited Members

- Public Types inherited from impeller::Contents
using ColorFilterProc = std::function< Color(Color)>
 
using RenderProc = std::function< bool(const ContentContext &renderer, const Entity &entity, RenderPass &pass)>
 
using CoverageProc = std::function< std::optional< Rect >(const Entity &entity)>
 
- Static Public Member Functions inherited from impeller::Contents
static std::shared_ptr< ContentsMakeAnonymous (RenderProc render_proc, CoverageProc coverage_proc)
 

Detailed Description

Definition at line 17 of file runtime_effect_contents.h.

Member Function Documentation

◆ CanInheritOpacity()

bool impeller::RuntimeEffectContents::CanInheritOpacity ( const Entity entity) const
overridevirtual

Whether or not this contents can accept the opacity peephole optimization.

By default all contents return false. Contents are responsible for determining whether or not their own geometries intersect in a way that makes accepting opacity impossible. It is always safe to return false, especially if computing overlap would be computationally expensive.

Reimplemented from impeller::ColorSourceContents.

Definition at line 40 of file runtime_effect_contents.cc.

40  {
41  return false;
42 }

◆ Render()

bool impeller::RuntimeEffectContents::Render ( const ContentContext renderer,
const Entity entity,
RenderPass pass 
) const
overridevirtual

Get or register shader.

Resolve geometry.

Get or create runtime stage pipeline.

Vertex stage uniforms.

Fragment stage uniforms.

Implements impeller::Contents.

Definition at line 79 of file runtime_effect_contents.cc.

81  {
82  // TODO(jonahwilliams): FragmentProgram API is not fully wired up on Android.
83  // Disable until this is complete so that integration tests and benchmarks can
84  // run m3 applications.
85  if (renderer.GetContext()->GetBackendType() ==
87  FML_DLOG(WARNING)
88  << "Fragment programs not supported on Vulkan. Content dropped.";
89  return true;
90  }
91  auto context = renderer.GetContext();
92  auto library = context->GetShaderLibrary();
93 
94  //--------------------------------------------------------------------------
95  /// Get or register shader.
96  ///
97 
98  // TODO(113719): Register the shader function earlier.
99 
100  std::shared_ptr<const ShaderFunction> function = library->GetFunction(
101  runtime_stage_->GetEntrypoint(), ShaderStage::kFragment);
102 
103  if (function && runtime_stage_->IsDirty()) {
104  context->GetPipelineLibrary()->RemovePipelinesWithEntryPoint(function);
105  library->UnregisterFunction(runtime_stage_->GetEntrypoint(),
107 
108  function = nullptr;
109  }
110 
111  if (!function) {
112  std::promise<bool> promise;
113  auto future = promise.get_future();
114 
115  library->RegisterFunction(
116  runtime_stage_->GetEntrypoint(),
117  ToShaderStage(runtime_stage_->GetShaderStage()),
118  runtime_stage_->GetCodeMapping(),
119  fml::MakeCopyable([promise = std::move(promise)](bool result) mutable {
120  promise.set_value(result);
121  }));
122 
123  if (!future.get()) {
124  VALIDATION_LOG << "Failed to build runtime effect (entry point: "
125  << runtime_stage_->GetEntrypoint() << ")";
126  return false;
127  }
128 
129  function = library->GetFunction(runtime_stage_->GetEntrypoint(),
131  if (!function) {
133  << "Failed to fetch runtime effect function immediately after "
134  "registering it (entry point: "
135  << runtime_stage_->GetEntrypoint() << ")";
136  return false;
137  }
138 
139  runtime_stage_->SetClean();
140  }
141 
142  //--------------------------------------------------------------------------
143  /// Resolve geometry.
144  ///
145 
146  auto geometry_result =
147  GetGeometry()->GetPositionBuffer(renderer, entity, pass);
148 
149  //--------------------------------------------------------------------------
150  /// Get or create runtime stage pipeline.
151  ///
152 
153  const auto& caps = context->GetCapabilities();
154  const auto color_attachment_format = caps->GetDefaultColorFormat();
155  const auto stencil_attachment_format = caps->GetDefaultStencilFormat();
156 
157  using VS = RuntimeEffectVertexShader;
158  PipelineDescriptor desc;
159  desc.SetLabel("Runtime Stage");
160  desc.AddStageEntrypoint(
161  library->GetFunction(VS::kEntrypointName, ShaderStage::kVertex));
162  desc.AddStageEntrypoint(library->GetFunction(runtime_stage_->GetEntrypoint(),
164  auto vertex_descriptor = std::make_shared<VertexDescriptor>();
165  vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs,
166  VS::kInterleavedBufferLayout);
167  desc.SetVertexDescriptor(std::move(vertex_descriptor));
168  desc.SetColorAttachmentDescriptor(
169  0u, {.format = color_attachment_format, .blending_enabled = true});
170 
171  StencilAttachmentDescriptor stencil0;
172  stencil0.stencil_compare = CompareFunction::kEqual;
173  desc.SetStencilAttachmentDescriptors(stencil0);
174  desc.SetStencilPixelFormat(stencil_attachment_format);
175 
176  auto options = OptionsFromPassAndEntity(pass, entity);
177  if (geometry_result.prevent_overdraw) {
178  options.stencil_compare = CompareFunction::kEqual;
179  options.stencil_operation = StencilOperation::kIncrementClamp;
180  }
181  options.primitive_type = geometry_result.type;
182  options.ApplyToPipelineDescriptor(desc);
183 
184  auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
185  if (!pipeline) {
186  VALIDATION_LOG << "Failed to get or create runtime effect pipeline.";
187  return false;
188  }
189 
190  Command cmd;
191  DEBUG_COMMAND_INFO(cmd, "RuntimeEffectContents");
192  cmd.pipeline = pipeline;
193  cmd.stencil_reference = entity.GetClipDepth();
194  cmd.BindVertices(std::move(geometry_result.vertex_buffer));
195 
196  //--------------------------------------------------------------------------
197  /// Vertex stage uniforms.
198  ///
199 
200  VS::FrameInfo frame_info;
201  frame_info.mvp = geometry_result.transform;
202  VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info));
203 
204  //--------------------------------------------------------------------------
205  /// Fragment stage uniforms.
206  ///
207 
208  size_t minimum_sampler_index = 100000000;
209  size_t buffer_index = 0;
210  size_t buffer_offset = 0;
211  for (const auto& uniform : runtime_stage_->GetUniforms()) {
212  std::shared_ptr<ShaderMetadata> metadata = MakeShaderMetadata(uniform);
213 
214  switch (uniform.type) {
215  case kSampledImage: {
216  // Sampler uniforms are ordered in the IPLR according to their
217  // declaration and the uniform location reflects the correct offset to
218  // be mapped to - except that it may include all proceeding float
219  // uniforms. For example, a float sampler that comes after 4 float
220  // uniforms may have a location of 4. To convert to the actual offset we
221  // need to find the largest location assigned to a float uniform and
222  // then subtract this from all uniform locations. This is more or less
223  // the same operation we previously performed in the shader compiler.
224  minimum_sampler_index =
225  std::min(minimum_sampler_index, uniform.location);
226  break;
227  }
228  case kFloat: {
229  size_t alignment =
230  std::max(uniform.bit_width / 8, DefaultUniformAlignment());
231  auto buffer_view = pass.GetTransientsBuffer().Emplace(
232  uniform_data_->data() + buffer_offset, uniform.GetSize(),
233  alignment);
234 
235  ShaderUniformSlot uniform_slot;
236  uniform_slot.name = uniform.name.c_str();
237  uniform_slot.ext_res_0 = uniform.location;
238  cmd.BindResource(ShaderStage::kFragment, uniform_slot, metadata,
239  buffer_view);
240  buffer_index++;
241  buffer_offset += uniform.GetSize();
242  break;
243  }
244  case kBoolean:
245  case kSignedByte:
246  case kUnsignedByte:
247  case kSignedShort:
248  case kUnsignedShort:
249  case kSignedInt:
250  case kUnsignedInt:
251  case kSignedInt64:
252  case kUnsignedInt64:
253  case kHalfFloat:
254  case kDouble:
255  VALIDATION_LOG << "Unsupported uniform type for " << uniform.name
256  << ".";
257  return true;
258  }
259  }
260 
261  size_t sampler_index = 0;
262  for (const auto& uniform : runtime_stage_->GetUniforms()) {
263  std::shared_ptr<ShaderMetadata> metadata = MakeShaderMetadata(uniform);
264 
265  switch (uniform.type) {
266  case kSampledImage: {
267  FML_DCHECK(sampler_index < texture_inputs_.size());
268  auto& input = texture_inputs_[sampler_index];
269 
270  auto sampler =
271  context->GetSamplerLibrary()->GetSampler(input.sampler_descriptor);
272 
273  SampledImageSlot image_slot;
274  image_slot.name = uniform.name.c_str();
275  image_slot.texture_index = uniform.location - minimum_sampler_index;
276  cmd.BindResource(ShaderStage::kFragment, image_slot, *metadata,
277  input.texture, sampler);
278 
279  sampler_index++;
280  break;
281  }
282  default:
283  continue;
284  }
285  }
286 
287  pass.AddCommand(std::move(cmd));
288 
289  if (geometry_result.prevent_overdraw) {
290  auto restore = ClipRestoreContents();
291  restore.SetRestoreCoverage(GetCoverage(entity));
292  return restore.Render(renderer, entity, pass);
293  }
294  return true;
295 }

References impeller::RenderPass::AddCommand(), impeller::PipelineDescriptor::AddStageEntrypoint(), impeller::Command::BindResource(), impeller::Command::BindVertices(), DEBUG_COMMAND_INFO, impeller::DefaultUniformAlignment(), impeller::HostBuffer::Emplace(), impeller::HostBuffer::EmplaceUniform(), impeller::ShaderUniformSlot::ext_res_0, impeller::Entity::GetClipDepth(), impeller::ContentContext::GetContext(), impeller::ColorSourceContents::GetCoverage(), impeller::ColorSourceContents::GetGeometry(), impeller::RenderPass::GetTransientsBuffer(), impeller::kBoolean, impeller::kDouble, impeller::kEqual, impeller::kFloat, impeller::kFragment, impeller::kHalfFloat, impeller::kIncrementClamp, impeller::kSampledImage, impeller::kSignedByte, impeller::kSignedInt, impeller::kSignedInt64, impeller::kSignedShort, impeller::kUnsignedByte, impeller::kUnsignedInt, impeller::kUnsignedInt64, impeller::kUnsignedShort, impeller::kVertex, impeller::Context::kVulkan, impeller::MakeShaderMetadata(), impeller::ShaderUniformSlot::name, impeller::SampledImageSlot::name, impeller::OptionsFromPassAndEntity(), impeller::Command::pipeline, impeller::PipelineDescriptor::SetColorAttachmentDescriptor(), impeller::PipelineDescriptor::SetLabel(), impeller::PipelineDescriptor::SetStencilAttachmentDescriptors(), impeller::PipelineDescriptor::SetStencilPixelFormat(), impeller::PipelineDescriptor::SetVertexDescriptor(), impeller::StencilAttachmentDescriptor::stencil_compare, impeller::Command::stencil_reference, impeller::SampledImageSlot::texture_index, impeller::ToShaderStage(), and VALIDATION_LOG.

◆ SetRuntimeStage()

void impeller::RuntimeEffectContents::SetRuntimeStage ( std::shared_ptr< RuntimeStage runtime_stage)

Definition at line 25 of file runtime_effect_contents.cc.

26  {
27  runtime_stage_ = std::move(runtime_stage);
28 }

◆ SetTextureInputs()

void impeller::RuntimeEffectContents::SetTextureInputs ( std::vector< TextureInput texture_inputs)

Definition at line 35 of file runtime_effect_contents.cc.

36  {
37  texture_inputs_ = std::move(texture_inputs);
38 }

◆ SetUniformData()

void impeller::RuntimeEffectContents::SetUniformData ( std::shared_ptr< std::vector< uint8_t >>  uniform_data)

Definition at line 30 of file runtime_effect_contents.cc.

31  {
32  uniform_data_ = std::move(uniform_data);
33 }

The documentation for this class was generated from the following files:
impeller::kBoolean
@ kBoolean
Definition: runtime_types.h:22
impeller::kFloat
@ kFloat
Definition: runtime_types.h:32
DEBUG_COMMAND_INFO
#define DEBUG_COMMAND_INFO(obj, arg)
Definition: command.h:28
impeller::MakeShaderMetadata
static std::shared_ptr< ShaderMetadata > MakeShaderMetadata(const RuntimeUniformDescription &uniform)
Definition: runtime_effect_contents.cc:66
impeller::DefaultUniformAlignment
constexpr size_t DefaultUniformAlignment()
Definition: platform.h:15
impeller::kUnsignedShort
@ kUnsignedShort
Definition: runtime_types.h:26
impeller::CompareFunction::kEqual
@ kEqual
Comparison test passes if new_value == current_value.
impeller::kSignedByte
@ kSignedByte
Definition: runtime_types.h:23
impeller::StencilOperation::kIncrementClamp
@ kIncrementClamp
Increment the current stencil value by 1. Clamp it to the maximum.
impeller::ColorSourceContents::GetGeometry
const std::shared_ptr< Geometry > & GetGeometry() const
Get the geometry that this contents will use to render.
Definition: color_source_contents.cc:21
impeller::kSampledImage
@ kSampledImage
Definition: runtime_types.h:34
impeller::ToShaderStage
constexpr ShaderStage ToShaderStage(RuntimeShaderStage stage)
Definition: shader_types.h:29
impeller::OptionsFromPassAndEntity
ContentContextOptions OptionsFromPassAndEntity(const RenderPass &pass, const Entity &entity)
Definition: contents.cc:28
impeller::kSignedInt
@ kSignedInt
Definition: runtime_types.h:27
impeller::kUnsignedByte
@ kUnsignedByte
Definition: runtime_types.h:24
impeller::kUnsignedInt64
@ kUnsignedInt64
Definition: runtime_types.h:30
impeller::ShaderStage::kFragment
@ kFragment
impeller::kHalfFloat
@ kHalfFloat
Definition: runtime_types.h:31
impeller::kUnsignedInt
@ kUnsignedInt
Definition: runtime_types.h:28
impeller::kSignedShort
@ kSignedShort
Definition: runtime_types.h:25
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:67
impeller::Context::BackendType::kVulkan
@ kVulkan
impeller::ColorSourceContents::GetCoverage
std::optional< Rect > GetCoverage(const Entity &entity) const override
Get the area of the render pass that will be affected when this contents is rendered.
Definition: color_source_contents.cc:45
impeller::kDouble
@ kDouble
Definition: runtime_types.h:33
impeller::ShaderStage::kVertex
@ kVertex
impeller::kSignedInt64
@ kSignedInt64
Definition: runtime_types.h:29