Flutter Engine
 
Loading...
Searching...
No Matches
flutter_skia_vma.cc
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
10
11namespace flutter {
12
13sk_sp<skgpu::VulkanMemoryAllocator> FlutterSkiaVulkanMemoryAllocator::Make(
14 uint32_t vulkan_api_version,
15 VkInstance instance,
16 VkPhysicalDevice physicalDevice,
17 VkDevice device,
19 bool mustUseCoherentHostVisibleMemory) {
20#define PROVIDE_PROC(tbl, proc, provider) tbl.vk##proc = provider->proc;
21
22 VmaVulkanFunctions proc_table = {};
23 proc_table.vkGetInstanceProcAddr = vk->NativeGetInstanceProcAddr();
24 PROVIDE_PROC(proc_table, GetDeviceProcAddr, vk);
25 PROVIDE_PROC(proc_table, GetPhysicalDeviceProperties, vk);
26 PROVIDE_PROC(proc_table, GetPhysicalDeviceMemoryProperties, vk);
27 PROVIDE_PROC(proc_table, AllocateMemory, vk);
28 PROVIDE_PROC(proc_table, FreeMemory, vk);
29 PROVIDE_PROC(proc_table, MapMemory, vk);
30 PROVIDE_PROC(proc_table, UnmapMemory, vk);
31 PROVIDE_PROC(proc_table, FlushMappedMemoryRanges, vk);
32 PROVIDE_PROC(proc_table, InvalidateMappedMemoryRanges, vk);
33 PROVIDE_PROC(proc_table, BindBufferMemory, vk);
34 PROVIDE_PROC(proc_table, BindImageMemory, vk);
35 PROVIDE_PROC(proc_table, GetBufferMemoryRequirements, vk);
36 PROVIDE_PROC(proc_table, GetImageMemoryRequirements, vk);
37 PROVIDE_PROC(proc_table, CreateBuffer, vk);
38 PROVIDE_PROC(proc_table, DestroyBuffer, vk);
39 PROVIDE_PROC(proc_table, CreateImage, vk);
40 PROVIDE_PROC(proc_table, DestroyImage, vk);
41 PROVIDE_PROC(proc_table, CmdCopyBuffer, vk);
42
43#define PROVIDE_PROC_COALESCE(tbl, proc, provider) \
44 tbl.vk##proc##KHR = provider->proc ? provider->proc : provider->proc##KHR;
45 // See the following link for why we have to pick either KHR version or
46 // promoted non-KHR version:
47 // https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator/issues/203
48 PROVIDE_PROC_COALESCE(proc_table, GetBufferMemoryRequirements2, vk);
49 PROVIDE_PROC_COALESCE(proc_table, GetImageMemoryRequirements2, vk);
50 PROVIDE_PROC_COALESCE(proc_table, BindBufferMemory2, vk);
51 PROVIDE_PROC_COALESCE(proc_table, BindImageMemory2, vk);
52 PROVIDE_PROC_COALESCE(proc_table, GetPhysicalDeviceMemoryProperties2, vk);
53#undef PROVIDE_PROC_COALESCE
54
55#undef PROVIDE_PROC
56
57 VmaAllocatorCreateInfo allocator_info = {};
58 allocator_info.vulkanApiVersion = vulkan_api_version;
59 allocator_info.physicalDevice = physicalDevice;
60 allocator_info.device = device;
61 allocator_info.instance = instance;
62 allocator_info.pVulkanFunctions = &proc_table;
63
64 VmaAllocator allocator;
65 vmaCreateAllocator(&allocator_info, &allocator);
66
67 return sk_sp<FlutterSkiaVulkanMemoryAllocator>(
68 new FlutterSkiaVulkanMemoryAllocator(vk, allocator,
69 mustUseCoherentHostVisibleMemory));
70}
71
72FlutterSkiaVulkanMemoryAllocator::FlutterSkiaVulkanMemoryAllocator(
74 VmaAllocator allocator,
75 bool mustUseCoherentHostVisibleMemory)
76 : vk_proc_table_(std::move(vk_proc_table)),
77 allocator_(allocator),
78 must_use_coherent_host_visible_memory_(mustUseCoherentHostVisibleMemory) {
79}
80
82 vmaDestroyAllocator(allocator_);
83 allocator_ = VK_NULL_HANDLE;
84}
85
87 VkImage image,
88 uint32_t allocationPropertyFlags,
89 skgpu::VulkanBackendMemory* backendMemory) {
90 VmaAllocationCreateInfo info;
91 info.flags = 0;
92 info.usage = VMA_MEMORY_USAGE_UNKNOWN;
93 info.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
94 info.preferredFlags = 0;
95 info.memoryTypeBits = 0;
96 info.pool = VK_NULL_HANDLE;
97 info.pUserData = nullptr;
98
99 if (kDedicatedAllocation_AllocationPropertyFlag & allocationPropertyFlags) {
100 info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
101 }
102 if (kLazyAllocation_AllocationPropertyFlag & allocationPropertyFlags) {
103 info.requiredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
104 }
105 if (kProtected_AllocationPropertyFlag & allocationPropertyFlags) {
106 info.requiredFlags |= VK_MEMORY_PROPERTY_PROTECTED_BIT;
107 }
108
109 VmaAllocation allocation;
110 VkResult result =
111 vmaAllocateMemoryForImage(allocator_, image, &info, &allocation, nullptr);
112 if (VK_SUCCESS == result) {
113 *backendMemory = reinterpret_cast<skgpu::VulkanBackendMemory>(allocation);
114 }
115 return result;
116}
117
119 VkBuffer buffer,
120 BufferUsage usage,
121 uint32_t allocationPropertyFlags,
122 skgpu::VulkanBackendMemory* backendMemory) {
123 VmaAllocationCreateInfo info;
124 info.flags = 0;
125 info.usage = VMA_MEMORY_USAGE_UNKNOWN;
126 info.memoryTypeBits = 0;
127 info.pool = VK_NULL_HANDLE;
128 info.pUserData = nullptr;
129
130 switch (usage) {
131 case BufferUsage::kGpuOnly:
132 info.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
133 info.preferredFlags = 0;
134 break;
135 case BufferUsage::kCpuWritesGpuReads:
136 // When doing cpu writes and gpu reads the general rule of thumb is to use
137 // coherent memory. Though this depends on the fact that we are not doing
138 // any cpu reads and the cpu writes are sequential. For sparse writes we'd
139 // want cpu cached memory, however we don't do these types of writes in
140 // Skia.
141 //
142 // TODO (kaushikiska): In the future there may be times where specific
143 // types of memory could benefit from a coherent and cached memory.
144 // Typically these allow for the gpu to read cpu writes from the cache
145 // without needing to flush the writes throughout the cache. The reverse
146 // is not true and GPU writes tend to invalidate the cache regardless.
147 // Also these gpu cache read access are typically lower bandwidth than
148 // non-cached memory. For now Skia doesn't really have a need or want of
149 // this type of memory. But if we ever do we could pass in an
150 // AllocationPropertyFlag that requests the cached property.
151 info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
152 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
153 info.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
154 break;
155 case BufferUsage::kTransfersFromCpuToGpu:
156 info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
157 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
158 info.preferredFlags = 0;
159 break;
160 case BufferUsage::kTransfersFromGpuToCpu:
161 info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
162 info.preferredFlags = VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
163 break;
164 }
165
166 if (must_use_coherent_host_visible_memory_ &&
167 (info.requiredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) {
168 info.requiredFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
169 }
170 if (kDedicatedAllocation_AllocationPropertyFlag & allocationPropertyFlags) {
171 info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
172 }
173 if ((kLazyAllocation_AllocationPropertyFlag & allocationPropertyFlags) &&
174 BufferUsage::kGpuOnly == usage) {
175 info.preferredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
176 }
177
178 if (kPersistentlyMapped_AllocationPropertyFlag & allocationPropertyFlags) {
179 SkASSERT(BufferUsage::kGpuOnly != usage);
180 info.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT;
181 }
182
183 VmaAllocation allocation;
184 VkResult result = vmaAllocateMemoryForBuffer(allocator_, buffer, &info,
185 &allocation, nullptr);
186 if (VK_SUCCESS == result) {
187 *backendMemory = reinterpret_cast<skgpu::VulkanBackendMemory>(allocation);
188 }
189
190 return result;
191}
192
194 const skgpu::VulkanBackendMemory& memoryHandle) {
195 const VmaAllocation allocation =
196 reinterpret_cast<const VmaAllocation>(memoryHandle);
197 vmaFreeMemory(allocator_, allocation);
198}
199
201 const skgpu::VulkanBackendMemory& memoryHandle,
202 skgpu::VulkanAlloc* alloc) const {
203 const VmaAllocation allocation =
204 reinterpret_cast<const VmaAllocation>(memoryHandle);
205 VmaAllocationInfo vmaInfo;
206 vmaGetAllocationInfo(allocator_, allocation, &vmaInfo);
207
208 VkMemoryPropertyFlags memFlags;
209 vmaGetMemoryTypeProperties(allocator_, vmaInfo.memoryType, &memFlags);
210
211 uint32_t flags = 0;
212 if (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT & memFlags) {
213 flags |= skgpu::VulkanAlloc::kMappable_Flag;
214 }
215 if (!(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT & memFlags)) {
216 flags |= skgpu::VulkanAlloc::kNoncoherent_Flag;
217 }
218 if (VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT & memFlags) {
219 flags |= skgpu::VulkanAlloc::kLazilyAllocated_Flag;
220 }
221
222 alloc->fMemory = vmaInfo.deviceMemory;
223 alloc->fOffset = vmaInfo.offset;
224 alloc->fSize = vmaInfo.size;
225 alloc->fFlags = flags;
226 alloc->fBackendMemory = memoryHandle;
227}
228
230 const skgpu::VulkanBackendMemory& memoryHandle,
231 void** data) {
232 const VmaAllocation allocation =
233 reinterpret_cast<const VmaAllocation>(memoryHandle);
234 return vmaMapMemory(allocator_, allocation, data);
235}
236
238 const skgpu::VulkanBackendMemory& memoryHandle) {
239 const VmaAllocation allocation =
240 reinterpret_cast<const VmaAllocation>(memoryHandle);
241 vmaUnmapMemory(allocator_, allocation);
242}
243
245 const skgpu::VulkanBackendMemory& memoryHandle,
246 VkDeviceSize offset,
247 VkDeviceSize size) {
248 const VmaAllocation allocation =
249 reinterpret_cast<const VmaAllocation>(memoryHandle);
250 return vmaFlushAllocation(allocator_, allocation, offset, size);
251}
252
254 const skgpu::VulkanBackendMemory& memoryHandle,
255 VkDeviceSize offset,
256 VkDeviceSize size) {
257 const VmaAllocation allocation =
258 reinterpret_cast<const VmaAllocation>(memoryHandle);
259 return vmaInvalidateAllocation(allocator_, allocation, offset, size);
260}
261
262std::pair<uint64_t, uint64_t>
264 VmaTotalStatistics stats;
265 vmaCalculateStatistics(allocator_, &stats);
266 return {stats.total.statistics.blockBytes,
267 stats.total.statistics.allocationBytes};
268}
269
270} // namespace flutter
VkResult mapMemory(const skgpu::VulkanBackendMemory &, void **data) override
static sk_sp< VulkanMemoryAllocator > Make(uint32_t vulkan_api_version, VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device, const fml::RefPtr< vulkan::VulkanProcTable > &vk, bool mustUseCoherentHostVisibleMemory)
VkResult invalidateMemory(const skgpu::VulkanBackendMemory &, VkDeviceSize offset, VkDeviceSize size) override
void freeMemory(const skgpu::VulkanBackendMemory &) override
VkResult allocateImageMemory(VkImage image, uint32_t allocationPropertyFlags, skgpu::VulkanBackendMemory *) override
VkResult allocateBufferMemory(VkBuffer buffer, BufferUsage usage, uint32_t allocationPropertyFlags, skgpu::VulkanBackendMemory *) override
void getAllocInfo(const skgpu::VulkanBackendMemory &, skgpu::VulkanAlloc *) const override
VkResult flushMemory(const skgpu::VulkanBackendMemory &, VkDeviceSize offset, VkDeviceSize size) override
std::pair< uint64_t, uint64_t > totalAllocatedAndUsedMemory() const override
void unmapMemory(const skgpu::VulkanBackendMemory &) override
FlutterVulkanImage * image
VkDevice device
Definition main.cc:69
VkInstance instance
Definition main.cc:64
#define PROVIDE_PROC_COALESCE(tbl, proc, provider)
#define PROVIDE_PROC(tbl, proc, provider)
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switch_defs.h:36
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
Definition switch_defs.h:98
Definition ref_ptr.h:261