1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkAMDMemoryAllocator.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include <semaphore>
11cb93a386Sopenharmony_ci#include <thread>
12cb93a386Sopenharmony_ci
13cb93a386Sopenharmony_ci#include "include/core/SkExecutor.h"
14cb93a386Sopenharmony_ci#include "include/core/SkLog.h"
15cb93a386Sopenharmony_ci#include "include/gpu/vk/GrVkExtensions.h"
16cb93a386Sopenharmony_ci#include "src/core/SkTraceEvent.h"
17cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkInterface.h"
18cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkMemory.h"
19cb93a386Sopenharmony_ci#include "src/gpu/vk/GrVkUtil.h"
20cb93a386Sopenharmony_ci#include "src/core/SkUtils.h"
21cb93a386Sopenharmony_ci
22cb93a386Sopenharmony_cistatic SkExecutor& GetThreadPool() {
23cb93a386Sopenharmony_ci    static std::unique_ptr<SkExecutor> executor = SkExecutor::MakeFIFOThreadPool(1, false);
24cb93a386Sopenharmony_ci    return *executor;
25cb93a386Sopenharmony_ci}
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_ci#ifndef SK_USE_VMA
28cb93a386Sopenharmony_cisk_sp<GrVkMemoryAllocator> GrVkAMDMemoryAllocator::Make(VkInstance instance,
29cb93a386Sopenharmony_ci                                                        VkPhysicalDevice physicalDevice,
30cb93a386Sopenharmony_ci                                                        VkDevice device,
31cb93a386Sopenharmony_ci                                                        uint32_t physicalDeviceVersion,
32cb93a386Sopenharmony_ci                                                        const GrVkExtensions* extensions,
33cb93a386Sopenharmony_ci                                                        sk_sp<const GrVkInterface> interface,
34cb93a386Sopenharmony_ci                                                        const GrVkCaps* caps,
35cb93a386Sopenharmony_ci                                                        bool cacheFlag,
36cb93a386Sopenharmony_ci                                                        size_t maxBlockCount) {
37cb93a386Sopenharmony_ci    return nullptr;
38cb93a386Sopenharmony_ci}
39cb93a386Sopenharmony_ci#else
40cb93a386Sopenharmony_ci
41cb93a386Sopenharmony_cisk_sp<GrVkMemoryAllocator> GrVkAMDMemoryAllocator::Make(VkInstance instance,
42cb93a386Sopenharmony_ci                                                        VkPhysicalDevice physicalDevice,
43cb93a386Sopenharmony_ci                                                        VkDevice device,
44cb93a386Sopenharmony_ci                                                        uint32_t physicalDeviceVersion,
45cb93a386Sopenharmony_ci                                                        const GrVkExtensions* extensions,
46cb93a386Sopenharmony_ci                                                        sk_sp<const GrVkInterface> interface,
47cb93a386Sopenharmony_ci                                                        const GrVkCaps* caps,
48cb93a386Sopenharmony_ci                                                        bool cacheFlag,
49cb93a386Sopenharmony_ci                                                        size_t maxBlockCount) {
50cb93a386Sopenharmony_ci#define GR_COPY_FUNCTION(NAME) functions.vk##NAME = interface->fFunctions.f##NAME
51cb93a386Sopenharmony_ci#define GR_COPY_FUNCTION_KHR(NAME) functions.vk##NAME##KHR = interface->fFunctions.f##NAME
52cb93a386Sopenharmony_ci
53cb93a386Sopenharmony_ci    VmaVulkanFunctions functions;
54cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(GetPhysicalDeviceProperties);
55cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(GetPhysicalDeviceMemoryProperties);
56cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(AllocateMemory);
57cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(FreeMemory);
58cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(MapMemory);
59cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(UnmapMemory);
60cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(FlushMappedMemoryRanges);
61cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(InvalidateMappedMemoryRanges);
62cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(BindBufferMemory);
63cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(BindImageMemory);
64cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(GetBufferMemoryRequirements);
65cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(GetImageMemoryRequirements);
66cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(CreateBuffer);
67cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(DestroyBuffer);
68cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(CreateImage);
69cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(DestroyImage);
70cb93a386Sopenharmony_ci    GR_COPY_FUNCTION(CmdCopyBuffer);
71cb93a386Sopenharmony_ci    GR_COPY_FUNCTION_KHR(GetBufferMemoryRequirements2);
72cb93a386Sopenharmony_ci    GR_COPY_FUNCTION_KHR(GetImageMemoryRequirements2);
73cb93a386Sopenharmony_ci    GR_COPY_FUNCTION_KHR(BindBufferMemory2);
74cb93a386Sopenharmony_ci    GR_COPY_FUNCTION_KHR(BindImageMemory2);
75cb93a386Sopenharmony_ci    GR_COPY_FUNCTION_KHR(GetPhysicalDeviceMemoryProperties2);
76cb93a386Sopenharmony_ci
77cb93a386Sopenharmony_ci    VmaAllocatorCreateInfo info;
78cb93a386Sopenharmony_ci    info.flags = 0; // OH ISSUE: enable vma lock protect
79cb93a386Sopenharmony_ci    if (physicalDeviceVersion >= VK_MAKE_VERSION(1, 1, 0) ||
80cb93a386Sopenharmony_ci        (extensions->hasExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, 1) &&
81cb93a386Sopenharmony_ci         extensions->hasExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME, 1))) {
82cb93a386Sopenharmony_ci        info.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
83cb93a386Sopenharmony_ci    }
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_ci    info.physicalDevice = physicalDevice;
86cb93a386Sopenharmony_ci    info.device = device;
87cb93a386Sopenharmony_ci    // 4MB was picked for the size here by looking at memory usage of Android apps and runs of DM.
88cb93a386Sopenharmony_ci    // It seems to be a good compromise of not wasting unused allocated space and not making too
89cb93a386Sopenharmony_ci    // many small allocations. The AMD allocator will start making blocks at 1/8 the max size and
90cb93a386Sopenharmony_ci    // builds up block size as needed before capping at the max set here.
91cb93a386Sopenharmony_ci    if (cacheFlag) {
92cb93a386Sopenharmony_ci        info.preferredLargeHeapBlockSize = SkGetVmaBlockSizeMB() * 1024 * 1024; // 1024 = 1K
93cb93a386Sopenharmony_ci    } else {
94cb93a386Sopenharmony_ci        info.preferredLargeHeapBlockSize = 4 * 1024 * 1024;
95cb93a386Sopenharmony_ci    }
96cb93a386Sopenharmony_ci    info.maxBlockCount = maxBlockCount;
97cb93a386Sopenharmony_ci    info.pAllocationCallbacks = nullptr;
98cb93a386Sopenharmony_ci    info.pDeviceMemoryCallbacks = nullptr;
99cb93a386Sopenharmony_ci    info.frameInUseCount = 0;
100cb93a386Sopenharmony_ci    info.pHeapSizeLimit = nullptr;
101cb93a386Sopenharmony_ci    info.pVulkanFunctions = &functions;
102cb93a386Sopenharmony_ci    info.pRecordSettings = nullptr;
103cb93a386Sopenharmony_ci    info.instance = instance;
104cb93a386Sopenharmony_ci    info.vulkanApiVersion = physicalDeviceVersion;
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ci    VmaAllocator allocator;
107cb93a386Sopenharmony_ci    vmaCreateAllocator(&info, &allocator);
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ci    return sk_sp<GrVkAMDMemoryAllocator>(new GrVkAMDMemoryAllocator(
110cb93a386Sopenharmony_ci#ifdef NOT_USE_PRE_ALLOC
111cb93a386Sopenharmony_ci            allocator, std::move(interface), caps->mustUseCoherentHostVisibleMemory()));
112cb93a386Sopenharmony_ci#else
113cb93a386Sopenharmony_ci            allocator, std::move(interface), caps->mustUseCoherentHostVisibleMemory(), cacheFlag));
114cb93a386Sopenharmony_ci#endif
115cb93a386Sopenharmony_ci}
116cb93a386Sopenharmony_ci
117cb93a386Sopenharmony_ciGrVkAMDMemoryAllocator::GrVkAMDMemoryAllocator(VmaAllocator allocator,
118cb93a386Sopenharmony_ci                                               sk_sp<const GrVkInterface> interface,
119cb93a386Sopenharmony_ci#ifdef NOT_USE_PRE_ALLOC
120cb93a386Sopenharmony_ci                                               bool mustUseCoherentHostVisibleMemory)
121cb93a386Sopenharmony_ci#else
122cb93a386Sopenharmony_ci                                               bool mustUseCoherentHostVisibleMemory,
123cb93a386Sopenharmony_ci                                               bool cacheFlag)
124cb93a386Sopenharmony_ci#endif
125cb93a386Sopenharmony_ci        : fAllocator(allocator)
126cb93a386Sopenharmony_ci        , fInterface(std::move(interface))
127cb93a386Sopenharmony_ci#ifdef NOT_USE_PRE_ALLOC
128cb93a386Sopenharmony_ci        , fMustUseCoherentHostVisibleMemory(mustUseCoherentHostVisibleMemory) {}
129cb93a386Sopenharmony_ci#else
130cb93a386Sopenharmony_ci        , fMustUseCoherentHostVisibleMemory(mustUseCoherentHostVisibleMemory)
131cb93a386Sopenharmony_ci        , fCacheFlag(cacheFlag) {}
132cb93a386Sopenharmony_ci#endif
133cb93a386Sopenharmony_ci
134cb93a386Sopenharmony_ciGrVkAMDMemoryAllocator::~GrVkAMDMemoryAllocator() {
135cb93a386Sopenharmony_ci    vmaDestroyAllocator(fAllocator);
136cb93a386Sopenharmony_ci    fAllocator = VK_NULL_HANDLE;
137cb93a386Sopenharmony_ci}
138cb93a386Sopenharmony_ci
139cb93a386Sopenharmony_ci// OH ISSUE: VMA preAlloc
140cb93a386Sopenharmony_cistatic void FirstPreAllocMemory(VmaAllocator allocator, VmaAllocationCreateInfo info) {
141cb93a386Sopenharmony_ci    VkImage fakeImage;
142cb93a386Sopenharmony_ci    VmaAllocation reservedAllocation;
143cb93a386Sopenharmony_ci    if (allocator == nullptr) {
144cb93a386Sopenharmony_ci        return;
145cb93a386Sopenharmony_ci    }
146cb93a386Sopenharmony_ci    VkResult result = vmaCreateFakeImage(allocator, &fakeImage);
147cb93a386Sopenharmony_ci    if (result != VK_SUCCESS) {
148cb93a386Sopenharmony_ci        SK_LOGE("FirstPreAllocMemory: CreateFakeImage Failed!! VkResult %d", result);
149cb93a386Sopenharmony_ci        return;
150cb93a386Sopenharmony_ci    }
151cb93a386Sopenharmony_ci    {
152cb93a386Sopenharmony_ci        HITRACE_METER_FMT(HITRACE_TAG_GRAPHIC_AGP, "vmaAllocateReservedMemoryForImage");
153cb93a386Sopenharmony_ci        result = vmaAllocateReservedMemoryForImage(allocator, fakeImage, &info, &reservedAllocation, nullptr);
154cb93a386Sopenharmony_ci    }
155cb93a386Sopenharmony_ci    if (result != VK_SUCCESS) {
156cb93a386Sopenharmony_ci        SK_LOGE("FirstPreAllocMemory: AllocateReservedMemory Failed!! VkResult %d", result);
157cb93a386Sopenharmony_ci        vmaDestroyFakeImage(allocator, fakeImage);
158cb93a386Sopenharmony_ci        return;
159cb93a386Sopenharmony_ci    }
160cb93a386Sopenharmony_ci    {
161cb93a386Sopenharmony_ci        HITRACE_METER_FMT(HITRACE_TAG_GRAPHIC_AGP, "vmaBindImageMemory");
162cb93a386Sopenharmony_ci        result = vmaBindImageMemory(allocator, reservedAllocation, fakeImage);
163cb93a386Sopenharmony_ci    }
164cb93a386Sopenharmony_ci    if (result != VK_SUCCESS) {
165cb93a386Sopenharmony_ci        SK_LOGE("FirstPreAllocMemory: BindImageMemory Failed!! VkResult %d", result);
166cb93a386Sopenharmony_ci    }
167cb93a386Sopenharmony_ci    vmaDestroyFakeImage(allocator, fakeImage);
168cb93a386Sopenharmony_ci    vmaFreeReservedMemory(allocator, reservedAllocation);
169cb93a386Sopenharmony_ci}
170cb93a386Sopenharmony_ci
171cb93a386Sopenharmony_ci// OH ISSUE: VMA preAlloc
172cb93a386Sopenharmony_cistatic void PreAllocMemory(VmaAllocator allocator, VmaAllocation reservedAllocation) {
173cb93a386Sopenharmony_ci    VkImage fakeImage;
174cb93a386Sopenharmony_ci    if (allocator == nullptr) {
175cb93a386Sopenharmony_ci        return;
176cb93a386Sopenharmony_ci    }
177cb93a386Sopenharmony_ci    VkResult result = vmaCreateFakeImage(allocator, &fakeImage);
178cb93a386Sopenharmony_ci    if (result != VK_SUCCESS) {
179cb93a386Sopenharmony_ci        SK_LOGE("PreAllocMemory: CreateFakeImage Failed!! VkResult %d", result);
180cb93a386Sopenharmony_ci        return;
181cb93a386Sopenharmony_ci    }
182cb93a386Sopenharmony_ci    {
183cb93a386Sopenharmony_ci        HITRACE_METER_FMT(HITRACE_TAG_GRAPHIC_AGP, "vmaBindImageMemory");
184cb93a386Sopenharmony_ci        result = vmaBindImageMemory(allocator, reservedAllocation, fakeImage);
185cb93a386Sopenharmony_ci    }
186cb93a386Sopenharmony_ci    if (result != VK_SUCCESS) {
187cb93a386Sopenharmony_ci        SK_LOGE("PreAllocMemory: BindImageMemory Failed!! VkResult %d", result);
188cb93a386Sopenharmony_ci    }
189cb93a386Sopenharmony_ci    vmaDestroyFakeImage(allocator, fakeImage);
190cb93a386Sopenharmony_ci    vmaFreeReservedMemory(allocator, reservedAllocation);
191cb93a386Sopenharmony_ci}
192cb93a386Sopenharmony_ci
193cb93a386Sopenharmony_ciVkResult GrVkAMDMemoryAllocator::allocateImageMemory(VkImage image, AllocationPropertyFlags flags,
194cb93a386Sopenharmony_ci                                                     GrVkBackendMemory* backendMemory) {
195cb93a386Sopenharmony_ci    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
196cb93a386Sopenharmony_ci    VmaAllocationCreateInfo info;
197cb93a386Sopenharmony_ci    info.flags = 0;
198cb93a386Sopenharmony_ci    info.usage = VMA_MEMORY_USAGE_UNKNOWN;
199cb93a386Sopenharmony_ci    info.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
200cb93a386Sopenharmony_ci    info.preferredFlags = 0;
201cb93a386Sopenharmony_ci    info.memoryTypeBits = 0;
202cb93a386Sopenharmony_ci    info.pool = VK_NULL_HANDLE;
203cb93a386Sopenharmony_ci    info.pUserData = nullptr;
204cb93a386Sopenharmony_ci
205cb93a386Sopenharmony_ci    if (AllocationPropertyFlags::kDedicatedAllocation & flags) {
206cb93a386Sopenharmony_ci        info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
207cb93a386Sopenharmony_ci    }
208cb93a386Sopenharmony_ci
209cb93a386Sopenharmony_ci    if (AllocationPropertyFlags::kLazyAllocation & flags) {
210cb93a386Sopenharmony_ci        info.requiredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
211cb93a386Sopenharmony_ci    }
212cb93a386Sopenharmony_ci
213cb93a386Sopenharmony_ci    if (AllocationPropertyFlags::kProtected & flags) {
214cb93a386Sopenharmony_ci        info.requiredFlags |= VK_MEMORY_PROPERTY_PROTECTED_BIT;
215cb93a386Sopenharmony_ci    }
216cb93a386Sopenharmony_ci
217cb93a386Sopenharmony_ci    VmaAllocation allocation;
218cb93a386Sopenharmony_ci    VkResult result = vmaAllocateMemoryForImage(fAllocator, image, &info, &allocation, nullptr);
219cb93a386Sopenharmony_ci    if (VK_SUCCESS == result) {
220cb93a386Sopenharmony_ci        *backendMemory = (GrVkBackendMemory)allocation;
221cb93a386Sopenharmony_ci    }
222cb93a386Sopenharmony_ci
223cb93a386Sopenharmony_ci    // OH ISSUE: VMA preAlloc
224cb93a386Sopenharmony_ci    bool newBlockflag = false;
225cb93a386Sopenharmony_ci    vmaGetNewBlockStats(allocation, &newBlockflag);
226cb93a386Sopenharmony_ci    if (newBlockflag && fCacheFlag && SkGetPreAllocFlag()) {
227cb93a386Sopenharmony_ci        HITRACE_METER_FMT(HITRACE_TAG_GRAPHIC_AGP, "GrVkAMDMemoryAllocator trigger preAlloc");
228cb93a386Sopenharmony_ci        vmaClearNewBlockStats(allocation);
229cb93a386Sopenharmony_ci        std::lock_guard<std::mutex> lock(mPreAllocMutex);
230cb93a386Sopenharmony_ci        // After swap, allocation belongs to vma reserved block.
231cb93a386Sopenharmony_ci        VkResult result2 = vmaSwapReservedBlock(fAllocator, image, &info, &allocation, nullptr);
232cb93a386Sopenharmony_ci        if (result2 == VK_NOT_READY) {
233cb93a386Sopenharmony_ci            GetThreadPool().add([=] {
234cb93a386Sopenharmony_ci                std::lock_guard<std::mutex> lock(mPreAllocMutex);
235cb93a386Sopenharmony_ci                HITRACE_METER_FMT(HITRACE_TAG_GRAPHIC_AGP, "FirstPreAllocMemory");
236cb93a386Sopenharmony_ci                FirstPreAllocMemory(fAllocator, info);
237cb93a386Sopenharmony_ci            });
238cb93a386Sopenharmony_ci            return result;
239cb93a386Sopenharmony_ci        }
240cb93a386Sopenharmony_ci        if (result2 == VK_SUCCESS) {
241cb93a386Sopenharmony_ci            GetThreadPool().add([=] {
242cb93a386Sopenharmony_ci                std::this_thread::sleep_for(std::chrono::microseconds(SkGetPreAllocDelay()));
243cb93a386Sopenharmony_ci                std::lock_guard<std::mutex> lock(mPreAllocMutex);
244cb93a386Sopenharmony_ci                HITRACE_METER_FMT(HITRACE_TAG_GRAPHIC_AGP, "PreAllocMemory");
245cb93a386Sopenharmony_ci                PreAllocMemory(fAllocator, allocation);
246cb93a386Sopenharmony_ci            });
247cb93a386Sopenharmony_ci            VmaAllocation newAllocation;
248cb93a386Sopenharmony_ci            VkResult result3 = vmaAllocateMemoryForImage(fAllocator, image, &info, &newAllocation, nullptr);
249cb93a386Sopenharmony_ci            if (result3 == VK_SUCCESS) {
250cb93a386Sopenharmony_ci                *backendMemory = (GrVkBackendMemory)newAllocation;
251cb93a386Sopenharmony_ci            }
252cb93a386Sopenharmony_ci            return result3;
253cb93a386Sopenharmony_ci        }
254cb93a386Sopenharmony_ci    }
255cb93a386Sopenharmony_ci    return result;
256cb93a386Sopenharmony_ci}
257cb93a386Sopenharmony_ci
258cb93a386Sopenharmony_ciVkResult GrVkAMDMemoryAllocator::allocateBufferMemory(VkBuffer buffer, BufferUsage usage,
259cb93a386Sopenharmony_ci                                                      AllocationPropertyFlags flags,
260cb93a386Sopenharmony_ci                                                      GrVkBackendMemory* backendMemory) {
261cb93a386Sopenharmony_ci    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
262cb93a386Sopenharmony_ci    VmaAllocationCreateInfo info;
263cb93a386Sopenharmony_ci    info.flags = 0;
264cb93a386Sopenharmony_ci    info.usage = VMA_MEMORY_USAGE_UNKNOWN;
265cb93a386Sopenharmony_ci    info.memoryTypeBits = 0;
266cb93a386Sopenharmony_ci    info.pool = VK_NULL_HANDLE;
267cb93a386Sopenharmony_ci    info.pUserData = nullptr;
268cb93a386Sopenharmony_ci
269cb93a386Sopenharmony_ci    switch (usage) {
270cb93a386Sopenharmony_ci        case BufferUsage::kGpuOnly:
271cb93a386Sopenharmony_ci            info.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
272cb93a386Sopenharmony_ci            info.preferredFlags = 0;
273cb93a386Sopenharmony_ci            break;
274cb93a386Sopenharmony_ci        case BufferUsage::kCpuWritesGpuReads:
275cb93a386Sopenharmony_ci            // When doing cpu writes and gpu reads the general rule of thumb is to use coherent
276cb93a386Sopenharmony_ci            // memory. Though this depends on the fact that we are not doing any cpu reads and the
277cb93a386Sopenharmony_ci            // cpu writes are sequential. For sparse writes we'd want cpu cached memory, however we
278cb93a386Sopenharmony_ci            // don't do these types of writes in Skia.
279cb93a386Sopenharmony_ci            //
280cb93a386Sopenharmony_ci            // TODO: In the future there may be times where specific types of memory could benefit
281cb93a386Sopenharmony_ci            // from a coherent and cached memory. Typically these allow for the gpu to read cpu
282cb93a386Sopenharmony_ci            // writes from the cache without needing to flush the writes throughout the cache. The
283cb93a386Sopenharmony_ci            // reverse is not true and GPU writes tend to invalidate the cache regardless. Also
284cb93a386Sopenharmony_ci            // these gpu cache read access are typically lower bandwidth than non-cached memory.
285cb93a386Sopenharmony_ci            // For now Skia doesn't really have a need or want of this type of memory. But if we
286cb93a386Sopenharmony_ci            // ever do we could pass in an AllocationPropertyFlag that requests the cached property.
287cb93a386Sopenharmony_ci            info.requiredFlags =
288cb93a386Sopenharmony_ci                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
289cb93a386Sopenharmony_ci            info.preferredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
290cb93a386Sopenharmony_ci            break;
291cb93a386Sopenharmony_ci        case BufferUsage::kTransfersFromCpuToGpu:
292cb93a386Sopenharmony_ci            info.requiredFlags =
293cb93a386Sopenharmony_ci                    VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
294cb93a386Sopenharmony_ci            break;
295cb93a386Sopenharmony_ci        case BufferUsage::kTransfersFromGpuToCpu:
296cb93a386Sopenharmony_ci            info.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT;
297cb93a386Sopenharmony_ci            info.preferredFlags = VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
298cb93a386Sopenharmony_ci            break;
299cb93a386Sopenharmony_ci    }
300cb93a386Sopenharmony_ci
301cb93a386Sopenharmony_ci    if (fMustUseCoherentHostVisibleMemory &&
302cb93a386Sopenharmony_ci        (info.requiredFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)) {
303cb93a386Sopenharmony_ci        info.requiredFlags |= VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
304cb93a386Sopenharmony_ci    }
305cb93a386Sopenharmony_ci
306cb93a386Sopenharmony_ci    if (AllocationPropertyFlags::kDedicatedAllocation & flags) {
307cb93a386Sopenharmony_ci        info.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT;
308cb93a386Sopenharmony_ci    }
309cb93a386Sopenharmony_ci
310cb93a386Sopenharmony_ci    if ((AllocationPropertyFlags::kLazyAllocation & flags) && BufferUsage::kGpuOnly == usage) {
311cb93a386Sopenharmony_ci        info.preferredFlags |= VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT;
312cb93a386Sopenharmony_ci    }
313cb93a386Sopenharmony_ci
314cb93a386Sopenharmony_ci    if (AllocationPropertyFlags::kPersistentlyMapped & flags) {
315cb93a386Sopenharmony_ci        SkASSERT(BufferUsage::kGpuOnly != usage);
316cb93a386Sopenharmony_ci        info.flags |= VMA_ALLOCATION_CREATE_MAPPED_BIT;
317cb93a386Sopenharmony_ci    }
318cb93a386Sopenharmony_ci
319cb93a386Sopenharmony_ci    VmaAllocation allocation;
320cb93a386Sopenharmony_ci    VkResult result = vmaAllocateMemoryForBuffer(fAllocator, buffer, &info, &allocation, nullptr);
321cb93a386Sopenharmony_ci    if (VK_SUCCESS == result) {
322cb93a386Sopenharmony_ci        *backendMemory = (GrVkBackendMemory)allocation;
323cb93a386Sopenharmony_ci    }
324cb93a386Sopenharmony_ci
325cb93a386Sopenharmony_ci    return result;
326cb93a386Sopenharmony_ci}
327cb93a386Sopenharmony_ci
328cb93a386Sopenharmony_civoid GrVkAMDMemoryAllocator::freeMemory(const GrVkBackendMemory& memoryHandle) {
329cb93a386Sopenharmony_ci    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
330cb93a386Sopenharmony_ci    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
331cb93a386Sopenharmony_ci    vmaFreeMemory(fAllocator, allocation);
332cb93a386Sopenharmony_ci}
333cb93a386Sopenharmony_ci
334cb93a386Sopenharmony_civoid GrVkAMDMemoryAllocator::getAllocInfo(const GrVkBackendMemory& memoryHandle,
335cb93a386Sopenharmony_ci                                          GrVkAlloc* alloc) const {
336cb93a386Sopenharmony_ci    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
337cb93a386Sopenharmony_ci    VmaAllocationInfo vmaInfo;
338cb93a386Sopenharmony_ci    vmaGetAllocationInfo(fAllocator, allocation, &vmaInfo);
339cb93a386Sopenharmony_ci
340cb93a386Sopenharmony_ci    VkMemoryPropertyFlags memFlags;
341cb93a386Sopenharmony_ci    vmaGetMemoryTypeProperties(fAllocator, vmaInfo.memoryType, &memFlags);
342cb93a386Sopenharmony_ci
343cb93a386Sopenharmony_ci    uint32_t flags = 0;
344cb93a386Sopenharmony_ci    if (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT & memFlags) {
345cb93a386Sopenharmony_ci        flags |= GrVkAlloc::kMappable_Flag;
346cb93a386Sopenharmony_ci    }
347cb93a386Sopenharmony_ci    if (!SkToBool(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT & memFlags)) {
348cb93a386Sopenharmony_ci        flags |= GrVkAlloc::kNoncoherent_Flag;
349cb93a386Sopenharmony_ci    }
350cb93a386Sopenharmony_ci    if (VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT & memFlags) {
351cb93a386Sopenharmony_ci        flags |= GrVkAlloc::kLazilyAllocated_Flag;
352cb93a386Sopenharmony_ci    }
353cb93a386Sopenharmony_ci
354cb93a386Sopenharmony_ci    alloc->fMemory        = vmaInfo.deviceMemory;
355cb93a386Sopenharmony_ci    alloc->fOffset        = vmaInfo.offset;
356cb93a386Sopenharmony_ci    alloc->fSize          = vmaInfo.size;
357cb93a386Sopenharmony_ci    alloc->fFlags         = flags;
358cb93a386Sopenharmony_ci    alloc->fBackendMemory = memoryHandle;
359cb93a386Sopenharmony_ci    alloc->fAllocator     = (GrVkMemoryAllocator *)this;
360cb93a386Sopenharmony_ci}
361cb93a386Sopenharmony_ci
362cb93a386Sopenharmony_ciVkResult GrVkAMDMemoryAllocator::mapMemory(const GrVkBackendMemory& memoryHandle, void** data) {
363cb93a386Sopenharmony_ci    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
364cb93a386Sopenharmony_ci    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
365cb93a386Sopenharmony_ci    return vmaMapMemory(fAllocator, allocation, data);
366cb93a386Sopenharmony_ci}
367cb93a386Sopenharmony_ci
368cb93a386Sopenharmony_civoid GrVkAMDMemoryAllocator::unmapMemory(const GrVkBackendMemory& memoryHandle) {
369cb93a386Sopenharmony_ci    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
370cb93a386Sopenharmony_ci    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
371cb93a386Sopenharmony_ci    vmaUnmapMemory(fAllocator, allocation);
372cb93a386Sopenharmony_ci}
373cb93a386Sopenharmony_ci
374cb93a386Sopenharmony_ciVkResult GrVkAMDMemoryAllocator::flushMemory(const GrVkBackendMemory& memoryHandle,
375cb93a386Sopenharmony_ci                                             VkDeviceSize offset, VkDeviceSize size) {
376cb93a386Sopenharmony_ci    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
377cb93a386Sopenharmony_ci    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
378cb93a386Sopenharmony_ci    return vmaFlushAllocation(fAllocator, allocation, offset, size);
379cb93a386Sopenharmony_ci}
380cb93a386Sopenharmony_ci
381cb93a386Sopenharmony_ciVkResult GrVkAMDMemoryAllocator::invalidateMemory(const GrVkBackendMemory& memoryHandle,
382cb93a386Sopenharmony_ci                                                  VkDeviceSize offset, VkDeviceSize size) {
383cb93a386Sopenharmony_ci    TRACE_EVENT0("skia.gpu", TRACE_FUNC);
384cb93a386Sopenharmony_ci    const VmaAllocation allocation = (const VmaAllocation)memoryHandle;
385cb93a386Sopenharmony_ci    return vmaInvalidateAllocation(fAllocator, allocation, offset, size);
386cb93a386Sopenharmony_ci}
387cb93a386Sopenharmony_ci
388cb93a386Sopenharmony_ciuint64_t GrVkAMDMemoryAllocator::totalUsedMemory() const {
389cb93a386Sopenharmony_ci    VmaStats stats;
390cb93a386Sopenharmony_ci    vmaCalculateStats(fAllocator, &stats);
391cb93a386Sopenharmony_ci    return stats.total.usedBytes;
392cb93a386Sopenharmony_ci}
393cb93a386Sopenharmony_ci
394cb93a386Sopenharmony_ciuint64_t GrVkAMDMemoryAllocator::totalAllocatedMemory() const {
395cb93a386Sopenharmony_ci    VmaStats stats;
396cb93a386Sopenharmony_ci    vmaCalculateStats(fAllocator, &stats);
397cb93a386Sopenharmony_ci    return stats.total.usedBytes + stats.total.unusedBytes;
398cb93a386Sopenharmony_ci}
399cb93a386Sopenharmony_ci
400cb93a386Sopenharmony_civoid GrVkAMDMemoryAllocator::dumpVmaStats(SkString *out, const char *sep) const
401cb93a386Sopenharmony_ci{
402cb93a386Sopenharmony_ci    constexpr int MB = 1024 * 1024;
403cb93a386Sopenharmony_ci    if (out == nullptr || sep == nullptr) {
404cb93a386Sopenharmony_ci        return;
405cb93a386Sopenharmony_ci    }
406cb93a386Sopenharmony_ci    bool flag = SkGetMemoryOptimizedFlag();
407cb93a386Sopenharmony_ci    out->appendf("vma_flag: %d %s", flag, sep);
408cb93a386Sopenharmony_ci    if (!flag) {
409cb93a386Sopenharmony_ci        return;
410cb93a386Sopenharmony_ci    }
411cb93a386Sopenharmony_ci    VmaStats stats;
412cb93a386Sopenharmony_ci    vmaCalculateStats(fAllocator, &stats);
413cb93a386Sopenharmony_ci    uint64_t free = stats.total.unusedBytes;
414cb93a386Sopenharmony_ci    uint64_t used = stats.total.usedBytes;
415cb93a386Sopenharmony_ci    uint64_t total = free + used;
416cb93a386Sopenharmony_ci    auto maxBlockCount = SkGetVmaBlockCountMax();
417cb93a386Sopenharmony_ci    out->appendf("vma_free: %llu (%d MB)%s", free, free / MB, sep);
418cb93a386Sopenharmony_ci    out->appendf("vma_used: %llu (%d MB)%s", used, used / MB, sep);
419cb93a386Sopenharmony_ci    out->appendf("vma_total: %llu (%d MB)%s", total, total / MB, sep);
420cb93a386Sopenharmony_ci    out->appendf("vma_cacheBlockSize: %d MB%s", SkGetVmaBlockSizeMB(), sep);
421cb93a386Sopenharmony_ci    out->appendf("vma_cacheBlockCount: %llu / %llu%s",
422cb93a386Sopenharmony_ci        stats.total.blockCount <= maxBlockCount ? stats.total.blockCount : maxBlockCount, maxBlockCount, sep);
423cb93a386Sopenharmony_ci    out->appendf("vma_dedicatedBlockCount: %llu%s",
424cb93a386Sopenharmony_ci        stats.total.blockCount <= maxBlockCount ? 0 : stats.total.blockCount - maxBlockCount, sep);
425cb93a386Sopenharmony_ci    out->appendf("vma_allocationCount: %u%s", stats.total.allocationCount, sep);
426cb93a386Sopenharmony_ci    out->appendf("vma_unusedRangeCount: %u%s", stats.total.unusedRangeCount, sep);
427cb93a386Sopenharmony_ci    out->appendf("vma_allocationSize: %llu / %llu / %llu%s",
428cb93a386Sopenharmony_ci        stats.total.allocationSizeMin, stats.total.allocationSizeAvg, stats.total.allocationSizeMax, sep);
429cb93a386Sopenharmony_ci    out->appendf("vma_unusedRangeSize: %llu / %llu / %llu%s",
430cb93a386Sopenharmony_ci        stats.total.unusedRangeSizeMin, stats.total.unusedRangeSizeAvg, stats.total.unusedRangeSizeMax, sep);
431cb93a386Sopenharmony_ci    uint32_t blockSize = 0;
432cb93a386Sopenharmony_ci    vmaGetPreAllocBlockSize(fAllocator, &blockSize);
433cb93a386Sopenharmony_ci    out->appendf("vma_preAllocBlockSize: %d / 1%s", blockSize, sep);
434cb93a386Sopenharmony_ci}
435cb93a386Sopenharmony_ci
436cb93a386Sopenharmony_civoid GrVkAMDMemoryAllocator::vmaDefragment()
437cb93a386Sopenharmony_ci{
438cb93a386Sopenharmony_ci    if (!fCacheFlag) {
439cb93a386Sopenharmony_ci        return;
440cb93a386Sopenharmony_ci    }
441cb93a386Sopenharmony_ci    bool flag = SkGetVmaDefragmentOn();
442cb93a386Sopenharmony_ci    if (!flag) {
443cb93a386Sopenharmony_ci        return;
444cb93a386Sopenharmony_ci    }
445cb93a386Sopenharmony_ci    bool debugFlag = SkGetVmaDebugFlag();
446cb93a386Sopenharmony_ci    if (!debugFlag) {
447cb93a386Sopenharmony_ci        std::lock_guard<std::mutex> lock(mPreAllocMutex);
448cb93a386Sopenharmony_ci        vmaFreeEmptyBlock(fAllocator);
449cb93a386Sopenharmony_ci        return;
450cb93a386Sopenharmony_ci    }
451cb93a386Sopenharmony_ci
452cb93a386Sopenharmony_ci    // dfx
453cb93a386Sopenharmony_ci    SkString debugInfo;
454cb93a386Sopenharmony_ci    dumpVmaStats(&debugInfo);
455cb93a386Sopenharmony_ci    SkDebugf("GrVkAMDMemoryAllocator::vmaDefragment() before: %s",
456cb93a386Sopenharmony_ci        debugInfo.c_str());
457cb93a386Sopenharmony_ci    HITRACE_OHOS_NAME_FMT_ALWAYS("GrVkAMDMemoryAllocator::vmaDefragment() before: %s", debugInfo.c_str());
458cb93a386Sopenharmony_ci
459cb93a386Sopenharmony_ci    {
460cb93a386Sopenharmony_ci        std::lock_guard<std::mutex> lock(mPreAllocMutex);
461cb93a386Sopenharmony_ci        vmaFreeEmptyBlock(fAllocator);
462cb93a386Sopenharmony_ci    }
463cb93a386Sopenharmony_ci
464cb93a386Sopenharmony_ci    // dfx
465cb93a386Sopenharmony_ci    debugInfo = "";
466cb93a386Sopenharmony_ci    dumpVmaStats(&debugInfo);
467cb93a386Sopenharmony_ci    SkDebugf("GrVkAMDMemoryAllocator::vmaDefragment() after: %s",
468cb93a386Sopenharmony_ci        debugInfo.c_str());
469cb93a386Sopenharmony_ci    HITRACE_OHOS_NAME_FMT_ALWAYS("GrVkAMDMemoryAllocator::vmaDefragment() after: %s", debugInfo.c_str());
470cb93a386Sopenharmony_ci}
471cb93a386Sopenharmony_ci
472cb93a386Sopenharmony_ci#endif // SK_USE_VMA
473