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