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