Flutter Impeller
blit_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 #include <Metal/Metal.h>
7 #import <MetalPerformanceShaders/MetalPerformanceShaders.h>
8 #include <memory>
9 #include <utility>
10 #include <variant>
11 
12 #include "flutter/fml/closure.h"
13 #include "flutter/fml/logging.h"
14 #include "flutter/fml/trace_event.h"
16 #include "impeller/core/formats.h"
24 
26 
27 namespace impeller {
28 
29 BlitPassMTL::BlitPassMTL(id<MTLCommandBuffer> buffer, id<MTLDevice> device)
30  : buffer_(buffer), device_(device) {
31  if (!buffer_) {
32  return;
33  }
34  encoder_ = [buffer_ blitCommandEncoder];
35 #ifdef IMPELLER_DEBUG
36  is_metal_trace_active_ =
37  [[MTLCaptureManager sharedCaptureManager] isCapturing];
38 #endif // IMPELLER_DEBUG
39  is_valid_ = true;
40 }
41 
43  if (!did_finish_encoding_) {
44  [encoder_ endEncoding];
45  }
46 }
47 
48 bool BlitPassMTL::IsValid() const {
49  return is_valid_;
50 }
51 
52 void BlitPassMTL::OnSetLabel(std::string label) {
53  if (label.empty()) {
54  return;
55  }
56  [encoder_ setLabel:@(label.c_str())];
57 }
58 
59 bool BlitPassMTL::EncodeCommands(
60  const std::shared_ptr<Allocator>& transients_allocator) const {
61  [encoder_ endEncoding];
62  did_finish_encoding_ = true;
63  return true;
64 }
65 
66 // |BlitPass|
67 bool BlitPassMTL::OnCopyTextureToTextureCommand(
68  std::shared_ptr<Texture> source,
69  std::shared_ptr<Texture> destination,
70  IRect source_region,
71  IPoint destination_origin,
72  std::string label) {
73  auto source_mtl = TextureMTL::Cast(*source).GetMTLTexture();
74  if (!source_mtl) {
75  return false;
76  }
77 
78  auto destination_mtl = TextureMTL::Cast(*destination).GetMTLTexture();
79  if (!destination_mtl) {
80  return false;
81  }
82 
83  auto source_origin_mtl =
84  MTLOriginMake(source_region.GetX(), source_region.GetY(), 0);
85  auto source_size_mtl =
86  MTLSizeMake(source_region.GetWidth(), source_region.GetHeight(), 1);
87  auto destination_origin_mtl =
88  MTLOriginMake(destination_origin.x, destination_origin.y, 0);
89 
90 #ifdef IMPELLER_DEBUG
91  if (is_metal_trace_active_) {
92  [encoder_ pushDebugGroup:@(label.c_str())];
93  }
94 #endif // IMPELLER_DEBUG
95  [encoder_ copyFromTexture:source_mtl
96  sourceSlice:0
97  sourceLevel:0
98  sourceOrigin:source_origin_mtl
99  sourceSize:source_size_mtl
100  toTexture:destination_mtl
101  destinationSlice:0
102  destinationLevel:0
103  destinationOrigin:destination_origin_mtl];
104 
105 #ifdef IMPELLER_DEBUG
106  if (is_metal_trace_active_) {
107  [encoder_ popDebugGroup];
108  }
109 #endif // IMPELLER_DEBUG
110  return true;
111 }
112 
113 // |BlitPass|
114 bool BlitPassMTL::ResizeTexture(const std::shared_ptr<Texture>& source,
115  const std::shared_ptr<Texture>& destination) {
116  auto source_mtl = TextureMTL::Cast(*source).GetMTLTexture();
117  if (!source_mtl) {
118  return false;
119  }
120 
121  auto destination_mtl = TextureMTL::Cast(*destination).GetMTLTexture();
122  if (!destination_mtl) {
123  return false;
124  }
125 
126  [encoder_ endEncoding];
127  auto filter = [[MPSImageBilinearScale alloc] initWithDevice:device_];
128  [filter encodeToCommandBuffer:buffer_
129  sourceTexture:source_mtl
130  destinationTexture:destination_mtl];
131  encoder_ = [buffer_ blitCommandEncoder];
132  return true;
133 }
134 
135 // |BlitPass|
136 bool BlitPassMTL::OnCopyTextureToBufferCommand(
137  std::shared_ptr<Texture> source,
138  std::shared_ptr<DeviceBuffer> destination,
139  IRect source_region,
140  size_t destination_offset,
141  std::string label) {
142  auto source_mtl = TextureMTL::Cast(*source).GetMTLTexture();
143  if (!source_mtl) {
144  return false;
145  }
146 
147  auto destination_mtl = DeviceBufferMTL::Cast(*destination).GetMTLBuffer();
148  if (!destination_mtl) {
149  return false;
150  }
151 
152  auto source_origin_mtl =
153  MTLOriginMake(source_region.GetX(), source_region.GetY(), 0);
154  auto source_size_mtl =
155  MTLSizeMake(source_region.GetWidth(), source_region.GetHeight(), 1);
156 
157  auto destination_bytes_per_pixel =
158  BytesPerPixelForPixelFormat(source->GetTextureDescriptor().format);
159  auto destination_bytes_per_row =
160  source_size_mtl.width * destination_bytes_per_pixel;
161  auto destination_bytes_per_image =
162  source_size_mtl.height * destination_bytes_per_row;
163 
164 #ifdef IMPELLER_DEBUG
165  if (is_metal_trace_active_) {
166  [encoder_ pushDebugGroup:@(label.c_str())];
167  }
168 #endif // IMPELLER_DEBUG
169  [encoder_ copyFromTexture:source_mtl
170  sourceSlice:0
171  sourceLevel:0
172  sourceOrigin:source_origin_mtl
173  sourceSize:source_size_mtl
174  toBuffer:destination_mtl
175  destinationOffset:destination_offset
176  destinationBytesPerRow:destination_bytes_per_row
177  destinationBytesPerImage:destination_bytes_per_image];
178 
179 #ifdef IMPELLER_DEBUG
180  if (is_metal_trace_active_) {
181  [encoder_ popDebugGroup];
182  }
183 #endif // IMPELLER_DEBUG
184  return true;
185 }
186 
187 bool BlitPassMTL::OnCopyBufferToTextureCommand(
188  BufferView source,
189  std::shared_ptr<Texture> destination,
190  IRect destination_region,
191  std::string label,
192  uint32_t slice,
193  bool convert_to_read) {
194  auto source_mtl = DeviceBufferMTL::Cast(*source.buffer).GetMTLBuffer();
195  if (!source_mtl) {
196  return false;
197  }
198 
199  auto destination_mtl = TextureMTL::Cast(*destination).GetMTLTexture();
200  if (!destination_mtl) {
201  return false;
202  }
203 
204  auto destination_origin_mtl =
205  MTLOriginMake(destination_region.GetX(), destination_region.GetY(), 0);
206  auto source_size_mtl = MTLSizeMake(destination_region.GetWidth(),
207  destination_region.GetHeight(), 1);
208 
209  auto destination_bytes_per_pixel =
210  BytesPerPixelForPixelFormat(destination->GetTextureDescriptor().format);
211  auto source_bytes_per_row =
212  destination_region.GetWidth() * destination_bytes_per_pixel;
213 
214 #ifdef IMPELLER_DEBUG
215  if (is_metal_trace_active_) {
216  [encoder_ pushDebugGroup:@(label.c_str())];
217  }
218 #endif // IMPELLER_DEBUG
219  [encoder_
220  copyFromBuffer:source_mtl
221  sourceOffset:source.range.offset
222  sourceBytesPerRow:source_bytes_per_row
223  sourceBytesPerImage:
224  0 // 0 for 2D textures according to
225  // https://developer.apple.com/documentation/metal/mtlblitcommandencoder/1400752-copyfrombuffer
226  sourceSize:source_size_mtl
227  toTexture:destination_mtl
228  destinationSlice:slice
229  destinationLevel:0
230  destinationOrigin:destination_origin_mtl];
231 
232 #ifdef IMPELLER_DEBUG
233  if (is_metal_trace_active_) {
234  [encoder_ popDebugGroup];
235  }
236 #endif // IMPELLER_DEBUG
237  return true;
238 }
239 
240 // |BlitPass|
241 bool BlitPassMTL::OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
242  std::string label) {
243 #ifdef IMPELLER_DEBUG
244  if (is_metal_trace_active_) {
245  [encoder_ pushDebugGroup:@(label.c_str())];
246  }
247 #endif // IMPELLER_DEBUG
248  auto result = TextureMTL::Cast(*texture).GenerateMipmap(encoder_);
249 #ifdef IMPELLER_DEBUG
250  if (is_metal_trace_active_) {
251  [encoder_ popDebugGroup];
252  }
253 #endif // IMPELLER_DEBUG
254  return result;
255 }
256 
257 } // namespace impeller
host_buffer.h
impeller::TextureMTL::GenerateMipmap
bool GenerateMipmap(id< MTLBlitCommandEncoder > encoder)
Definition: texture_mtl.mm:150
impeller::BlitPassMTL::~BlitPassMTL
~BlitPassMTL() override
Definition: blit_pass_mtl.mm:42
blit_command.h
impeller::TextureMTL::GetMTLTexture
id< MTLTexture > GetMTLTexture() const
Definition: texture_mtl.mm:134
formats_mtl.h
formats.h
pipeline_mtl.h
impeller::BytesPerPixelForPixelFormat
constexpr size_t BytesPerPixelForPixelFormat(PixelFormat format)
Definition: formats.h:466
blit_pass_mtl.h
backend_cast.h
impeller::DeviceBufferMTL::GetMTLBuffer
id< MTLBuffer > GetMTLBuffer() const
Definition: device_buffer_mtl.mm:21
impeller::IPoint
TPoint< int64_t > IPoint
Definition: point.h:328
texture_mtl.h
impeller::BackendCast< TextureMTL, Texture >::Cast
static TextureMTL & Cast(Texture &base)
Definition: backend_cast.h:13
impeller::IRect
IRect64 IRect
Definition: rect.h:779
sampler_mtl.h
shader_types.h
impeller
Definition: allocation.cc:12
device_buffer_mtl.h