Flutter Impeller
render_pass_mtl.mm
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 "flutter/fml/closure.h"
8 #include "flutter/fml/logging.h"
9 #include "flutter/fml/make_copyable.h"
10 #include "flutter/fml/trace_event.h"
12 #include "impeller/core/formats.h"
23 
24 namespace impeller {
25 
27  const Attachment& desc,
28  MTLRenderPassAttachmentDescriptor* attachment) {
29  bool needs_resolve =
32 
33  if (needs_resolve && !desc.resolve_texture) {
34  VALIDATION_LOG << "Resolve store action specified on attachment but no "
35  "resolve texture was specified.";
36  return false;
37  }
38 
39  if (desc.resolve_texture && !needs_resolve) {
40  VALIDATION_LOG << "A resolve texture was specified even though the store "
41  "action doesn't require it.";
42  return false;
43  }
44 
45  if (!desc.resolve_texture) {
46  return true;
47  }
48 
49  attachment.resolveTexture =
51 
52  return true;
53 }
54 
55 static bool ConfigureAttachment(const Attachment& desc,
56  MTLRenderPassAttachmentDescriptor* attachment) {
57  if (!desc.texture) {
58  return false;
59  }
60 
61  attachment.texture = TextureMTL::Cast(*desc.texture).GetMTLTexture();
62  attachment.loadAction = ToMTLLoadAction(desc.load_action);
63  attachment.storeAction = ToMTLStoreAction(desc.store_action);
64 
65  if (!ConfigureResolveTextureAttachment(desc, attachment)) {
66  return false;
67  }
68 
69  return true;
70 }
71 
73  const ColorAttachment& desc,
74  MTLRenderPassColorAttachmentDescriptor* attachment) {
75  if (!ConfigureAttachment(desc, attachment)) {
76  return false;
77  }
78  attachment.clearColor = ToMTLClearColor(desc.clear_color);
79  return true;
80 }
81 
83  const DepthAttachment& desc,
84  MTLRenderPassDepthAttachmentDescriptor* attachment) {
85  if (!ConfigureAttachment(desc, attachment)) {
86  return false;
87  }
88  attachment.clearDepth = desc.clear_depth;
89  return true;
90 }
91 
93  const StencilAttachment& desc,
94  MTLRenderPassStencilAttachmentDescriptor* attachment) {
95  if (!ConfigureAttachment(desc, attachment)) {
96  return false;
97  }
98  attachment.clearStencil = desc.clear_stencil;
99  return true;
100 }
101 
102 // TODO(csg): Move this to formats_mtl.h
103 static MTLRenderPassDescriptor* ToMTLRenderPassDescriptor(
104  const RenderTarget& desc) {
105  auto result = [MTLRenderPassDescriptor renderPassDescriptor];
106 
107  const auto& colors = desc.GetColorAttachments();
108 
109  for (const auto& color : colors) {
110  if (!ConfigureColorAttachment(color.second,
111  result.colorAttachments[color.first])) {
112  VALIDATION_LOG << "Could not configure color attachment at index "
113  << color.first;
114  return nil;
115  }
116  }
117 
118  const auto& depth = desc.GetDepthAttachment();
119 
120  if (depth.has_value() &&
121  !ConfigureDepthAttachment(depth.value(), result.depthAttachment)) {
122  VALIDATION_LOG << "Could not configure depth attachment.";
123  return nil;
124  }
125 
126  const auto& stencil = desc.GetStencilAttachment();
127 
128  if (stencil.has_value() &&
129  !ConfigureStencilAttachment(stencil.value(), result.stencilAttachment)) {
130  VALIDATION_LOG << "Could not configure stencil attachment.";
131  return nil;
132  }
133 
134  return result;
135 }
136 
137 RenderPassMTL::RenderPassMTL(std::weak_ptr<const Context> context,
138  const RenderTarget& target,
139  id<MTLCommandBuffer> buffer)
140  : RenderPass(std::move(context), target),
141  buffer_(buffer),
142  desc_(ToMTLRenderPassDescriptor(GetRenderTarget())) {
143  if (!buffer_ || !desc_ || !render_target_.IsValid()) {
144  return;
145  }
146  is_valid_ = true;
147 }
148 
149 RenderPassMTL::~RenderPassMTL() = default;
150 
151 bool RenderPassMTL::IsValid() const {
152  return is_valid_;
153 }
154 
155 void RenderPassMTL::OnSetLabel(std::string label) {
156  if (label.empty()) {
157  return;
158  }
159  label_ = std::move(label);
160 }
161 
162 bool RenderPassMTL::OnEncodeCommands(const Context& context) const {
163  TRACE_EVENT0("impeller", "RenderPassMTL::EncodeCommands");
164  if (!IsValid()) {
165  return false;
166  }
167  auto render_command_encoder =
168  [buffer_ renderCommandEncoderWithDescriptor:desc_];
169 
170  if (!render_command_encoder) {
171  return false;
172  }
173 
174  if (!label_.empty()) {
175  [render_command_encoder setLabel:@(label_.c_str())];
176  }
177 
178  // Success or failure, the pass must end. The buffer can only process one pass
179  // at a time.
180  fml::ScopedCleanupClosure auto_end(
181  [render_command_encoder]() { [render_command_encoder endEncoding]; });
182 
183  return EncodeCommands(context.GetResourceAllocator(), render_command_encoder);
184 }
185 
186 //-----------------------------------------------------------------------------
187 /// @brief Ensures that bindings on the pass are not redundantly set or
188 /// updated. Avoids making the driver do additional checks and makes
189 /// the frame insights during profiling and instrumentation not
190 /// complain about the same.
191 ///
192 /// There should be no change to rendering if this caching was
193 /// absent.
194 ///
196  explicit PassBindingsCache(id<MTLRenderCommandEncoder> encoder)
197  : encoder_(encoder) {}
198 
199  PassBindingsCache(const PassBindingsCache&) = delete;
200 
202 
203  void SetRenderPipelineState(id<MTLRenderPipelineState> pipeline) {
204  if (pipeline == pipeline_) {
205  return;
206  }
207  pipeline_ = pipeline;
208  [encoder_ setRenderPipelineState:pipeline_];
209  }
210 
211  void SetDepthStencilState(id<MTLDepthStencilState> depth_stencil) {
212  if (depth_stencil_ == depth_stencil) {
213  return;
214  }
215  depth_stencil_ = depth_stencil;
216  [encoder_ setDepthStencilState:depth_stencil_];
217  }
218 
219  bool SetBuffer(ShaderStage stage,
220  uint64_t index,
221  uint64_t offset,
222  id<MTLBuffer> buffer) {
223  auto& buffers_map = buffers_[stage];
224  auto found = buffers_map.find(index);
225  if (found != buffers_map.end() && found->second.buffer == buffer) {
226  // The right buffer is bound. Check if its offset needs to be updated.
227  if (found->second.offset == offset) {
228  // Buffer and its offset is identical. Nothing to do.
229  return true;
230  }
231 
232  // Only the offset needs to be updated.
233  found->second.offset = offset;
234 
235  switch (stage) {
236  case ShaderStage::kVertex:
237  [encoder_ setVertexBufferOffset:offset atIndex:index];
238  return true;
239  case ShaderStage::kFragment:
240  [encoder_ setFragmentBufferOffset:offset atIndex:index];
241  return true;
242  default:
243  VALIDATION_LOG << "Cannot update buffer offset of an unknown stage.";
244  return false;
245  }
246  return true;
247  }
248  buffers_map[index] = {buffer, static_cast<size_t>(offset)};
249  switch (stage) {
250  case ShaderStage::kVertex:
251  [encoder_ setVertexBuffer:buffer offset:offset atIndex:index];
252  return true;
253  case ShaderStage::kFragment:
254  [encoder_ setFragmentBuffer:buffer offset:offset atIndex:index];
255  return true;
256  default:
257  VALIDATION_LOG << "Cannot bind buffer to unknown shader stage.";
258  return false;
259  }
260  return false;
261  }
262 
263  bool SetTexture(ShaderStage stage, uint64_t index, id<MTLTexture> texture) {
264  auto& texture_map = textures_[stage];
265  auto found = texture_map.find(index);
266  if (found != texture_map.end() && found->second == texture) {
267  // Already bound.
268  return true;
269  }
270  texture_map[index] = texture;
271  switch (stage) {
272  case ShaderStage::kVertex:
273  [encoder_ setVertexTexture:texture atIndex:index];
274  return true;
275  case ShaderStage::kFragment:
276  [encoder_ setFragmentTexture:texture atIndex:index];
277  return true;
278  default:
279  VALIDATION_LOG << "Cannot bind buffer to unknown shader stage.";
280  return false;
281  }
282  return false;
283  }
284 
286  uint64_t index,
287  id<MTLSamplerState> sampler) {
288  auto& sampler_map = samplers_[stage];
289  auto found = sampler_map.find(index);
290  if (found != sampler_map.end() && found->second == sampler) {
291  // Already bound.
292  return true;
293  }
294  sampler_map[index] = sampler;
295  switch (stage) {
296  case ShaderStage::kVertex:
297  [encoder_ setVertexSamplerState:sampler atIndex:index];
298  return true;
299  case ShaderStage::kFragment:
300  [encoder_ setFragmentSamplerState:sampler atIndex:index];
301  return true;
302  default:
303  VALIDATION_LOG << "Cannot bind buffer to unknown shader stage.";
304  return false;
305  }
306  return false;
307  }
308 
309  void SetViewport(const Viewport& viewport) {
310  if (viewport_.has_value() && viewport_.value() == viewport) {
311  return;
312  }
313  [encoder_ setViewport:MTLViewport{
314  .originX = viewport.rect.GetX(),
315  .originY = viewport.rect.GetY(),
316  .width = viewport.rect.GetWidth(),
317  .height = viewport.rect.GetHeight(),
318  .znear = viewport.depth_range.z_near,
319  .zfar = viewport.depth_range.z_far,
320  }];
321  viewport_ = viewport;
322  }
323 
324  void SetScissor(const IRect& scissor) {
325  if (scissor_.has_value() && scissor_.value() == scissor) {
326  return;
327  }
328  [encoder_
329  setScissorRect:MTLScissorRect{
330  .x = static_cast<NSUInteger>(scissor.GetX()),
331  .y = static_cast<NSUInteger>(scissor.GetY()),
332  .width = static_cast<NSUInteger>(scissor.GetWidth()),
333  .height =
334  static_cast<NSUInteger>(scissor.GetHeight()),
335  }];
336  scissor_ = scissor;
337  }
338 
339  private:
340  struct BufferOffsetPair {
341  id<MTLBuffer> buffer = nullptr;
342  size_t offset = 0u;
343  };
344  using BufferMap = std::map<uint64_t, BufferOffsetPair>;
345  using TextureMap = std::map<uint64_t, id<MTLTexture>>;
346  using SamplerMap = std::map<uint64_t, id<MTLSamplerState>>;
347 
348  const id<MTLRenderCommandEncoder> encoder_;
349  id<MTLRenderPipelineState> pipeline_ = nullptr;
350  id<MTLDepthStencilState> depth_stencil_ = nullptr;
351  std::map<ShaderStage, BufferMap> buffers_;
352  std::map<ShaderStage, TextureMap> textures_;
353  std::map<ShaderStage, SamplerMap> samplers_;
354  std::optional<Viewport> viewport_;
355  std::optional<IRect> scissor_;
356 };
357 
358 static bool Bind(PassBindingsCache& pass,
359  Allocator& allocator,
360  ShaderStage stage,
361  size_t bind_index,
362  const BufferView& view) {
363  if (!view.buffer) {
364  return false;
365  }
366 
367  auto device_buffer = view.buffer->GetDeviceBuffer(allocator);
368  if (!device_buffer) {
369  return false;
370  }
371 
372  auto buffer = DeviceBufferMTL::Cast(*device_buffer).GetMTLBuffer();
373  // The Metal call is a void return and we don't want to make it on nil.
374  if (!buffer) {
375  return false;
376  }
377 
378  return pass.SetBuffer(stage, bind_index, view.range.offset, buffer);
379 }
380 
381 static bool Bind(PassBindingsCache& pass,
382  ShaderStage stage,
383  size_t bind_index,
384  const Sampler& sampler,
385  const Texture& texture) {
386  if (!sampler.IsValid() || !texture.IsValid()) {
387  return false;
388  }
389 
390  if (texture.NeedsMipmapGeneration()) {
391  // TODO(127697): generate mips when the GPU is available on iOS.
392 #if !FML_OS_IOS
394  << "Texture at binding index " << bind_index
395  << " has a mip count > 1, but the mipmap has not been generated.";
396  return false;
397 #endif // !FML_OS_IOS
398  }
399 
400  return pass.SetTexture(stage, bind_index,
401  TextureMTL::Cast(texture).GetMTLTexture()) &&
402  pass.SetSampler(stage, bind_index,
403  SamplerMTL::Cast(sampler).GetMTLSamplerState());
404 }
405 
406 bool RenderPassMTL::EncodeCommands(const std::shared_ptr<Allocator>& allocator,
407  id<MTLRenderCommandEncoder> encoder) const {
408  PassBindingsCache pass_bindings(encoder);
409  auto bind_stage_resources = [&allocator, &pass_bindings](
410  const Bindings& bindings,
411  ShaderStage stage) -> bool {
412  for (const BufferAndUniformSlot& buffer : bindings.buffers) {
413  if (!Bind(pass_bindings, *allocator, stage, buffer.slot.ext_res_0,
414  buffer.view.resource)) {
415  return false;
416  }
417  }
418  for (const TextureAndSampler& data : bindings.sampled_images) {
419  if (!Bind(pass_bindings, stage, data.slot.texture_index, *data.sampler,
420  *data.texture.resource)) {
421  return false;
422  }
423  }
424  return true;
425  };
426 
427  const auto target_sample_count = render_target_.GetSampleCount();
428 
429  fml::closure pop_debug_marker = [encoder]() { [encoder popDebugGroup]; };
430  for (const auto& command : commands_) {
431 #ifdef IMPELLER_DEBUG
432  fml::ScopedCleanupClosure auto_pop_debug_marker(pop_debug_marker);
433  if (!command.label.empty()) {
434  [encoder pushDebugGroup:@(command.label.c_str())];
435  } else {
436  auto_pop_debug_marker.Release();
437  }
438 #endif // IMPELLER_DEBUG
439 
440  const auto& pipeline_desc = command.pipeline->GetDescriptor();
441  if (target_sample_count != pipeline_desc.GetSampleCount()) {
442  VALIDATION_LOG << "Pipeline for command and the render target disagree "
443  "on sample counts (target was "
444  << static_cast<uint64_t>(target_sample_count)
445  << " but pipeline wanted "
446  << static_cast<uint64_t>(pipeline_desc.GetSampleCount())
447  << ").";
448  return false;
449  }
450 
451  pass_bindings.SetRenderPipelineState(
452  PipelineMTL::Cast(*command.pipeline).GetMTLRenderPipelineState());
453  pass_bindings.SetDepthStencilState(
454  PipelineMTL::Cast(*command.pipeline).GetMTLDepthStencilState());
455  pass_bindings.SetViewport(command.viewport.value_or<Viewport>(
456  {.rect = Rect::MakeSize(GetRenderTargetSize())}));
457  pass_bindings.SetScissor(
458  command.scissor.value_or(IRect::MakeSize(GetRenderTargetSize())));
459 
460  [encoder setFrontFacingWinding:pipeline_desc.GetWindingOrder() ==
461  WindingOrder::kClockwise
462  ? MTLWindingClockwise
463  : MTLWindingCounterClockwise];
464  [encoder setCullMode:ToMTLCullMode(pipeline_desc.GetCullMode())];
465  [encoder setTriangleFillMode:ToMTLTriangleFillMode(
466  pipeline_desc.GetPolygonMode())];
467  [encoder setStencilReferenceValue:command.stencil_reference];
468 
469  if (!Bind(pass_bindings, *allocator, ShaderStage::kVertex,
470  VertexDescriptor::kReservedVertexBufferIndex,
471  command.vertex_buffer.vertex_buffer)) {
472  return false;
473  }
474 
475  if (!bind_stage_resources(command.vertex_bindings, ShaderStage::kVertex)) {
476  return false;
477  }
478  if (!bind_stage_resources(command.fragment_bindings,
479  ShaderStage::kFragment)) {
480  return false;
481  }
482 
483  const PrimitiveType primitive_type = pipeline_desc.GetPrimitiveType();
484  if (command.vertex_buffer.index_type == IndexType::kNone) {
485  if (command.instance_count != 1u) {
486 #if TARGET_OS_SIMULATOR
487  VALIDATION_LOG << "iOS Simulator does not support instanced rendering.";
488  return false;
489 #else // TARGET_OS_SIMULATOR
490  [encoder drawPrimitives:ToMTLPrimitiveType(primitive_type)
491  vertexStart:command.base_vertex
492  vertexCount:command.vertex_buffer.vertex_count
493  instanceCount:command.instance_count
494  baseInstance:0u];
495 #endif // TARGET_OS_SIMULATOR
496  } else {
497  [encoder drawPrimitives:ToMTLPrimitiveType(primitive_type)
498  vertexStart:command.base_vertex
499  vertexCount:command.vertex_buffer.vertex_count];
500  }
501  continue;
502  }
503 
504  if (command.vertex_buffer.index_type == IndexType::kUnknown) {
505  return false;
506  }
507  auto index_buffer = command.vertex_buffer.index_buffer.buffer;
508  if (!index_buffer) {
509  return false;
510  }
511  auto device_buffer = index_buffer->GetDeviceBuffer(*allocator);
512  if (!device_buffer) {
513  return false;
514  }
515  auto mtl_index_buffer =
516  DeviceBufferMTL::Cast(*device_buffer).GetMTLBuffer();
517  if (!mtl_index_buffer) {
518  return false;
519  }
520 
521  FML_DCHECK(
522  command.vertex_buffer.vertex_count *
523  (command.vertex_buffer.index_type == IndexType::k16bit ? 2 : 4) ==
524  command.vertex_buffer.index_buffer.range.length);
525 
526  if (command.instance_count != 1u) {
527 #if TARGET_OS_SIMULATOR
528  VALIDATION_LOG << "iOS Simulator does not support instanced rendering.";
529  return false;
530 #else // TARGET_OS_SIMULATOR
531  [encoder
532  drawIndexedPrimitives:ToMTLPrimitiveType(primitive_type)
533  indexCount:command.vertex_buffer.vertex_count
534  indexType:ToMTLIndexType(command.vertex_buffer.index_type)
535  indexBuffer:mtl_index_buffer
536  indexBufferOffset:command.vertex_buffer.index_buffer.range.offset
537  instanceCount:command.instance_count
538  baseVertex:command.base_vertex
539  baseInstance:0u];
540 #endif // TARGET_OS_SIMULATOR
541  } else {
542  [encoder
543  drawIndexedPrimitives:ToMTLPrimitiveType(primitive_type)
544  indexCount:command.vertex_buffer.vertex_count
545  indexType:ToMTLIndexType(command.vertex_buffer.index_type)
546  indexBuffer:mtl_index_buffer
547  indexBufferOffset:command.vertex_buffer.index_buffer.range
548  .offset];
549  }
550  }
551  return true;
552 }
553 
554 } // namespace impeller
impeller::StoreAction::kMultisampleResolve
@ kMultisampleResolve
impeller::Texture::NeedsMipmapGeneration
bool NeedsMipmapGeneration() const
Definition: texture.cc:85
host_buffer.h
impeller::StoreAction::kStoreAndMultisampleResolve
@ kStoreAndMultisampleResolve
impeller::ConfigureColorAttachment
static bool ConfigureColorAttachment(const ColorAttachment &desc, MTLRenderPassColorAttachmentDescriptor *attachment)
Definition: render_pass_mtl.mm:72
impeller::Attachment::store_action
StoreAction store_action
Definition: formats.h:637
impeller::Viewport::rect
Rect rect
Definition: formats.h:396
impeller::ConfigureStencilAttachment
static bool ConfigureStencilAttachment(const StencilAttachment &desc, MTLRenderPassStencilAttachmentDescriptor *attachment)
Definition: render_pass_mtl.mm:92
impeller::PassBindingsCache::PassBindingsCache
PassBindingsCache(id< MTLRenderCommandEncoder > encoder)
Definition: render_pass_mtl.mm:196
impeller::Viewport::depth_range
DepthRange depth_range
Definition: formats.h:397
context_mtl.h
render_pass_mtl.h
impeller::DepthRange::z_far
Scalar z_far
Definition: formats.h:388
impeller::ColorAttachment
Definition: formats.h:642
impeller::Range::offset
size_t offset
Definition: range.h:15
impeller::DepthRange::z_near
Scalar z_near
Definition: formats.h:387
impeller::ConfigureAttachment
static bool ConfigureAttachment(const Attachment &desc, MTLRenderPassAttachmentDescriptor *attachment)
Definition: render_pass_mtl.mm:55
formats.h
impeller::TextureMTL::GetMTLTexture
id< MTLTexture > GetMTLTexture() const
Definition: texture_mtl.mm:116
formats_mtl.h
impeller::ShaderStage
ShaderStage
Definition: shader_types.h:22
impeller::ToMTLStoreAction
constexpr MTLStoreAction ToMTLStoreAction(StoreAction action)
Definition: formats_mtl.h:307
impeller::TRect::GetX
constexpr Type GetX() const
Returns the X coordinate of the upper left corner, equivalent to |GetOrigin().x|.
Definition: rect.h:163
impeller::BufferView::range
Range range
Definition: buffer_view.h:16
impeller::TRect::GetHeight
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
Definition: rect.h:175
impeller::RenderTarget::GetColorAttachments
const std::map< size_t, ColorAttachment > & GetColorAttachments() const
Definition: render_target.cc:209
impeller::Texture::IsValid
virtual bool IsValid() const =0
pipeline_mtl.h
impeller::ToMTLClearColor
MTLClearColor ToMTLClearColor(const Color &color)
Definition: formats_mtl.h:372
vertex_descriptor.h
impeller::PassBindingsCache::SetScissor
void SetScissor(const IRect &scissor)
Definition: render_pass_mtl.mm:324
command.h
impeller::PassBindingsCache::SetTexture
bool SetTexture(ShaderStage stage, uint64_t index, id< MTLTexture > texture)
Definition: render_pass_mtl.mm:263
impeller::StencilAttachment
Definition: formats.h:650
impeller::ConfigureDepthAttachment
static bool ConfigureDepthAttachment(const DepthAttachment &desc, MTLRenderPassDepthAttachmentDescriptor *attachment)
Definition: render_pass_mtl.mm:82
impeller::Texture
Definition: texture.h:17
impeller::Sampler
Definition: sampler.h:15
impeller::PrimitiveType
PrimitiveType
Decides how backend draws pixels based on input vertices.
Definition: formats.h:350
impeller::RenderTarget::GetDepthAttachment
const std::optional< DepthAttachment > & GetDepthAttachment() const
Definition: render_target.cc:214
impeller::ColorAttachment::clear_color
Color clear_color
Definition: formats.h:643
impeller::ToMTLLoadAction
constexpr MTLLoadAction ToMTLLoadAction(LoadAction action)
Definition: formats_mtl.h:279
impeller::ToMTLRenderPassDescriptor
static MTLRenderPassDescriptor * ToMTLRenderPassDescriptor(const RenderTarget &desc)
Definition: render_pass_mtl.mm:103
impeller::Attachment::texture
std::shared_ptr< Texture > texture
Definition: formats.h:634
impeller::ToMTLPrimitiveType
constexpr MTLPrimitiveType ToMTLPrimitiveType(PrimitiveType type)
Definition: formats_mtl.h:151
impeller::PassBindingsCache
Ensures that bindings on the pass are not redundantly set or updated. Avoids making the driver do add...
Definition: render_pass_mtl.mm:195
impeller::TRect::GetWidth
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
Definition: rect.h:171
impeller::BufferView::buffer
std::shared_ptr< const Buffer > buffer
Definition: buffer_view.h:14
impeller::SamplerMap
std::unordered_map< SamplerDescriptor, std::shared_ptr< const Sampler >, ComparableHash< SamplerDescriptor >, ComparableEqual< SamplerDescriptor > > SamplerMap
Definition: sampler.h:37
backend_cast.h
impeller::PassBindingsCache::SetDepthStencilState
void SetDepthStencilState(id< MTLDepthStencilState > depth_stencil)
Definition: render_pass_mtl.mm:211
impeller::Allocator
An object that allocates device memory.
Definition: allocator.h:22
impeller::Attachment
Definition: formats.h:633
impeller::RenderTarget
Definition: render_target.h:49
impeller::StencilAttachment::clear_stencil
uint32_t clear_stencil
Definition: formats.h:651
impeller::ConfigureResolveTextureAttachment
static bool ConfigureResolveTextureAttachment(const Attachment &desc, MTLRenderPassAttachmentDescriptor *attachment)
Definition: render_pass_mtl.mm:26
impeller::PassBindingsCache::SetSampler
bool SetSampler(ShaderStage stage, uint64_t index, id< MTLSamplerState > sampler)
Definition: render_pass_mtl.mm:285
impeller::Viewport
Definition: formats.h:395
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:67
impeller::BufferView
Definition: buffer_view.h:13
impeller::Attachment::resolve_texture
std::shared_ptr< Texture > resolve_texture
Definition: formats.h:635
impeller::PassBindingsCache::SetViewport
void SetViewport(const Viewport &viewport)
Definition: render_pass_mtl.mm:309
std
Definition: comparable.h:95
impeller::Sampler::IsValid
virtual bool IsValid() const =0
texture_mtl.h
impeller::BackendCast< TextureMTL, Texture >::Cast
static TextureMTL & Cast(Texture &base)
Definition: backend_cast.h:15
impeller::Attachment::load_action
LoadAction load_action
Definition: formats.h:636
impeller::ToMTLIndexType
constexpr MTLIndexType ToMTLIndexType(IndexType type)
Definition: formats_mtl.h:177
impeller::DepthAttachment::clear_depth
double clear_depth
Definition: formats.h:647
sampler_mtl.h
impeller::PassBindingsCache::SetBuffer
bool SetBuffer(ShaderStage stage, uint64_t index, uint64_t offset, id< MTLBuffer > buffer)
Definition: render_pass_mtl.mm:219
impeller::DepthAttachment
Definition: formats.h:646
impeller::PassBindingsCache::SetRenderPipelineState
void SetRenderPipelineState(id< MTLRenderPipelineState > pipeline)
Definition: render_pass_mtl.mm:203
impeller::RenderTarget::GetStencilAttachment
const std::optional< StencilAttachment > & GetStencilAttachment() const
Definition: render_target.cc:218
shader_types.h
impeller::TRect::GetY
constexpr Type GetY() const
Returns the Y coordinate of the upper left corner, equivalent to |GetOrigin().y|.
Definition: rect.h:167
impeller::ToMTLCullMode
constexpr MTLCullMode ToMTLCullMode(CullMode mode)
Definition: formats_mtl.h:186
impeller
Definition: aiks_context.cc:10
impeller::ToMTLTriangleFillMode
constexpr MTLTriangleFillMode ToMTLTriangleFillMode(PolygonMode mode)
Definition: formats_mtl.h:167
impeller::TRect< int64_t >
device_buffer_mtl.h
impeller::Bind
static bool Bind(PassBindingsCache &pass, ShaderStage stage, size_t bind_index, const Sampler &sampler, const Texture &texture)
Definition: render_pass_mtl.mm:381