1164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel/*
2164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel* Copyright 2015 Google Inc.
3164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel*
4164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel* Use of this source code is governed by a BSD-style license that can be
5164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel* found in the LICENSE file.
6164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel*/
7164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
8164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkMemory.h"
9164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
10164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkGpu.h"
11164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel#include "GrVkUtil.h"
12164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1368c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#ifdef SK_DEBUG
1468c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth// for simple tracking of how much we're using in each heap
1568c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth// last counter is for non-subheap allocations
1668c3d30702c8af5ae249c78b30a9ea2351f875edjvanverthVkDeviceSize gHeapUsage[VK_MAX_MEMORY_HEAPS+1] = { 0 };
1768c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#endif
1868c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth
199d54afc38b171c01a03b34e773d154fcf83d97dcjvanverthstatic bool get_valid_memory_type_index(const VkPhysicalDeviceMemoryProperties& physDevMemProps,
20164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                        uint32_t typeBits,
21164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                        VkMemoryPropertyFlags requestedMemFlags,
2268c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                                        uint32_t* typeIndex,
2368c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                                        uint32_t* heapIndex) {
249d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    for (uint32_t i = 0; i < physDevMemProps.memoryTypeCount; ++i) {
259d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        if (typeBits & (1 << i)) {
26164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            uint32_t supportedFlags = physDevMemProps.memoryTypes[i].propertyFlags &
27164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                      requestedMemFlags;
28164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            if (supportedFlags == requestedMemFlags) {
29164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                *typeIndex = i;
3068c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                *heapIndex = physDevMemProps.memoryTypes[i].heapIndex;
31164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                return true;
32164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel            }
33164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        }
34164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
35164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return false;
36164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
37164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
386b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthstatic GrVkGpu::Heap buffer_type_to_heap(GrVkBuffer::Type type) {
396b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    const GrVkGpu::Heap kBufferToHeap[]{
406b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        GrVkGpu::kVertexBuffer_Heap,
416b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        GrVkGpu::kIndexBuffer_Heap,
426b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        GrVkGpu::kUniformBuffer_Heap,
43c2dd5ed93753dc54619fb713ebcf38bd1af08592Greg Daniel        GrVkGpu::kTexelBuffer_Heap,
446b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        GrVkGpu::kCopyReadBuffer_Heap,
456b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        GrVkGpu::kCopyWriteBuffer_Heap,
46164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    };
476b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    GR_STATIC_ASSERT(0 == GrVkBuffer::kVertex_Type);
486b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    GR_STATIC_ASSERT(1 == GrVkBuffer::kIndex_Type);
496b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    GR_STATIC_ASSERT(2 == GrVkBuffer::kUniform_Type);
50c2dd5ed93753dc54619fb713ebcf38bd1af08592Greg Daniel    GR_STATIC_ASSERT(3 == GrVkBuffer::kTexel_Type);
51c2dd5ed93753dc54619fb713ebcf38bd1af08592Greg Daniel    GR_STATIC_ASSERT(4 == GrVkBuffer::kCopyRead_Type);
52c2dd5ed93753dc54619fb713ebcf38bd1af08592Greg Daniel    GR_STATIC_ASSERT(5 == GrVkBuffer::kCopyWrite_Type);
53164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
546b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    return kBufferToHeap[type];
55164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
56164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
57164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkMemory::AllocAndBindBufferMemory(const GrVkGpu* gpu,
58164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                          VkBuffer buffer,
596b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                                          GrVkBuffer::Type type,
60a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth                                          bool dynamic,
611e305ba0d6a4237020d36234e9e286d3b0489401jvanverth                                          GrVkAlloc* alloc) {
62e50f3e75392d7be8ae89df8f55b1700100c34ad7jvanverth    const GrVkInterface* iface = gpu->vkInterface();
63164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkDevice device = gpu->device();
64164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
65164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkMemoryRequirements memReqs;
66e50f3e75392d7be8ae89df8f55b1700100c34ad7jvanverth    GR_VK_CALL(iface, GetBufferMemoryRequirements(device, buffer, &memReqs));
67164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
687378ac8e1e591b6bc3e723cc428a28129886ccd6jvanverth    uint32_t typeIndex = 0;
6968c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth    uint32_t heapIndex = 0;
709d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    const VkPhysicalDeviceMemoryProperties& phDevMemProps = gpu->physicalDeviceMemoryProperties();
718385a8a44bd06cbd400bc66440466229dc52f33fGreg Daniel    const VkPhysicalDeviceProperties& phDevProps = gpu->physicalDeviceProperties();
729d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    if (dynamic) {
739d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        // try to get cached and ideally non-coherent memory first
749d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        if (!get_valid_memory_type_index(phDevMemProps,
759d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth                                         memReqs.memoryTypeBits,
769d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth                                         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
779d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth                                         VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
7868c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                                         &typeIndex,
7968c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                                         &heapIndex)) {
809d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth            // some sort of host-visible memory type should always be available for dynamic buffers
819d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth            SkASSERT_RELEASE(get_valid_memory_type_index(phDevMemProps,
829d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth                                                         memReqs.memoryTypeBits,
839d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth                                                         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
8468c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                                                         &typeIndex,
8568c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                                                         &heapIndex));
869d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        }
879d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth
889d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        VkMemoryPropertyFlags mpf = phDevMemProps.memoryTypes[typeIndex].propertyFlags;
899d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        alloc->fFlags = mpf & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ? 0x0
909d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth                                                                   : GrVkAlloc::kNoncoherent_Flag;
918385a8a44bd06cbd400bc66440466229dc52f33fGreg Daniel        if (SkToBool(alloc->fFlags & GrVkAlloc::kNoncoherent_Flag)) {
928385a8a44bd06cbd400bc66440466229dc52f33fGreg Daniel            SkASSERT(SkIsPow2(memReqs.alignment));
938385a8a44bd06cbd400bc66440466229dc52f33fGreg Daniel            SkASSERT(SkIsPow2(phDevProps.limits.nonCoherentAtomSize));
948385a8a44bd06cbd400bc66440466229dc52f33fGreg Daniel            memReqs.alignment = SkTMax(memReqs.alignment, phDevProps.limits.nonCoherentAtomSize);
958385a8a44bd06cbd400bc66440466229dc52f33fGreg Daniel        }
969d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    } else {
979d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        // device-local memory should always be available for static buffers
989d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        SkASSERT_RELEASE(get_valid_memory_type_index(phDevMemProps,
996b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                                                     memReqs.memoryTypeBits,
1009d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth                                                     VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
10168c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                                                     &typeIndex,
10268c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                                                     &heapIndex));
1039d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        alloc->fFlags = 0x0;
1046b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    }
1056b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
1066b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    GrVkHeap* heap = gpu->getHeap(buffer_type_to_heap(type));
1076b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
10868c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth    if (!heap->alloc(memReqs.size, memReqs.alignment, typeIndex, heapIndex, alloc)) {
10968c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth        // if static, try to allocate from non-host-visible non-device-local memory instead
11068c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth        if (dynamic ||
11168c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth            !get_valid_memory_type_index(phDevMemProps, memReqs.memoryTypeBits,
11268c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                                         0, &typeIndex, &heapIndex) ||
11368c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth            !heap->alloc(memReqs.size, memReqs.alignment, typeIndex, heapIndex, alloc)) {
11468c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth            SkDebugf("Failed to alloc buffer\n");
11568c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth            return false;
11668c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth        }
117164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
118164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1199d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    // Bind buffer
1206e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdaniel    VkResult err = GR_VK_CALL(iface, BindBufferMemory(device, buffer,
1211e305ba0d6a4237020d36234e9e286d3b0489401jvanverth                                                      alloc->fMemory, alloc->fOffset));
122164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (err) {
1236b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        SkASSERT_RELEASE(heap->free(*alloc));
124164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
125164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
1266b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
127164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
128164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
129164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1306b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthvoid GrVkMemory::FreeBufferMemory(const GrVkGpu* gpu, GrVkBuffer::Type type,
1316b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                                  const GrVkAlloc& alloc) {
1326b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
1336b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    GrVkHeap* heap = gpu->getHeap(buffer_type_to_heap(type));
1346b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    SkASSERT_RELEASE(heap->free(alloc));
1356b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth}
1366b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
1376b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth// for debugging
1386b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthstatic uint64_t gTotalImageMemory = 0;
1396b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthstatic uint64_t gTotalImageMemoryFullPage = 0;
1406b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
1416b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthconst VkDeviceSize kMaxSmallImageSize = 16 * 1024;
1426b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthconst VkDeviceSize kMinVulkanPageSize = 16 * 1024;
1436b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
1446b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthstatic VkDeviceSize align_size(VkDeviceSize size, VkDeviceSize alignment) {
1456b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    return (size + alignment - 1) & ~(alignment - 1);
1461e305ba0d6a4237020d36234e9e286d3b0489401jvanverth}
1471e305ba0d6a4237020d36234e9e286d3b0489401jvanverth
148164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkMemory::AllocAndBindImageMemory(const GrVkGpu* gpu,
149164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel                                         VkImage image,
1506b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                                         bool linearTiling,
1511e305ba0d6a4237020d36234e9e286d3b0489401jvanverth                                         GrVkAlloc* alloc) {
152e50f3e75392d7be8ae89df8f55b1700100c34ad7jvanverth    const GrVkInterface* iface = gpu->vkInterface();
153164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkDevice device = gpu->device();
154164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
155164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkMemoryRequirements memReqs;
156e50f3e75392d7be8ae89df8f55b1700100c34ad7jvanverth    GR_VK_CALL(iface, GetImageMemoryRequirements(device, image, &memReqs));
157164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
1587378ac8e1e591b6bc3e723cc428a28129886ccd6jvanverth    uint32_t typeIndex = 0;
15968c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth    uint32_t heapIndex = 0;
1606b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    GrVkHeap* heap;
1619d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    const VkPhysicalDeviceMemoryProperties& phDevMemProps = gpu->physicalDeviceMemoryProperties();
1628385a8a44bd06cbd400bc66440466229dc52f33fGreg Daniel    const VkPhysicalDeviceProperties& phDevProps = gpu->physicalDeviceProperties();
1636b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    if (linearTiling) {
1646b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        VkMemoryPropertyFlags desiredMemProps = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
1656b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                                                VK_MEMORY_PROPERTY_HOST_CACHED_BIT;
1669d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        if (!get_valid_memory_type_index(phDevMemProps,
1676b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                                         memReqs.memoryTypeBits,
1686b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                                         desiredMemProps,
16968c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                                         &typeIndex,
17068c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                                         &heapIndex)) {
1719d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth            // some sort of host-visible memory type should always be available
1729d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth            SkASSERT_RELEASE(get_valid_memory_type_index(phDevMemProps,
1736b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                                                         memReqs.memoryTypeBits,
1749d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth                                                         VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
17568c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                                                         &typeIndex,
17668c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                                                         &heapIndex));
1776b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        }
1786b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        heap = gpu->getHeap(GrVkGpu::kLinearImage_Heap);
1799d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        VkMemoryPropertyFlags mpf = phDevMemProps.memoryTypes[typeIndex].propertyFlags;
1809d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        alloc->fFlags = mpf & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ? 0x0
1819d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth                                                                   : GrVkAlloc::kNoncoherent_Flag;
1828385a8a44bd06cbd400bc66440466229dc52f33fGreg Daniel        if (SkToBool(alloc->fFlags & GrVkAlloc::kNoncoherent_Flag)) {
1838385a8a44bd06cbd400bc66440466229dc52f33fGreg Daniel            SkASSERT(SkIsPow2(memReqs.alignment));
1848385a8a44bd06cbd400bc66440466229dc52f33fGreg Daniel            SkASSERT(SkIsPow2(phDevProps.limits.nonCoherentAtomSize));
1858385a8a44bd06cbd400bc66440466229dc52f33fGreg Daniel            memReqs.alignment = SkTMax(memReqs.alignment, phDevProps.limits.nonCoherentAtomSize);
1868385a8a44bd06cbd400bc66440466229dc52f33fGreg Daniel        }
1876b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    } else {
1886b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        // this memory type should always be available
1899d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        SkASSERT_RELEASE(get_valid_memory_type_index(phDevMemProps,
1906b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                                                     memReqs.memoryTypeBits,
1916b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                                                     VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
19268c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                                                     &typeIndex,
19368c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                                                     &heapIndex));
1946b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        if (memReqs.size <= kMaxSmallImageSize) {
1956b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            heap = gpu->getHeap(GrVkGpu::kSmallOptimalImage_Heap);
1966b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        } else {
1976b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            heap = gpu->getHeap(GrVkGpu::kOptimalImage_Heap);
1986b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        }
1999d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        alloc->fFlags = 0x0;
2006b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    }
2016b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
20268c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth    if (!heap->alloc(memReqs.size, memReqs.alignment, typeIndex, heapIndex, alloc)) {
20368c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth        // if optimal, try to allocate from non-host-visible non-device-local memory instead
20468c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth        if (linearTiling ||
20568c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth            !get_valid_memory_type_index(phDevMemProps, memReqs.memoryTypeBits,
20668c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                                         0, &typeIndex, &heapIndex) ||
20768c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth            !heap->alloc(memReqs.size, memReqs.alignment, typeIndex, heapIndex, alloc)) {
20868c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth            SkDebugf("Failed to alloc image\n");
20968c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth            return false;
21068c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth        }
211164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
212164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
2139d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    // Bind image
2141e305ba0d6a4237020d36234e9e286d3b0489401jvanverth    VkResult err = GR_VK_CALL(iface, BindImageMemory(device, image,
2151e305ba0d6a4237020d36234e9e286d3b0489401jvanverth                              alloc->fMemory, alloc->fOffset));
216164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (err) {
2176b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        SkASSERT_RELEASE(heap->free(*alloc));
218164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return false;
219164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
2206b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
2216b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    gTotalImageMemory += alloc->fSize;
2226b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
2236b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    VkDeviceSize pageAlignedSize = align_size(alloc->fSize, kMinVulkanPageSize);
2246b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    gTotalImageMemoryFullPage += pageAlignedSize;
2256b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
226164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return true;
227164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
228164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
2296b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthvoid GrVkMemory::FreeImageMemory(const GrVkGpu* gpu, bool linearTiling,
2306b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                                 const GrVkAlloc& alloc) {
2316b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    GrVkHeap* heap;
2326b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    if (linearTiling) {
2336b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        heap = gpu->getHeap(GrVkGpu::kLinearImage_Heap);
2346b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    } else if (alloc.fSize <= kMaxSmallImageSize) {
2356b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        heap = gpu->getHeap(GrVkGpu::kSmallOptimalImage_Heap);
2366b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    } else {
2376b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        heap = gpu->getHeap(GrVkGpu::kOptimalImage_Heap);
2386b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    }
2396b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    if (!heap->free(alloc)) {
2406b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        // must be an adopted allocation
2416b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        GR_VK_CALL(gpu->vkInterface(), FreeMemory(gpu->device(), alloc.fMemory, nullptr));
2426b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    } else {
2436b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        gTotalImageMemory -= alloc.fSize;
2446b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        VkDeviceSize pageAlignedSize = align_size(alloc.fSize, kMinVulkanPageSize);
2456b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        gTotalImageMemoryFullPage -= pageAlignedSize;
2466b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    }
2471e305ba0d6a4237020d36234e9e286d3b0489401jvanverth}
2481e305ba0d6a4237020d36234e9e286d3b0489401jvanverth
249164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielVkPipelineStageFlags GrVkMemory::LayoutToPipelineStageFlags(const VkImageLayout layout) {
250164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (VK_IMAGE_LAYOUT_GENERAL == layout) {
251164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
252164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout ||
253164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel               VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) {
254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return VK_PIPELINE_STAGE_TRANSFER_BIT;
255164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout ||
256164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel               VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL == layout ||
257164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel               VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL == layout ||
258164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel               VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) {
259bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel        return VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
260164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) {
261164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        return VK_PIPELINE_STAGE_HOST_BIT;
262164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
263164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
264164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED == layout);
265164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
266164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
267164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
268164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielVkAccessFlags GrVkMemory::LayoutToSrcAccessMask(const VkImageLayout layout) {
269164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // Currently we assume we will never being doing any explict shader writes (this doesn't include
270164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // color attachment or depth/stencil writes). So we will ignore the
271164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // VK_MEMORY_OUTPUT_SHADER_WRITE_BIT.
272164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel
273164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // We can only directly access the host memory if we are in preinitialized or general layout,
274164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // and the image is linear.
275164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    // TODO: Add check for linear here so we are not always adding host to general, and we should
276164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    //       only be in preinitialized if we are linear
277164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    VkAccessFlags flags = 0;;
278164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    if (VK_IMAGE_LAYOUT_GENERAL == layout) {
279164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
28019ff1035d3334ffa513c93edce04662bb5ead5bdegdaniel                VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
28119ff1035d3334ffa513c93edce04662bb5ead5bdegdaniel                VK_ACCESS_TRANSFER_WRITE_BIT |
28219ff1035d3334ffa513c93edce04662bb5ead5bdegdaniel                VK_ACCESS_TRANSFER_READ_BIT |
28319ff1035d3334ffa513c93edce04662bb5ead5bdegdaniel                VK_ACCESS_SHADER_READ_BIT |
28419ff1035d3334ffa513c93edce04662bb5ead5bdegdaniel                VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_HOST_READ_BIT;
285164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) {
286c2fde8b2272cf80c79414e01451689ffd971b348egdaniel        flags = VK_ACCESS_HOST_WRITE_BIT;
287164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout) {
288164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
289164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else if (VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL == layout) {
290164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        flags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
291164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else if (VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) {
292164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        flags = VK_ACCESS_TRANSFER_WRITE_BIT;
293164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout) {
294164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        flags = VK_ACCESS_TRANSFER_READ_BIT;
295164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    } else if (VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) {
296164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel        flags = VK_ACCESS_SHADER_READ_BIT;
297164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    }
298164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel    return flags;
299164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel}
3006b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
301e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Danielvoid GrVkMemory::FlushMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc, VkDeviceSize offset,
302e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel                                  VkDeviceSize size) {
3039d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    if (alloc.fFlags & GrVkAlloc::kNoncoherent_Flag) {
304e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel#ifdef SK_DEBUG
305e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel        SkASSERT(offset >= alloc.fOffset);
306e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel        VkDeviceSize alignment = gpu->physicalDeviceProperties().limits.nonCoherentAtomSize;
307e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel        SkASSERT(0 == (offset & (alignment-1)));
308e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel        if (size != VK_WHOLE_SIZE) {
309e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel            SkASSERT(size > 0);
310e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel            SkASSERT(0 == (size & (alignment-1)) ||
311e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel                     (offset + size) == (alloc.fOffset + alloc.fSize));
312e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel            SkASSERT(offset + size <= alloc.fOffset + alloc.fSize);
313e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel        }
314e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel#endif
315e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel
3169d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        VkMappedMemoryRange mappedMemoryRange;
3179d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        memset(&mappedMemoryRange, 0, sizeof(VkMappedMemoryRange));
3189d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        mappedMemoryRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
3199d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        mappedMemoryRange.memory = alloc.fMemory;
320e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel        mappedMemoryRange.offset = offset;
321e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel        mappedMemoryRange.size = size;
3229d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        GR_VK_CALL(gpu->vkInterface(), FlushMappedMemoryRanges(gpu->device(),
3239d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth                                                               1, &mappedMemoryRange));
3249d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    }
3259d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth}
3269d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth
327e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Danielvoid GrVkMemory::InvalidateMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc,
328e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel                                       VkDeviceSize offset, VkDeviceSize size) {
3299d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    if (alloc.fFlags & GrVkAlloc::kNoncoherent_Flag) {
330e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel#ifdef SK_DEBUG
331e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel        SkASSERT(offset >= alloc.fOffset);
332e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel        VkDeviceSize alignment = gpu->physicalDeviceProperties().limits.nonCoherentAtomSize;
333e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel        SkASSERT(0 == (offset & (alignment-1)));
334e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel        if (size != VK_WHOLE_SIZE) {
335e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel            SkASSERT(size > 0);
336e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel            SkASSERT(0 == (size & (alignment-1)) ||
337e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel                     (offset + size) == (alloc.fOffset + alloc.fSize));
338e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel            SkASSERT(offset + size <= alloc.fOffset + alloc.fSize);
339e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel        }
340e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel#endif
341e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel
3429d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        VkMappedMemoryRange mappedMemoryRange;
3439d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        memset(&mappedMemoryRange, 0, sizeof(VkMappedMemoryRange));
3449d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        mappedMemoryRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
3459d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        mappedMemoryRange.memory = alloc.fMemory;
346e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel        mappedMemoryRange.offset = offset;
347e35a99ed706dcd0407c7ca4373ed97d21d988069Greg Daniel        mappedMemoryRange.size = size;
3489d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth        GR_VK_CALL(gpu->vkInterface(), InvalidateMappedMemoryRanges(gpu->device(),
3499d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth                                                               1, &mappedMemoryRange));
3509d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth    }
3519d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth}
3529d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth
35382356cc41f360c607a1612cb9aead2423c0846a0jvanverthbool GrVkFreeListAlloc::alloc(VkDeviceSize requestedSize,
35482356cc41f360c607a1612cb9aead2423c0846a0jvanverth                              VkDeviceSize* allocOffset, VkDeviceSize* allocSize) {
35582356cc41f360c607a1612cb9aead2423c0846a0jvanverth    VkDeviceSize alignedSize = align_size(requestedSize, fAlignment);
3566b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
3576b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    // find the smallest block big enough for our allocation
3586b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    FreeList::Iter iter = fFreeList.headIter();
3596b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    FreeList::Iter bestFitIter;
3606b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    VkDeviceSize   bestFitSize = fSize + 1;
3616b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    VkDeviceSize   secondLargestSize = 0;
3626b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    VkDeviceSize   secondLargestOffset = 0;
3636b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    while (iter.get()) {
3646b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        Block* block = iter.get();
3656b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        // need to adjust size to match desired alignment
3666b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        SkASSERT(align_size(block->fOffset, fAlignment) - block->fOffset == 0);
3676b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        if (block->fSize >= alignedSize && block->fSize < bestFitSize) {
3686b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            bestFitIter = iter;
3696b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            bestFitSize = block->fSize;
3706b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        }
3716b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        if (secondLargestSize < block->fSize && block->fOffset != fLargestBlockOffset) {
3726b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            secondLargestSize = block->fSize;
3736b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            secondLargestOffset = block->fOffset;
3746b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        }
3756b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        iter.next();
3766b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    }
3776b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    SkASSERT(secondLargestSize <= fLargestBlockSize);
3786b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
3796b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    Block* bestFit = bestFitIter.get();
3806b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    if (bestFit) {
3816b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        SkASSERT(align_size(bestFit->fOffset, fAlignment) == bestFit->fOffset);
38282356cc41f360c607a1612cb9aead2423c0846a0jvanverth        *allocOffset = bestFit->fOffset;
38382356cc41f360c607a1612cb9aead2423c0846a0jvanverth        *allocSize = alignedSize;
3846b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        // adjust or remove current block
3856b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        VkDeviceSize originalBestFitOffset = bestFit->fOffset;
3866b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        if (bestFit->fSize > alignedSize) {
3876b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            bestFit->fOffset += alignedSize;
3886b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            bestFit->fSize -= alignedSize;
3896b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            if (fLargestBlockOffset == originalBestFitOffset) {
3906b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                if (bestFit->fSize >= secondLargestSize) {
3916b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                    fLargestBlockSize = bestFit->fSize;
3926b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                    fLargestBlockOffset = bestFit->fOffset;
3936b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                } else {
3946b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                    fLargestBlockSize = secondLargestSize;
3956b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                    fLargestBlockOffset = secondLargestOffset;
3966b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                }
3976b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            }
3986b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth#ifdef SK_DEBUG
3996b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            VkDeviceSize largestSize = 0;
4006b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            iter = fFreeList.headIter();
4016b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            while (iter.get()) {
4026b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                Block* block = iter.get();
4036b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                if (largestSize < block->fSize) {
4046b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                    largestSize = block->fSize;
4056b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                }
4066b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                iter.next();
4076b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            }
408d6562000efca50bc2bfddae8dcb69dce6b8c0950caryclark            SkASSERT(largestSize == fLargestBlockSize);
4096b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth#endif
4106b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        } else {
4116b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            SkASSERT(bestFit->fSize == alignedSize);
4126b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            if (fLargestBlockOffset == originalBestFitOffset) {
4136b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                fLargestBlockSize = secondLargestSize;
4146b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                fLargestBlockOffset = secondLargestOffset;
4156b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            }
4166b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            fFreeList.remove(bestFit);
4176b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth#ifdef SK_DEBUG
4186b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            VkDeviceSize largestSize = 0;
4196b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            iter = fFreeList.headIter();
4206b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            while (iter.get()) {
4216b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                Block* block = iter.get();
4226b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                if (largestSize < block->fSize) {
4236b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                    largestSize = block->fSize;
4246b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                }
4256b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                iter.next();
4266b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            }
4276b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            SkASSERT(largestSize == fLargestBlockSize);
4286b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth#endif
4296b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        }
4306b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        fFreeSize -= alignedSize;
4316e46eea63efdede18525ff7b7097e611d3986d0degdaniel        SkASSERT(*allocSize > 0);
4326b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
4336b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        return true;
4346b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    }
43582356cc41f360c607a1612cb9aead2423c0846a0jvanverth
4366b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    SkDebugf("Can't allocate %d bytes, %d bytes available, largest free block %d\n", alignedSize, fFreeSize, fLargestBlockSize);
4376b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
4386b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    return false;
4396b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth}
4406b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
44182356cc41f360c607a1612cb9aead2423c0846a0jvanverthvoid GrVkFreeListAlloc::free(VkDeviceSize allocOffset, VkDeviceSize allocSize) {
4426b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    // find the block right after this allocation
4436b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    FreeList::Iter iter = fFreeList.headIter();
444d6f8034b886d59a3c722bf3932195143f2bf5eb8jvanverth    FreeList::Iter prev;
44582356cc41f360c607a1612cb9aead2423c0846a0jvanverth    while (iter.get() && iter.get()->fOffset < allocOffset) {
446d6f8034b886d59a3c722bf3932195143f2bf5eb8jvanverth        prev = iter;
4476b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        iter.next();
44882356cc41f360c607a1612cb9aead2423c0846a0jvanverth    }
4496b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    // we have four cases:
4506b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    // we exactly follow the previous one
4516b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    Block* block;
45282356cc41f360c607a1612cb9aead2423c0846a0jvanverth    if (prev.get() && prev.get()->fOffset + prev.get()->fSize == allocOffset) {
4536b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        block = prev.get();
45482356cc41f360c607a1612cb9aead2423c0846a0jvanverth        block->fSize += allocSize;
4556b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        if (block->fOffset == fLargestBlockOffset) {
4566b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            fLargestBlockSize = block->fSize;
4576b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        }
4586b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        // and additionally we may exactly precede the next one
45982356cc41f360c607a1612cb9aead2423c0846a0jvanverth        if (iter.get() && iter.get()->fOffset == allocOffset + allocSize) {
4606b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            block->fSize += iter.get()->fSize;
4616b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            if (iter.get()->fOffset == fLargestBlockOffset) {
4626b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                fLargestBlockOffset = block->fOffset;
4636b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                fLargestBlockSize = block->fSize;
4646b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            }
4656b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            fFreeList.remove(iter.get());
4666b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        }
4676b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    // or we only exactly proceed the next one
46882356cc41f360c607a1612cb9aead2423c0846a0jvanverth    } else if (iter.get() && iter.get()->fOffset == allocOffset + allocSize) {
4696b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        block = iter.get();
47082356cc41f360c607a1612cb9aead2423c0846a0jvanverth        block->fSize += allocSize;
4716b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        if (block->fOffset == fLargestBlockOffset) {
47282356cc41f360c607a1612cb9aead2423c0846a0jvanverth            fLargestBlockOffset = allocOffset;
4736b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            fLargestBlockSize = block->fSize;
4746b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        }
47582356cc41f360c607a1612cb9aead2423c0846a0jvanverth        block->fOffset = allocOffset;
4766b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    // or we fall somewhere in between, with gaps
4776b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    } else {
4786b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        block = fFreeList.addBefore(iter);
47982356cc41f360c607a1612cb9aead2423c0846a0jvanverth        block->fOffset = allocOffset;
48082356cc41f360c607a1612cb9aead2423c0846a0jvanverth        block->fSize = allocSize;
4816b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    }
48282356cc41f360c607a1612cb9aead2423c0846a0jvanverth    fFreeSize += allocSize;
4836b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    if (block->fSize > fLargestBlockSize) {
4846b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        fLargestBlockSize = block->fSize;
4856b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        fLargestBlockOffset = block->fOffset;
4866b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    }
4876b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
4886b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth#ifdef SK_DEBUG
4896b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    VkDeviceSize   largestSize = 0;
4906b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    iter = fFreeList.headIter();
4916b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    while (iter.get()) {
4926b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        Block* block = iter.get();
4936b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        if (largestSize < block->fSize) {
4946b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            largestSize = block->fSize;
4956b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        }
4966b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        iter.next();
4976b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    }
4986b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    SkASSERT(fLargestBlockSize == largestSize);
4996b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth#endif
5006b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth}
5016b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
50268c3d30702c8af5ae249c78b30a9ea2351f875edjvanverthGrVkSubHeap::GrVkSubHeap(const GrVkGpu* gpu, uint32_t memoryTypeIndex, uint32_t heapIndex,
50382356cc41f360c607a1612cb9aead2423c0846a0jvanverth                         VkDeviceSize size, VkDeviceSize alignment)
50482356cc41f360c607a1612cb9aead2423c0846a0jvanverth    : INHERITED(size, alignment)
50582356cc41f360c607a1612cb9aead2423c0846a0jvanverth    , fGpu(gpu)
50668c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#ifdef SK_DEBUG
50768c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth    , fHeapIndex(heapIndex)
50868c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#endif
509ae6e4869c94596eb3bf5069888b32ab06199aec0jvanverth    , fMemoryTypeIndex(memoryTypeIndex) {
51082356cc41f360c607a1612cb9aead2423c0846a0jvanverth
51182356cc41f360c607a1612cb9aead2423c0846a0jvanverth    VkMemoryAllocateInfo allocInfo = {
51282356cc41f360c607a1612cb9aead2423c0846a0jvanverth        VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,      // sType
513a93a14a99816d25b773f0b12868143702baf44bfBen Wagner        nullptr,                                     // pNext
51482356cc41f360c607a1612cb9aead2423c0846a0jvanverth        size,                                        // allocationSize
51582356cc41f360c607a1612cb9aead2423c0846a0jvanverth        memoryTypeIndex,                             // memoryTypeIndex
51682356cc41f360c607a1612cb9aead2423c0846a0jvanverth    };
51782356cc41f360c607a1612cb9aead2423c0846a0jvanverth
51882356cc41f360c607a1612cb9aead2423c0846a0jvanverth    VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateMemory(gpu->device(),
51982356cc41f360c607a1612cb9aead2423c0846a0jvanverth                                                                 &allocInfo,
52082356cc41f360c607a1612cb9aead2423c0846a0jvanverth                                                                 nullptr,
52182356cc41f360c607a1612cb9aead2423c0846a0jvanverth                                                                 &fAlloc));
52282356cc41f360c607a1612cb9aead2423c0846a0jvanverth    if (VK_SUCCESS != err) {
52382356cc41f360c607a1612cb9aead2423c0846a0jvanverth        this->reset();
52463fd760a37905c45d26fc3d49cac261fad1b4808Ben Wagner    }
52568c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#ifdef SK_DEBUG
52668c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth    else {
52768c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth        gHeapUsage[heapIndex] += size;
52882356cc41f360c607a1612cb9aead2423c0846a0jvanverth    }
52968c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#endif
53082356cc41f360c607a1612cb9aead2423c0846a0jvanverth}
53182356cc41f360c607a1612cb9aead2423c0846a0jvanverth
53282356cc41f360c607a1612cb9aead2423c0846a0jvanverthGrVkSubHeap::~GrVkSubHeap() {
53382356cc41f360c607a1612cb9aead2423c0846a0jvanverth    const GrVkInterface* iface = fGpu->vkInterface();
53482356cc41f360c607a1612cb9aead2423c0846a0jvanverth    GR_VK_CALL(iface, FreeMemory(fGpu->device(), fAlloc, nullptr));
53568c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#ifdef SK_DEBUG
53668c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth    gHeapUsage[fHeapIndex] -= fSize;
53768c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#endif
53882356cc41f360c607a1612cb9aead2423c0846a0jvanverth}
53982356cc41f360c607a1612cb9aead2423c0846a0jvanverth
54082356cc41f360c607a1612cb9aead2423c0846a0jvanverthbool GrVkSubHeap::alloc(VkDeviceSize size, GrVkAlloc* alloc) {
54182356cc41f360c607a1612cb9aead2423c0846a0jvanverth    alloc->fMemory = fAlloc;
54282356cc41f360c607a1612cb9aead2423c0846a0jvanverth    return INHERITED::alloc(size, &alloc->fOffset, &alloc->fSize);
54382356cc41f360c607a1612cb9aead2423c0846a0jvanverth}
54482356cc41f360c607a1612cb9aead2423c0846a0jvanverth
54582356cc41f360c607a1612cb9aead2423c0846a0jvanverthvoid GrVkSubHeap::free(const GrVkAlloc& alloc) {
54682356cc41f360c607a1612cb9aead2423c0846a0jvanverth    SkASSERT(alloc.fMemory == fAlloc);
54782356cc41f360c607a1612cb9aead2423c0846a0jvanverth
54882356cc41f360c607a1612cb9aead2423c0846a0jvanverth    INHERITED::free(alloc.fOffset, alloc.fSize);
5496b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth}
5506b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
5516e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdanielbool GrVkHeap::subAlloc(VkDeviceSize size, VkDeviceSize alignment,
55268c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                        uint32_t memoryTypeIndex, uint32_t heapIndex, GrVkAlloc* alloc) {
5536b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    VkDeviceSize alignedSize = align_size(size, alignment);
5546b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
5556dc3af4499893045f7b187d5d85bc785b6e44baajvanverth    // if requested is larger than our subheap allocation, just alloc directly
5566dc3af4499893045f7b187d5d85bc785b6e44baajvanverth    if (alignedSize > fSubHeapSize) {
5576dc3af4499893045f7b187d5d85bc785b6e44baajvanverth        VkMemoryAllocateInfo allocInfo = {
5586dc3af4499893045f7b187d5d85bc785b6e44baajvanverth            VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,      // sType
559a93a14a99816d25b773f0b12868143702baf44bfBen Wagner            nullptr,                                     // pNext
5608385a8a44bd06cbd400bc66440466229dc52f33fGreg Daniel            alignedSize,                                 // allocationSize
5616dc3af4499893045f7b187d5d85bc785b6e44baajvanverth            memoryTypeIndex,                             // memoryTypeIndex
5626dc3af4499893045f7b187d5d85bc785b6e44baajvanverth        };
5636dc3af4499893045f7b187d5d85bc785b6e44baajvanverth
5646dc3af4499893045f7b187d5d85bc785b6e44baajvanverth        VkResult err = GR_VK_CALL(fGpu->vkInterface(), AllocateMemory(fGpu->device(),
5656dc3af4499893045f7b187d5d85bc785b6e44baajvanverth                                                                      &allocInfo,
5666dc3af4499893045f7b187d5d85bc785b6e44baajvanverth                                                                      nullptr,
5676dc3af4499893045f7b187d5d85bc785b6e44baajvanverth                                                                      &alloc->fMemory));
5686dc3af4499893045f7b187d5d85bc785b6e44baajvanverth        if (VK_SUCCESS != err) {
5696dc3af4499893045f7b187d5d85bc785b6e44baajvanverth            return false;
5706dc3af4499893045f7b187d5d85bc785b6e44baajvanverth        }
5716dc3af4499893045f7b187d5d85bc785b6e44baajvanverth        alloc->fOffset = 0;
5728385a8a44bd06cbd400bc66440466229dc52f33fGreg Daniel        alloc->fSize = alignedSize;
5738385a8a44bd06cbd400bc66440466229dc52f33fGreg Daniel        alloc->fUsesSystemHeap = true;
57468c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#ifdef SK_DEBUG
57568c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth        gHeapUsage[VK_MAX_MEMORY_HEAPS] += alignedSize;
57668c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#endif
5776e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdaniel
5786dc3af4499893045f7b187d5d85bc785b6e44baajvanverth        return true;
5796dc3af4499893045f7b187d5d85bc785b6e44baajvanverth    }
5806dc3af4499893045f7b187d5d85bc785b6e44baajvanverth
5816b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    // first try to find a subheap that fits our allocation request
5826b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    int bestFitIndex = -1;
5836b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    VkDeviceSize bestFitSize = 0x7FFFFFFF;
5846b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    for (auto i = 0; i < fSubHeaps.count(); ++i) {
5856e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdaniel        if (fSubHeaps[i]->memoryTypeIndex() == memoryTypeIndex &&
5866e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdaniel            fSubHeaps[i]->alignment() == alignment) {
5876b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            VkDeviceSize heapSize = fSubHeaps[i]->largestBlockSize();
588d6f8034b886d59a3c722bf3932195143f2bf5eb8jvanverth            if (heapSize >= alignedSize && heapSize < bestFitSize) {
5896b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                bestFitIndex = i;
5906b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                bestFitSize = heapSize;
5916b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            }
5926b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        }
5936b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    }
5946b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
5956b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    if (bestFitIndex >= 0) {
5966b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        SkASSERT(fSubHeaps[bestFitIndex]->alignment() == alignment);
5976b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        if (fSubHeaps[bestFitIndex]->alloc(size, alloc)) {
5986b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            fUsedSize += alloc->fSize;
5996b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            return true;
6006b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        }
6016b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        return false;
6026dc3af4499893045f7b187d5d85bc785b6e44baajvanverth    }
6036b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
6046b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    // need to allocate a new subheap
605145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagner    std::unique_ptr<GrVkSubHeap>& subHeap = fSubHeaps.push_back();
60668c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth    subHeap.reset(new GrVkSubHeap(fGpu, memoryTypeIndex, heapIndex, fSubHeapSize, alignment));
6076dc3af4499893045f7b187d5d85bc785b6e44baajvanverth    // try to recover from failed allocation by only allocating what we need
6086dc3af4499893045f7b187d5d85bc785b6e44baajvanverth    if (subHeap->size() == 0) {
6096dc3af4499893045f7b187d5d85bc785b6e44baajvanverth        VkDeviceSize alignedSize = align_size(size, alignment);
61068c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth        subHeap.reset(new GrVkSubHeap(fGpu, memoryTypeIndex, heapIndex, alignedSize, alignment));
6116dc3af4499893045f7b187d5d85bc785b6e44baajvanverth        if (subHeap->size() == 0) {
6126dc3af4499893045f7b187d5d85bc785b6e44baajvanverth            return false;
6136dc3af4499893045f7b187d5d85bc785b6e44baajvanverth        }
6146dc3af4499893045f7b187d5d85bc785b6e44baajvanverth    }
6156b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fAllocSize += fSubHeapSize;
6166b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    if (subHeap->alloc(size, alloc)) {
6176b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        fUsedSize += alloc->fSize;
6186b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        return true;
6196b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    }
6206b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
6216b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    return false;
6226b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth}
6236b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
6246e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdanielbool GrVkHeap::singleAlloc(VkDeviceSize size, VkDeviceSize alignment,
62568c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth                           uint32_t memoryTypeIndex, uint32_t heapIndex, GrVkAlloc* alloc) {
6266b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    VkDeviceSize alignedSize = align_size(size, alignment);
6276b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
6286b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    // first try to find an unallocated subheap that fits our allocation request
6296b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    int bestFitIndex = -1;
6306b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    VkDeviceSize bestFitSize = 0x7FFFFFFF;
6316b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    for (auto i = 0; i < fSubHeaps.count(); ++i) {
6326e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdaniel        if (fSubHeaps[i]->memoryTypeIndex() == memoryTypeIndex &&
6336e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdaniel            fSubHeaps[i]->alignment() == alignment &&
6346e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdaniel            fSubHeaps[i]->unallocated()) {
6356b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            VkDeviceSize heapSize = fSubHeaps[i]->size();
636d6f8034b886d59a3c722bf3932195143f2bf5eb8jvanverth            if (heapSize >= alignedSize && heapSize < bestFitSize) {
6376b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                bestFitIndex = i;
6386b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth                bestFitSize = heapSize;
6396b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            }
6406b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        }
6416b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    }
6426b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
6436b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    if (bestFitIndex >= 0) {
6446b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        SkASSERT(fSubHeaps[bestFitIndex]->alignment() == alignment);
6456b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        if (fSubHeaps[bestFitIndex]->alloc(size, alloc)) {
6466b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            fUsedSize += alloc->fSize;
6476b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            return true;
6486b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        }
6496b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        return false;
6506b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    }
6516b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
6526b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    // need to allocate a new subheap
653145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagner    std::unique_ptr<GrVkSubHeap>& subHeap = fSubHeaps.push_back();
65468c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth    subHeap.reset(new GrVkSubHeap(fGpu, memoryTypeIndex, heapIndex, alignedSize, alignment));
6556b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    fAllocSize += alignedSize;
6566b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    if (subHeap->alloc(size, alloc)) {
6576b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        fUsedSize += alloc->fSize;
6586b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        return true;
6596b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    }
6606b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
6616b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    return false;
6626b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth}
6636b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
6646b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthbool GrVkHeap::free(const GrVkAlloc& alloc) {
6656dc3af4499893045f7b187d5d85bc785b6e44baajvanverth    // a size of 0 means we're using the system heap
6668385a8a44bd06cbd400bc66440466229dc52f33fGreg Daniel    if (alloc.fUsesSystemHeap) {
6676dc3af4499893045f7b187d5d85bc785b6e44baajvanverth        const GrVkInterface* iface = fGpu->vkInterface();
6686dc3af4499893045f7b187d5d85bc785b6e44baajvanverth        GR_VK_CALL(iface, FreeMemory(fGpu->device(), alloc.fMemory, nullptr));
6696dc3af4499893045f7b187d5d85bc785b6e44baajvanverth        return true;
6706dc3af4499893045f7b187d5d85bc785b6e44baajvanverth    }
6716dc3af4499893045f7b187d5d85bc785b6e44baajvanverth
6726b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    for (auto i = 0; i < fSubHeaps.count(); ++i) {
6736b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        if (fSubHeaps[i]->memory() == alloc.fMemory) {
6746b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            fSubHeaps[i]->free(alloc);
6756b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            fUsedSize -= alloc.fSize;
6766b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth            return true;
6776b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth        }
6786b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    }
6796b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
6806b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth    return false;
6816b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth}
6826b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
6836b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth
684