| 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
5 #include "impeller/renderer/backend/metal/render_pass_mtl.h"
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"
11 #include "impeller/base/backend_cast.h"
12 #include "impeller/core/formats.h"
13 #include "impeller/core/host_buffer.h"
14 #include "impeller/core/shader_types.h"
15 #include "impeller/renderer/backend/metal/context_mtl.h"
16 #include "impeller/renderer/backend/metal/device_buffer_mtl.h"
17 #include "impeller/renderer/backend/metal/formats_mtl.h"
18 #include "impeller/renderer/backend/metal/pipeline_mtl.h"
19 #include "impeller/renderer/backend/metal/sampler_mtl.h"
20 #include "impeller/renderer/backend/metal/texture_mtl.h"
21 #include "impeller/renderer/command.h"
22 #include "impeller/renderer/vertex_descriptor.h"
23
24 namespace impeller {
25
26 static bool ConfigureResolveTextureAttachment(
27 const Attachment& desc,
28 MTLRenderPassAttachmentDescriptor* attachment) {
29 bool needs_resolve =
30 desc.store_action == StoreAction::kMultisampleResolve ||
31 desc.store_action == StoreAction::kStoreAndMultisampleResolve;
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 =
50 TextureMTL::Cast(*desc.resolve_texture).GetMTLTexture();
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
72 static bool ConfigureColorAttachment(
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
82 static bool ConfigureDepthAttachment(
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
92 static bool ConfigureStencilAttachment(
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 ///
195 struct PassBindingsCache {
196 explicit PassBindingsCache(id<MTLRenderCommandEncoder> encoder)
197 : encoder_(encoder) {}
198
199 PassBindingsCache(const PassBindingsCache&) = delete;
200
201 PassBindingsCache(PassBindingsCache&&) = delete;
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
285 bool SetSampler(ShaderStage stage,
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
393 VALIDATION_LOG
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