7 #include <Metal/Metal.h>
8 #import <MetalPerformanceShaders/MetalPerformanceShaders.h>
14 #include "flutter/fml/closure.h"
15 #include "flutter/fml/logging.h"
16 #include "flutter/fml/trace_event.h"
31 BlitPassMTL::BlitPassMTL(id<MTLCommandBuffer> buffer, id<MTLDevice> device)
32 : buffer_(buffer), device_(device) {
36 encoder_ = [buffer_ blitCommandEncoder];
38 is_metal_trace_active_ =
39 [[MTLCaptureManager sharedCaptureManager] isCapturing];
44 BlitPassMTL::~BlitPassMTL() {
45 if (!did_finish_encoding_) {
46 [encoder_ endEncoding];
50 bool BlitPassMTL::IsValid()
const {
54 void BlitPassMTL::OnSetLabel(std::string_view label) {
58 [encoder_ setLabel:@(label.data())];
61 bool BlitPassMTL::EncodeCommands()
const {
62 [encoder_ endEncoding];
63 did_finish_encoding_ =
true;
68 bool BlitPassMTL::OnCopyTextureToTextureCommand(
69 std::shared_ptr<Texture> source,
70 std::shared_ptr<Texture> destination,
73 std::string_view label) {
74 auto source_mtl = TextureMTL::Cast(*source).GetMTLTexture();
79 auto destination_mtl = TextureMTL::Cast(*destination).GetMTLTexture();
80 if (!destination_mtl) {
84 auto source_origin_mtl =
85 MTLOriginMake(source_region.GetX(), source_region.GetY(), 0);
86 auto source_size_mtl =
87 MTLSizeMake(source_region.GetWidth(), source_region.GetHeight(), 1);
88 auto destination_origin_mtl =
89 MTLOriginMake(destination_origin.x, destination_origin.y, 0);
92 if (is_metal_trace_active_) {
93 [encoder_ pushDebugGroup:@(label.data())];
96 [encoder_ copyFromTexture:source_mtl
99 sourceOrigin:source_origin_mtl
100 sourceSize:source_size_mtl
101 toTexture:destination_mtl
104 destinationOrigin:destination_origin_mtl];
106 #ifdef IMPELLER_DEBUG
107 if (is_metal_trace_active_) {
108 [encoder_ popDebugGroup];
115 bool BlitPassMTL::ResizeTexture(
const std::shared_ptr<Texture>& source,
116 const std::shared_ptr<Texture>& destination) {
117 auto source_mtl = TextureMTL::Cast(*source).GetMTLTexture();
122 auto destination_mtl = TextureMTL::Cast(*destination).GetMTLTexture();
123 if (!destination_mtl) {
127 [encoder_ endEncoding];
128 auto filter = [[MPSImageBilinearScale alloc] initWithDevice:device_];
129 [filter encodeToCommandBuffer:buffer_
130 sourceTexture:source_mtl
131 destinationTexture:destination_mtl];
132 encoder_ = [buffer_ blitCommandEncoder];
137 bool BlitPassMTL::OnCopyTextureToBufferCommand(
138 std::shared_ptr<Texture> source,
139 std::shared_ptr<DeviceBuffer> destination,
141 size_t destination_offset,
142 std::string_view label) {
143 auto source_mtl = TextureMTL::Cast(*source).GetMTLTexture();
148 auto destination_mtl = DeviceBufferMTL::Cast(*destination).GetMTLBuffer();
149 if (!destination_mtl) {
153 auto source_origin_mtl =
154 MTLOriginMake(source_region.GetX(), source_region.GetY(), 0);
155 auto source_size_mtl =
156 MTLSizeMake(source_region.GetWidth(), source_region.GetHeight(), 1);
158 auto destination_bytes_per_pixel =
160 auto destination_bytes_per_row =
161 source_size_mtl.width * destination_bytes_per_pixel;
162 auto destination_bytes_per_image =
163 source_size_mtl.height * destination_bytes_per_row;
165 #ifdef IMPELLER_DEBUG
166 if (is_metal_trace_active_) {
167 [encoder_ pushDebugGroup:@(label.data())];
170 [encoder_ copyFromTexture:source_mtl
173 sourceOrigin:source_origin_mtl
174 sourceSize:source_size_mtl
175 toBuffer:destination_mtl
176 destinationOffset:destination_offset
177 destinationBytesPerRow:destination_bytes_per_row
178 destinationBytesPerImage:destination_bytes_per_image];
180 #ifdef IMPELLER_DEBUG
181 if (is_metal_trace_active_) {
182 [encoder_ popDebugGroup];
188 bool BlitPassMTL::OnCopyBufferToTextureCommand(
190 std::shared_ptr<Texture> destination,
191 IRect destination_region,
192 std::string_view label,
195 bool convert_to_read) {
196 auto source_mtl = DeviceBufferMTL::Cast(*source.GetBuffer()).GetMTLBuffer();
201 auto destination_mtl = TextureMTL::Cast(*destination).GetMTLTexture();
202 if (!destination_mtl) {
206 auto destination_origin_mtl =
207 MTLOriginMake(destination_region.GetX(), destination_region.GetY(), 0);
208 auto source_size_mtl = MTLSizeMake(destination_region.GetWidth(),
209 destination_region.GetHeight(), 1);
211 auto destination_bytes_per_pixel =
213 auto source_bytes_per_row =
214 destination_region.GetWidth() * destination_bytes_per_pixel;
216 #ifdef IMPELLER_DEBUG
217 if (is_metal_trace_active_) {
218 [encoder_ pushDebugGroup:@(label.data())];
222 copyFromBuffer:source_mtl
223 sourceOffset:source.GetRange().offset
224 sourceBytesPerRow:source_bytes_per_row
228 sourceSize:source_size_mtl
229 toTexture:destination_mtl
230 destinationSlice:slice
231 destinationLevel:mip_level
232 destinationOrigin:destination_origin_mtl];
234 #ifdef IMPELLER_DEBUG
235 if (is_metal_trace_active_) {
236 [encoder_ popDebugGroup];
243 bool BlitPassMTL::OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
244 std::string_view label) {
245 #ifdef IMPELLER_DEBUG
246 if (is_metal_trace_active_) {
247 [encoder_ pushDebugGroup:@(label.data())];
250 auto result = TextureMTL::Cast(*texture).GenerateMipmap(encoder_);
251 #ifdef IMPELLER_DEBUG
252 if (is_metal_trace_active_) {
253 [encoder_ popDebugGroup];
constexpr size_t BytesPerPixelForPixelFormat(PixelFormat format)