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