Flutter Engine
 
Loading...
Searching...
No Matches
allocator_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
9#include "fml/trace_event.h"
16
17namespace impeller {
18
19static bool DeviceSupportsDeviceTransientTargets(id<MTLDevice> device) {
20 // Refer to the "Memoryless render targets" feature in the table below:
21 // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
22 return [device supportsFamily:MTLGPUFamilyApple2];
23}
24
26 // Since Apple didn't expose API for us to get the max texture size, we have
27 // to use hardcoded data from
28 // https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
29 // According to the feature set table, there are two supported max sizes :
30 // 16384 and 8192 for devices flutter support. The former is used on macs and
31 // latest ios devices. The latter is used on old ios devices.
32 if ([device supportsFamily:MTLGPUFamilyApple3] ||
33 [device supportsFamily:MTLGPUFamilyMacCatalyst1] ||
34 [device supportsFamily:MTLGPUFamilyMac1]) {
35 return {16384, 16384};
36 }
37 return {8192, 8192};
38}
39
40static bool SupportsLossyTextureCompression(id<MTLDevice> device) {
41#ifdef FML_OS_IOS_SIMULATOR
42 return false;
43#else
44 return [device supportsFamily:MTLGPUFamilyApple8];
45#endif
46}
47
49 size_.fetch_add(size, std::memory_order_relaxed);
50}
51
53 size_.fetch_sub(size, std::memory_order_relaxed);
54}
55
57 return Bytes{size_.load()};
58}
59
60AllocatorMTL::AllocatorMTL(id<MTLDevice> device, std::string label)
61 : device_(device), allocator_label_(std::move(label)) {
62 if (!device_) {
63 return;
64 }
65
66 supports_memoryless_targets_ = DeviceSupportsDeviceTransientTargets(device_);
67 supports_uma_ = device_.hasUnifiedMemory;
68 max_texture_supported_ = DeviceMaxTextureSizeSupported(device_);
69
70 is_valid_ = true;
71}
72
74
75bool AllocatorMTL::IsValid() const {
76 return is_valid_;
77}
78
79static MTLResourceOptions ToMTLResourceOptions(StorageMode type,
80 bool supports_memoryless_targets,
81 bool supports_uma) {
82 switch (type) {
84#if FML_OS_IOS
85 return MTLResourceStorageModeShared;
86#else
87 if (supports_uma) {
88 return MTLResourceStorageModeShared;
89 } else {
90 return MTLResourceStorageModeManaged;
91 }
92#endif
94 return MTLResourceStorageModePrivate;
96 if (supports_memoryless_targets) {
97 // Device may support but the OS has not been updated.
98 if (@available(macOS 11.0, *)) {
99 return MTLResourceStorageModeMemoryless;
100 } else {
101 return MTLResourceStorageModePrivate;
102 }
103 } else {
104 return MTLResourceStorageModePrivate;
105 }
107 }
109}
110
111static MTLStorageMode ToMTLStorageMode(StorageMode mode,
112 bool supports_memoryless_targets,
113 bool supports_uma) {
114 switch (mode) {
116#if FML_OS_IOS
117 return MTLStorageModeShared;
118#else
119 if (supports_uma) {
120 return MTLStorageModeShared;
121 } else {
122 return MTLStorageModeManaged;
123 }
124#endif
126 return MTLStorageModePrivate;
128 if (supports_memoryless_targets) {
129 // Device may support but the OS has not been updated.
130 if (@available(macOS 11.0, *)) {
131 return MTLStorageModeMemoryless;
132 } else {
133 return MTLStorageModePrivate;
134 }
135 } else {
136 return MTLStorageModePrivate;
137 }
139 }
141}
142
143std::shared_ptr<DeviceBuffer> AllocatorMTL::OnCreateBuffer(
144 const DeviceBufferDescriptor& desc) {
145 const auto resource_options = ToMTLResourceOptions(
146 desc.storage_mode, supports_memoryless_targets_, supports_uma_);
147 const auto storage_mode = ToMTLStorageMode(
148 desc.storage_mode, supports_memoryless_targets_, supports_uma_);
149
150 auto buffer = [device_ newBufferWithLength:desc.size
151 options:resource_options];
152 if (!buffer) {
153 return nullptr;
154 }
155 return std::shared_ptr<DeviceBufferMTL>(new DeviceBufferMTL(desc, //
156 buffer, //
157 storage_mode //
158 ));
159}
160
161std::shared_ptr<Texture> AllocatorMTL::OnCreateTexture(
162 const TextureDescriptor& desc,
163 bool threadsafe) {
164 if (!IsValid()) {
165 return nullptr;
166 }
167
168 auto mtl_texture_desc = ToMTLTextureDescriptor(desc);
169
170 if (!mtl_texture_desc) {
171 VALIDATION_LOG << "Texture descriptor was invalid.";
172 return nullptr;
173 }
174
175 mtl_texture_desc.storageMode = ToMTLStorageMode(
176 desc.storage_mode, supports_memoryless_targets_, supports_uma_);
177
178 if (@available(macOS 12.5, ios 15.0, *)) {
179 if (desc.compression_type == CompressionType::kLossy &&
181 mtl_texture_desc.compressionType = MTLTextureCompressionTypeLossy;
182 }
183 }
184
185#ifdef IMPELLER_DEBUG
186 if (desc.storage_mode != StorageMode::kDeviceTransient) {
187 debug_allocater_->Increment(desc.GetByteSizeOfAllMipLevels());
188 }
189#endif // IMPELLER_DEBUG
190
191 auto texture = [device_ newTextureWithDescriptor:mtl_texture_desc];
192 if (!texture) {
193 return nullptr;
194 }
195 std::shared_ptr<TextureMTL> result_texture =
197#ifdef IMPELLER_DEBUG
198 result_texture->SetDebugAllocator(debug_allocater_);
199#endif // IMPELLER_DEBUG
200
201 return result_texture;
202}
203
204uint16_t AllocatorMTL::MinimumBytesPerRow(PixelFormat format) const {
205 return static_cast<uint16_t>([device_
206 minimumLinearTextureAlignmentForPixelFormat:ToMTLPixelFormat(format)]);
207}
208
209ISize AllocatorMTL::GetMaxTextureSizeSupported() const {
210 return max_texture_supported_;
211}
212
214 supports_uma_ = value;
215}
216
218#ifdef IMPELLER_DEBUG
219 return debug_allocater_->GetAllocationSize();
220#else
221 return {};
222#endif // IMPELLER_DEBUG
223}
224
225void AllocatorMTL::DebugTraceMemoryStatistics() const {
226#ifdef IMPELLER_DEBUG
227 FML_TRACE_COUNTER("flutter", "AllocatorMTL",
228 reinterpret_cast<int64_t>(this), // Trace Counter ID
229 "MemoryBudgetUsageMB",
230 DebugGetHeapUsage().ConvertTo<MebiBytes>().GetSize());
231#endif // IMPELLER_DEBUG
232}
233
234} // namespace impeller
GLenum type
void DebugSetSupportsUMA(bool value)
Bytes DebugGetHeapUsage() const override
Bytes GetAllocationSize()
Get the current tracked allocation size.
void Increment(size_t size)
Increment the tracked allocation size in bytes.
void Decrement(size_t size)
Decrement the tracked allocation size in bytes.
static std::shared_ptr< TextureMTL > Create(TextureDescriptor desc, id< MTLTexture > texture)
int32_t value
VkDevice device
Definition main.cc:69
#define FML_UNREACHABLE()
Definition logging.h:128
FlTexture * texture
static MTLStorageMode ToMTLStorageMode(StorageMode mode, bool supports_memoryless_targets, bool supports_uma)
StorageMode
Specified where the allocation resides and how it is used.
Definition formats.h:32
static bool SupportsLossyTextureCompression(id< MTLDevice > device)
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition formats.h:99
ISize DeviceMaxTextureSizeSupported(id< MTLDevice > device)
static MTLResourceOptions ToMTLResourceOptions(StorageMode type, bool supports_memoryless_targets, bool supports_uma)
static bool DeviceSupportsDeviceTransientTargets(id< MTLDevice > device)
constexpr MTLPixelFormat ToMTLPixelFormat(PixelFormat format)
Definition formats_mtl.h:76
ISize64 ISize
Definition size.h:162
MTLTextureDescriptor * ToMTLTextureDescriptor(const TextureDescriptor &desc)
Definition ref_ptr.h:261
#define FML_TRACE_COUNTER(category_group, name, counter_id, arg1,...)
Definition trace_event.h:85
#define VALIDATION_LOG
Definition validation.h:91