Flutter Engine
The Flutter Engine
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
5#include "flutter/flutter_vma/flutter_skia_vma.h"
6
7#include "flutter/fml/memory/ref_ptr.h"
8#include "flutter/vulkan/procs/vulkan_handle.h"
9#include "flutter/vulkan/procs/vulkan_proc_table.h"
10
11namespace flutter {
12
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
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;
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) {
104 }
105 if (kProtected_AllocationPropertyFlag & allocationPropertyFlags) {
106 info.requiredFlags |= VK_MEMORY_PROPERTY_PROTECTED_BIT;
107 }
108
109 VmaAllocation allocation;
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,
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) {
133 info.preferredFlags = 0;
134 break;
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.
154 break;
158 info.preferredFlags = 0;
159 break;
163 break;
164 }
165
166 if (must_use_coherent_host_visible_memory_ &&
167 (info.requiredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) {
169 }
170 if (kDedicatedAllocation_AllocationPropertyFlag & allocationPropertyFlags) {
171 info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
172 }
173 if ((kLazyAllocation_AllocationPropertyFlag & allocationPropertyFlags) &&
176 }
177
178 if (kPersistentlyMapped_AllocationPropertyFlag & allocationPropertyFlags) {
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;
214 }
215 if (!(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT & memFlags)) {
217 }
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,
248 const VmaAllocation allocation =
249 reinterpret_cast<const VmaAllocation>(memoryHandle);
250 return vmaFlushAllocation(allocator_, allocation, offset, size);
251}
252
254 const skgpu::VulkanBackendMemory& memoryHandle,
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
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
#define SkASSERT(cond)
Definition: SkAssert.h:116
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
VkDevice device
Definition: main.cc:53
VkInstance instance
Definition: main.cc:48
FlutterSemanticsFlag flags
GAsyncResult * result
#define PROVIDE_PROC_COALESCE(tbl, proc, provider)
#define PROVIDE_PROC(tbl, proc, provider)
sk_sp< const SkImage > image
Definition: SkRecords.h:269
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: switches.h:41
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 vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
it will be possible to load the file into Perfetto s trace viewer 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
Definition: switches.h:259
dictionary stats
Definition: malisc.py:20
vk
Definition: malisc.py:42
intptr_t VulkanBackendMemory
Definition: VulkanTypes.h:32
Definition: ref_ptr.h:256
static void usage(char *argv0)
SeparatedVector2 offset
VkDeviceSize fSize
Definition: VulkanTypes.h:41
VulkanBackendMemory fBackendMemory
Definition: VulkanTypes.h:44
VkDeviceMemory fMemory
Definition: VulkanTypes.h:39
VkDeviceSize fOffset
Definition: VulkanTypes.h:40
VkFlags VkMemoryPropertyFlags
Definition: vulkan_core.h:2410
@ VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT
Definition: vulkan_core.h:2403
@ VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
Definition: vulkan_core.h:2401
@ VK_MEMORY_PROPERTY_PROTECTED_BIT
Definition: vulkan_core.h:2404
@ VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
Definition: vulkan_core.h:2399
@ VK_MEMORY_PROPERTY_HOST_CACHED_BIT
Definition: vulkan_core.h:2402
@ VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
Definition: vulkan_core.h:2400
uint64_t VkDeviceSize
Definition: vulkan_core.h:96
VkResult
Definition: vulkan_core.h:140
@ VK_SUCCESS
Definition: vulkan_core.h:141
#define VK_NULL_HANDLE
Definition: vulkan_core.h:46