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, 436b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GrVkGpu::kCopyReadBuffer_Heap, 446b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GrVkGpu::kCopyWriteBuffer_Heap, 45164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel }; 466b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GR_STATIC_ASSERT(0 == GrVkBuffer::kVertex_Type); 476b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GR_STATIC_ASSERT(1 == GrVkBuffer::kIndex_Type); 486b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GR_STATIC_ASSERT(2 == GrVkBuffer::kUniform_Type); 496b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GR_STATIC_ASSERT(3 == GrVkBuffer::kCopyRead_Type); 506b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GR_STATIC_ASSERT(4 == GrVkBuffer::kCopyWrite_Type); 51164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 526b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth return kBufferToHeap[type]; 53164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 54164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 55164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkMemory::AllocAndBindBufferMemory(const GrVkGpu* gpu, 56164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkBuffer buffer, 576b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GrVkBuffer::Type type, 58a584de966a4f7ab71f3f07077cf1e226def9d730jvanverth bool dynamic, 591e305ba0d6a4237020d36234e9e286d3b0489401jvanverth GrVkAlloc* alloc) { 60e50f3e75392d7be8ae89df8f55b1700100c34ad7jvanverth const GrVkInterface* iface = gpu->vkInterface(); 61164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkDevice device = gpu->device(); 62164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 63164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkMemoryRequirements memReqs; 64e50f3e75392d7be8ae89df8f55b1700100c34ad7jvanverth GR_VK_CALL(iface, GetBufferMemoryRequirements(device, buffer, &memReqs)); 65164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 667378ac8e1e591b6bc3e723cc428a28129886ccd6jvanverth uint32_t typeIndex = 0; 6768c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth uint32_t heapIndex = 0; 689d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth const VkPhysicalDeviceMemoryProperties& phDevMemProps = gpu->physicalDeviceMemoryProperties(); 699d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth if (dynamic) { 709d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth // try to get cached and ideally non-coherent memory first 719d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth if (!get_valid_memory_type_index(phDevMemProps, 729d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth memReqs.memoryTypeBits, 739d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | 749d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth VK_MEMORY_PROPERTY_HOST_CACHED_BIT, 7568c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth &typeIndex, 7668c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth &heapIndex)) { 779d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth // some sort of host-visible memory type should always be available for dynamic buffers 789d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth SkASSERT_RELEASE(get_valid_memory_type_index(phDevMemProps, 799d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth memReqs.memoryTypeBits, 809d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 8168c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth &typeIndex, 8268c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth &heapIndex)); 839d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth } 849d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth 859d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth VkMemoryPropertyFlags mpf = phDevMemProps.memoryTypes[typeIndex].propertyFlags; 869d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth alloc->fFlags = mpf & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ? 0x0 879d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth : GrVkAlloc::kNoncoherent_Flag; 889d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth } else { 899d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth // device-local memory should always be available for static buffers 909d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth SkASSERT_RELEASE(get_valid_memory_type_index(phDevMemProps, 916b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth memReqs.memoryTypeBits, 929d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 9368c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth &typeIndex, 9468c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth &heapIndex)); 959d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth alloc->fFlags = 0x0; 966b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 976b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 986b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GrVkHeap* heap = gpu->getHeap(buffer_type_to_heap(type)); 996b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 10068c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth if (!heap->alloc(memReqs.size, memReqs.alignment, typeIndex, heapIndex, alloc)) { 10168c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth // if static, try to allocate from non-host-visible non-device-local memory instead 10268c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth if (dynamic || 10368c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth !get_valid_memory_type_index(phDevMemProps, memReqs.memoryTypeBits, 10468c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth 0, &typeIndex, &heapIndex) || 10568c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth !heap->alloc(memReqs.size, memReqs.alignment, typeIndex, heapIndex, alloc)) { 10668c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth SkDebugf("Failed to alloc buffer\n"); 10768c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth return false; 10868c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth } 109164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 110164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1119d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth // Bind buffer 1126e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdaniel VkResult err = GR_VK_CALL(iface, BindBufferMemory(device, buffer, 1131e305ba0d6a4237020d36234e9e286d3b0489401jvanverth alloc->fMemory, alloc->fOffset)); 114164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (err) { 1156b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth SkASSERT_RELEASE(heap->free(*alloc)); 116164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 117164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 1186b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 119164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return true; 120164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 121164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1226b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthvoid GrVkMemory::FreeBufferMemory(const GrVkGpu* gpu, GrVkBuffer::Type type, 1236b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth const GrVkAlloc& alloc) { 1246b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 1256b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GrVkHeap* heap = gpu->getHeap(buffer_type_to_heap(type)); 1266b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth SkASSERT_RELEASE(heap->free(alloc)); 1276b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth} 1286b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 1296b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth// for debugging 1306b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthstatic uint64_t gTotalImageMemory = 0; 1316b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthstatic uint64_t gTotalImageMemoryFullPage = 0; 1326b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 1336b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthconst VkDeviceSize kMaxSmallImageSize = 16 * 1024; 1346b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthconst VkDeviceSize kMinVulkanPageSize = 16 * 1024; 1356b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 1366b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthstatic VkDeviceSize align_size(VkDeviceSize size, VkDeviceSize alignment) { 1376b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth return (size + alignment - 1) & ~(alignment - 1); 1381e305ba0d6a4237020d36234e9e286d3b0489401jvanverth} 1391e305ba0d6a4237020d36234e9e286d3b0489401jvanverth 140164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Danielbool GrVkMemory::AllocAndBindImageMemory(const GrVkGpu* gpu, 141164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkImage image, 1426b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth bool linearTiling, 1431e305ba0d6a4237020d36234e9e286d3b0489401jvanverth GrVkAlloc* alloc) { 144e50f3e75392d7be8ae89df8f55b1700100c34ad7jvanverth const GrVkInterface* iface = gpu->vkInterface(); 145164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkDevice device = gpu->device(); 146164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 147164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkMemoryRequirements memReqs; 148e50f3e75392d7be8ae89df8f55b1700100c34ad7jvanverth GR_VK_CALL(iface, GetImageMemoryRequirements(device, image, &memReqs)); 149164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1507378ac8e1e591b6bc3e723cc428a28129886ccd6jvanverth uint32_t typeIndex = 0; 15168c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth uint32_t heapIndex = 0; 1526b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GrVkHeap* heap; 1539d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth const VkPhysicalDeviceMemoryProperties& phDevMemProps = gpu->physicalDeviceMemoryProperties(); 1546b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (linearTiling) { 1556b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VkMemoryPropertyFlags desiredMemProps = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | 1566b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VK_MEMORY_PROPERTY_HOST_CACHED_BIT; 1579d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth if (!get_valid_memory_type_index(phDevMemProps, 1586b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth memReqs.memoryTypeBits, 1596b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth desiredMemProps, 16068c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth &typeIndex, 16168c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth &heapIndex)) { 1629d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth // some sort of host-visible memory type should always be available 1639d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth SkASSERT_RELEASE(get_valid_memory_type_index(phDevMemProps, 1646b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth memReqs.memoryTypeBits, 1659d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, 16668c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth &typeIndex, 16768c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth &heapIndex)); 1686b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 1696b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth heap = gpu->getHeap(GrVkGpu::kLinearImage_Heap); 1709d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth VkMemoryPropertyFlags mpf = phDevMemProps.memoryTypes[typeIndex].propertyFlags; 1719d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth alloc->fFlags = mpf & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT ? 0x0 1729d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth : GrVkAlloc::kNoncoherent_Flag; 1736b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } else { 1746b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth // this memory type should always be available 1759d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth SkASSERT_RELEASE(get_valid_memory_type_index(phDevMemProps, 1766b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth memReqs.memoryTypeBits, 1776b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 17868c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth &typeIndex, 17968c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth &heapIndex)); 1806b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (memReqs.size <= kMaxSmallImageSize) { 1816b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth heap = gpu->getHeap(GrVkGpu::kSmallOptimalImage_Heap); 1826b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } else { 1836b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth heap = gpu->getHeap(GrVkGpu::kOptimalImage_Heap); 1846b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 1859d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth alloc->fFlags = 0x0; 1866b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 1876b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 18868c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth if (!heap->alloc(memReqs.size, memReqs.alignment, typeIndex, heapIndex, alloc)) { 18968c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth // if optimal, try to allocate from non-host-visible non-device-local memory instead 19068c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth if (linearTiling || 19168c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth !get_valid_memory_type_index(phDevMemProps, memReqs.memoryTypeBits, 19268c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth 0, &typeIndex, &heapIndex) || 19368c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth !heap->alloc(memReqs.size, memReqs.alignment, typeIndex, heapIndex, alloc)) { 19468c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth SkDebugf("Failed to alloc image\n"); 19568c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth return false; 19668c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth } 197164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 198164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 1999d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth // Bind image 2001e305ba0d6a4237020d36234e9e286d3b0489401jvanverth VkResult err = GR_VK_CALL(iface, BindImageMemory(device, image, 2011e305ba0d6a4237020d36234e9e286d3b0489401jvanverth alloc->fMemory, alloc->fOffset)); 202164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (err) { 2036b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth SkASSERT_RELEASE(heap->free(*alloc)); 204164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return false; 205164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 2066b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 2076b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth gTotalImageMemory += alloc->fSize; 2086b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 2096b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VkDeviceSize pageAlignedSize = align_size(alloc->fSize, kMinVulkanPageSize); 2106b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth gTotalImageMemoryFullPage += pageAlignedSize; 2116b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 212164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return true; 213164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 214164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 2156b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthvoid GrVkMemory::FreeImageMemory(const GrVkGpu* gpu, bool linearTiling, 2166b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth const GrVkAlloc& alloc) { 2176b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GrVkHeap* heap; 2186b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (linearTiling) { 2196b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth heap = gpu->getHeap(GrVkGpu::kLinearImage_Heap); 2206b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } else if (alloc.fSize <= kMaxSmallImageSize) { 2216b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth heap = gpu->getHeap(GrVkGpu::kSmallOptimalImage_Heap); 2226b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } else { 2236b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth heap = gpu->getHeap(GrVkGpu::kOptimalImage_Heap); 2246b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 2256b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (!heap->free(alloc)) { 2266b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth // must be an adopted allocation 2276b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth GR_VK_CALL(gpu->vkInterface(), FreeMemory(gpu->device(), alloc.fMemory, nullptr)); 2286b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } else { 2296b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth gTotalImageMemory -= alloc.fSize; 2306b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VkDeviceSize pageAlignedSize = align_size(alloc.fSize, kMinVulkanPageSize); 2316b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth gTotalImageMemoryFullPage -= pageAlignedSize; 2326b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 2331e305ba0d6a4237020d36234e9e286d3b0489401jvanverth} 2341e305ba0d6a4237020d36234e9e286d3b0489401jvanverth 235164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielVkPipelineStageFlags GrVkMemory::LayoutToPipelineStageFlags(const VkImageLayout layout) { 236164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (VK_IMAGE_LAYOUT_GENERAL == layout) { 237164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; 238164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout || 239164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) { 240164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return VK_PIPELINE_STAGE_TRANSFER_BIT; 241164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout || 242164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL == layout || 243164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL == layout || 244164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) { 245bc9b2963bf9e39c47ae5c3ab94b8503b476f4f0eegdaniel return VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT; 246164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) { 247164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return VK_PIPELINE_STAGE_HOST_BIT; 248164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 249164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 250164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel SkASSERT(VK_IMAGE_LAYOUT_UNDEFINED == layout); 251164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT; 252164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 253164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 254164a9f061c5186ae931cc23a3c73f32472e80ff5Greg DanielVkAccessFlags GrVkMemory::LayoutToSrcAccessMask(const VkImageLayout layout) { 255164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // Currently we assume we will never being doing any explict shader writes (this doesn't include 256164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // color attachment or depth/stencil writes). So we will ignore the 257164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // VK_MEMORY_OUTPUT_SHADER_WRITE_BIT. 258164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel 259164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // We can only directly access the host memory if we are in preinitialized or general layout, 260164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // and the image is linear. 261164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // TODO: Add check for linear here so we are not always adding host to general, and we should 262164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel // only be in preinitialized if we are linear 263164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel VkAccessFlags flags = 0;; 264164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel if (VK_IMAGE_LAYOUT_GENERAL == layout) { 265164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | 26619ff1035d3334ffa513c93edce04662bb5ead5bdegdaniel VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | 26719ff1035d3334ffa513c93edce04662bb5ead5bdegdaniel VK_ACCESS_TRANSFER_WRITE_BIT | 26819ff1035d3334ffa513c93edce04662bb5ead5bdegdaniel VK_ACCESS_TRANSFER_READ_BIT | 26919ff1035d3334ffa513c93edce04662bb5ead5bdegdaniel VK_ACCESS_SHADER_READ_BIT | 27019ff1035d3334ffa513c93edce04662bb5ead5bdegdaniel VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_HOST_READ_BIT; 271164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else if (VK_IMAGE_LAYOUT_PREINITIALIZED == layout) { 272c2fde8b2272cf80c79414e01451689ffd971b348egdaniel flags = VK_ACCESS_HOST_WRITE_BIT; 273164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else if (VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL == layout) { 274164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel flags = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 275164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else if (VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL == layout) { 276164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel flags = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; 277164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else if (VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL == layout) { 278164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel flags = VK_ACCESS_TRANSFER_WRITE_BIT; 279164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else if (VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL == layout) { 280164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel flags = VK_ACCESS_TRANSFER_READ_BIT; 281164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } else if (VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL == layout) { 282164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel flags = VK_ACCESS_SHADER_READ_BIT; 283164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel } 284164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel return flags; 285164a9f061c5186ae931cc23a3c73f32472e80ff5Greg Daniel} 2866b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 2879d54afc38b171c01a03b34e773d154fcf83d97dcjvanverthvoid GrVkMemory::FlushMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc) { 2889d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth if (alloc.fFlags & GrVkAlloc::kNoncoherent_Flag) { 2899d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth VkMappedMemoryRange mappedMemoryRange; 2909d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth memset(&mappedMemoryRange, 0, sizeof(VkMappedMemoryRange)); 2919d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth mappedMemoryRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; 2929d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth mappedMemoryRange.memory = alloc.fMemory; 2939d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth mappedMemoryRange.offset = alloc.fOffset; 2949d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth mappedMemoryRange.size = alloc.fSize; 2959d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth GR_VK_CALL(gpu->vkInterface(), FlushMappedMemoryRanges(gpu->device(), 2969d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth 1, &mappedMemoryRange)); 2979d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth } 2989d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth} 2999d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth 3009d54afc38b171c01a03b34e773d154fcf83d97dcjvanverthvoid GrVkMemory::InvalidateMappedAlloc(const GrVkGpu* gpu, const GrVkAlloc& alloc) { 3019d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth if (alloc.fFlags & GrVkAlloc::kNoncoherent_Flag) { 3029d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth VkMappedMemoryRange mappedMemoryRange; 3039d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth memset(&mappedMemoryRange, 0, sizeof(VkMappedMemoryRange)); 3049d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth mappedMemoryRange.sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE; 3059d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth mappedMemoryRange.memory = alloc.fMemory; 3069d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth mappedMemoryRange.offset = alloc.fOffset; 3079d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth mappedMemoryRange.size = alloc.fSize; 3089d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth GR_VK_CALL(gpu->vkInterface(), InvalidateMappedMemoryRanges(gpu->device(), 3099d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth 1, &mappedMemoryRange)); 3109d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth } 3119d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth} 3129d54afc38b171c01a03b34e773d154fcf83d97dcjvanverth 31382356cc41f360c607a1612cb9aead2423c0846a0jvanverthbool GrVkFreeListAlloc::alloc(VkDeviceSize requestedSize, 31482356cc41f360c607a1612cb9aead2423c0846a0jvanverth VkDeviceSize* allocOffset, VkDeviceSize* allocSize) { 31582356cc41f360c607a1612cb9aead2423c0846a0jvanverth VkDeviceSize alignedSize = align_size(requestedSize, fAlignment); 3166b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 3176b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth // find the smallest block big enough for our allocation 3186b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth FreeList::Iter iter = fFreeList.headIter(); 3196b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth FreeList::Iter bestFitIter; 3206b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VkDeviceSize bestFitSize = fSize + 1; 3216b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VkDeviceSize secondLargestSize = 0; 3226b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VkDeviceSize secondLargestOffset = 0; 3236b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth while (iter.get()) { 3246b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth Block* block = iter.get(); 3256b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth // need to adjust size to match desired alignment 3266b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth SkASSERT(align_size(block->fOffset, fAlignment) - block->fOffset == 0); 3276b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (block->fSize >= alignedSize && block->fSize < bestFitSize) { 3286b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth bestFitIter = iter; 3296b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth bestFitSize = block->fSize; 3306b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 3316b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (secondLargestSize < block->fSize && block->fOffset != fLargestBlockOffset) { 3326b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth secondLargestSize = block->fSize; 3336b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth secondLargestOffset = block->fOffset; 3346b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 3356b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth iter.next(); 3366b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 3376b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth SkASSERT(secondLargestSize <= fLargestBlockSize); 3386b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 3396b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth Block* bestFit = bestFitIter.get(); 3406b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (bestFit) { 3416b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth SkASSERT(align_size(bestFit->fOffset, fAlignment) == bestFit->fOffset); 34282356cc41f360c607a1612cb9aead2423c0846a0jvanverth *allocOffset = bestFit->fOffset; 34382356cc41f360c607a1612cb9aead2423c0846a0jvanverth *allocSize = alignedSize; 3446b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth // adjust or remove current block 3456b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VkDeviceSize originalBestFitOffset = bestFit->fOffset; 3466b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (bestFit->fSize > alignedSize) { 3476b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth bestFit->fOffset += alignedSize; 3486b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth bestFit->fSize -= alignedSize; 3496b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (fLargestBlockOffset == originalBestFitOffset) { 3506b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (bestFit->fSize >= secondLargestSize) { 3516b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fLargestBlockSize = bestFit->fSize; 3526b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fLargestBlockOffset = bestFit->fOffset; 3536b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } else { 3546b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fLargestBlockSize = secondLargestSize; 3556b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fLargestBlockOffset = secondLargestOffset; 3566b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 3576b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 3586b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth#ifdef SK_DEBUG 3596b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VkDeviceSize largestSize = 0; 3606b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth iter = fFreeList.headIter(); 3616b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth while (iter.get()) { 3626b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth Block* block = iter.get(); 3636b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (largestSize < block->fSize) { 3646b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth largestSize = block->fSize; 3656b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 3666b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth iter.next(); 3676b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 368d6562000efca50bc2bfddae8dcb69dce6b8c0950caryclark SkASSERT(largestSize == fLargestBlockSize); 3696b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth#endif 3706b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } else { 3716b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth SkASSERT(bestFit->fSize == alignedSize); 3726b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (fLargestBlockOffset == originalBestFitOffset) { 3736b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fLargestBlockSize = secondLargestSize; 3746b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fLargestBlockOffset = secondLargestOffset; 3756b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 3766b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fFreeList.remove(bestFit); 3776b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth#ifdef SK_DEBUG 3786b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VkDeviceSize largestSize = 0; 3796b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth iter = fFreeList.headIter(); 3806b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth while (iter.get()) { 3816b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth Block* block = iter.get(); 3826b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (largestSize < block->fSize) { 3836b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth largestSize = block->fSize; 3846b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 3856b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth iter.next(); 3866b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 3876b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth SkASSERT(largestSize == fLargestBlockSize); 3886b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth#endif 3896b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 3906b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fFreeSize -= alignedSize; 3916e46eea63efdede18525ff7b7097e611d3986d0degdaniel SkASSERT(*allocSize > 0); 3926b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 3936b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth return true; 3946b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 39582356cc41f360c607a1612cb9aead2423c0846a0jvanverth 3966b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth SkDebugf("Can't allocate %d bytes, %d bytes available, largest free block %d\n", alignedSize, fFreeSize, fLargestBlockSize); 3976b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 3986b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth return false; 3996b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth} 4006b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 40182356cc41f360c607a1612cb9aead2423c0846a0jvanverthvoid GrVkFreeListAlloc::free(VkDeviceSize allocOffset, VkDeviceSize allocSize) { 4026b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth // find the block right after this allocation 4036b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth FreeList::Iter iter = fFreeList.headIter(); 404d6f8034b886d59a3c722bf3932195143f2bf5eb8jvanverth FreeList::Iter prev; 40582356cc41f360c607a1612cb9aead2423c0846a0jvanverth while (iter.get() && iter.get()->fOffset < allocOffset) { 406d6f8034b886d59a3c722bf3932195143f2bf5eb8jvanverth prev = iter; 4076b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth iter.next(); 40882356cc41f360c607a1612cb9aead2423c0846a0jvanverth } 4096b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth // we have four cases: 4106b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth // we exactly follow the previous one 4116b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth Block* block; 41282356cc41f360c607a1612cb9aead2423c0846a0jvanverth if (prev.get() && prev.get()->fOffset + prev.get()->fSize == allocOffset) { 4136b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth block = prev.get(); 41482356cc41f360c607a1612cb9aead2423c0846a0jvanverth block->fSize += allocSize; 4156b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (block->fOffset == fLargestBlockOffset) { 4166b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fLargestBlockSize = block->fSize; 4176b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 4186b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth // and additionally we may exactly precede the next one 41982356cc41f360c607a1612cb9aead2423c0846a0jvanverth if (iter.get() && iter.get()->fOffset == allocOffset + allocSize) { 4206b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth block->fSize += iter.get()->fSize; 4216b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (iter.get()->fOffset == fLargestBlockOffset) { 4226b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fLargestBlockOffset = block->fOffset; 4236b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fLargestBlockSize = block->fSize; 4246b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 4256b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fFreeList.remove(iter.get()); 4266b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 4276b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth // or we only exactly proceed the next one 42882356cc41f360c607a1612cb9aead2423c0846a0jvanverth } else if (iter.get() && iter.get()->fOffset == allocOffset + allocSize) { 4296b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth block = iter.get(); 43082356cc41f360c607a1612cb9aead2423c0846a0jvanverth block->fSize += allocSize; 4316b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (block->fOffset == fLargestBlockOffset) { 43282356cc41f360c607a1612cb9aead2423c0846a0jvanverth fLargestBlockOffset = allocOffset; 4336b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fLargestBlockSize = block->fSize; 4346b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 43582356cc41f360c607a1612cb9aead2423c0846a0jvanverth block->fOffset = allocOffset; 4366b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth // or we fall somewhere in between, with gaps 4376b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } else { 4386b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth block = fFreeList.addBefore(iter); 43982356cc41f360c607a1612cb9aead2423c0846a0jvanverth block->fOffset = allocOffset; 44082356cc41f360c607a1612cb9aead2423c0846a0jvanverth block->fSize = allocSize; 4416b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 44282356cc41f360c607a1612cb9aead2423c0846a0jvanverth fFreeSize += allocSize; 4436b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (block->fSize > fLargestBlockSize) { 4446b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fLargestBlockSize = block->fSize; 4456b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fLargestBlockOffset = block->fOffset; 4466b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 4476b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 4486b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth#ifdef SK_DEBUG 4496b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VkDeviceSize largestSize = 0; 4506b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth iter = fFreeList.headIter(); 4516b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth while (iter.get()) { 4526b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth Block* block = iter.get(); 4536b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (largestSize < block->fSize) { 4546b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth largestSize = block->fSize; 4556b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 4566b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth iter.next(); 4576b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 4586b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth SkASSERT(fLargestBlockSize == largestSize); 4596b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth#endif 4606b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth} 4616b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 46268c3d30702c8af5ae249c78b30a9ea2351f875edjvanverthGrVkSubHeap::GrVkSubHeap(const GrVkGpu* gpu, uint32_t memoryTypeIndex, uint32_t heapIndex, 46382356cc41f360c607a1612cb9aead2423c0846a0jvanverth VkDeviceSize size, VkDeviceSize alignment) 46482356cc41f360c607a1612cb9aead2423c0846a0jvanverth : INHERITED(size, alignment) 46582356cc41f360c607a1612cb9aead2423c0846a0jvanverth , fGpu(gpu) 46668c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#ifdef SK_DEBUG 46768c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth , fHeapIndex(heapIndex) 46868c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#endif 469ae6e4869c94596eb3bf5069888b32ab06199aec0jvanverth , fMemoryTypeIndex(memoryTypeIndex) { 47082356cc41f360c607a1612cb9aead2423c0846a0jvanverth 47182356cc41f360c607a1612cb9aead2423c0846a0jvanverth VkMemoryAllocateInfo allocInfo = { 47282356cc41f360c607a1612cb9aead2423c0846a0jvanverth VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType 47382356cc41f360c607a1612cb9aead2423c0846a0jvanverth NULL, // pNext 47482356cc41f360c607a1612cb9aead2423c0846a0jvanverth size, // allocationSize 47582356cc41f360c607a1612cb9aead2423c0846a0jvanverth memoryTypeIndex, // memoryTypeIndex 47682356cc41f360c607a1612cb9aead2423c0846a0jvanverth }; 47782356cc41f360c607a1612cb9aead2423c0846a0jvanverth 47882356cc41f360c607a1612cb9aead2423c0846a0jvanverth VkResult err = GR_VK_CALL(gpu->vkInterface(), AllocateMemory(gpu->device(), 47982356cc41f360c607a1612cb9aead2423c0846a0jvanverth &allocInfo, 48082356cc41f360c607a1612cb9aead2423c0846a0jvanverth nullptr, 48182356cc41f360c607a1612cb9aead2423c0846a0jvanverth &fAlloc)); 48282356cc41f360c607a1612cb9aead2423c0846a0jvanverth if (VK_SUCCESS != err) { 48382356cc41f360c607a1612cb9aead2423c0846a0jvanverth this->reset(); 48468c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth } 48568c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#ifdef SK_DEBUG 48668c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth else { 48768c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth gHeapUsage[heapIndex] += size; 48882356cc41f360c607a1612cb9aead2423c0846a0jvanverth } 48968c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#endif 49082356cc41f360c607a1612cb9aead2423c0846a0jvanverth} 49182356cc41f360c607a1612cb9aead2423c0846a0jvanverth 49282356cc41f360c607a1612cb9aead2423c0846a0jvanverthGrVkSubHeap::~GrVkSubHeap() { 49382356cc41f360c607a1612cb9aead2423c0846a0jvanverth const GrVkInterface* iface = fGpu->vkInterface(); 49482356cc41f360c607a1612cb9aead2423c0846a0jvanverth GR_VK_CALL(iface, FreeMemory(fGpu->device(), fAlloc, nullptr)); 49568c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#ifdef SK_DEBUG 49668c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth gHeapUsage[fHeapIndex] -= fSize; 49768c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#endif 49882356cc41f360c607a1612cb9aead2423c0846a0jvanverth} 49982356cc41f360c607a1612cb9aead2423c0846a0jvanverth 50082356cc41f360c607a1612cb9aead2423c0846a0jvanverthbool GrVkSubHeap::alloc(VkDeviceSize size, GrVkAlloc* alloc) { 50182356cc41f360c607a1612cb9aead2423c0846a0jvanverth alloc->fMemory = fAlloc; 50282356cc41f360c607a1612cb9aead2423c0846a0jvanverth return INHERITED::alloc(size, &alloc->fOffset, &alloc->fSize); 50382356cc41f360c607a1612cb9aead2423c0846a0jvanverth} 50482356cc41f360c607a1612cb9aead2423c0846a0jvanverth 50582356cc41f360c607a1612cb9aead2423c0846a0jvanverthvoid GrVkSubHeap::free(const GrVkAlloc& alloc) { 50682356cc41f360c607a1612cb9aead2423c0846a0jvanverth SkASSERT(alloc.fMemory == fAlloc); 50782356cc41f360c607a1612cb9aead2423c0846a0jvanverth 50882356cc41f360c607a1612cb9aead2423c0846a0jvanverth INHERITED::free(alloc.fOffset, alloc.fSize); 5096b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth} 5106b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 5116e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdanielbool GrVkHeap::subAlloc(VkDeviceSize size, VkDeviceSize alignment, 51268c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth uint32_t memoryTypeIndex, uint32_t heapIndex, GrVkAlloc* alloc) { 5136b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VkDeviceSize alignedSize = align_size(size, alignment); 5146b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 5156dc3af4499893045f7b187d5d85bc785b6e44baajvanverth // if requested is larger than our subheap allocation, just alloc directly 5166dc3af4499893045f7b187d5d85bc785b6e44baajvanverth if (alignedSize > fSubHeapSize) { 5176dc3af4499893045f7b187d5d85bc785b6e44baajvanverth VkMemoryAllocateInfo allocInfo = { 5186dc3af4499893045f7b187d5d85bc785b6e44baajvanverth VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType 5196dc3af4499893045f7b187d5d85bc785b6e44baajvanverth NULL, // pNext 5206dc3af4499893045f7b187d5d85bc785b6e44baajvanverth size, // allocationSize 5216dc3af4499893045f7b187d5d85bc785b6e44baajvanverth memoryTypeIndex, // memoryTypeIndex 5226dc3af4499893045f7b187d5d85bc785b6e44baajvanverth }; 5236dc3af4499893045f7b187d5d85bc785b6e44baajvanverth 5246dc3af4499893045f7b187d5d85bc785b6e44baajvanverth VkResult err = GR_VK_CALL(fGpu->vkInterface(), AllocateMemory(fGpu->device(), 5256dc3af4499893045f7b187d5d85bc785b6e44baajvanverth &allocInfo, 5266dc3af4499893045f7b187d5d85bc785b6e44baajvanverth nullptr, 5276dc3af4499893045f7b187d5d85bc785b6e44baajvanverth &alloc->fMemory)); 5286dc3af4499893045f7b187d5d85bc785b6e44baajvanverth if (VK_SUCCESS != err) { 5296dc3af4499893045f7b187d5d85bc785b6e44baajvanverth return false; 5306dc3af4499893045f7b187d5d85bc785b6e44baajvanverth } 5316dc3af4499893045f7b187d5d85bc785b6e44baajvanverth alloc->fOffset = 0; 5326dc3af4499893045f7b187d5d85bc785b6e44baajvanverth alloc->fSize = 0; // hint that this is not a subheap allocation 53368c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#ifdef SK_DEBUG 53468c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth gHeapUsage[VK_MAX_MEMORY_HEAPS] += alignedSize; 53568c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth#endif 5366e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdaniel 5376dc3af4499893045f7b187d5d85bc785b6e44baajvanverth return true; 5386dc3af4499893045f7b187d5d85bc785b6e44baajvanverth } 5396dc3af4499893045f7b187d5d85bc785b6e44baajvanverth 5406b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth // first try to find a subheap that fits our allocation request 5416b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth int bestFitIndex = -1; 5426b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VkDeviceSize bestFitSize = 0x7FFFFFFF; 5436b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth for (auto i = 0; i < fSubHeaps.count(); ++i) { 5446e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdaniel if (fSubHeaps[i]->memoryTypeIndex() == memoryTypeIndex && 5456e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdaniel fSubHeaps[i]->alignment() == alignment) { 5466b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VkDeviceSize heapSize = fSubHeaps[i]->largestBlockSize(); 547d6f8034b886d59a3c722bf3932195143f2bf5eb8jvanverth if (heapSize >= alignedSize && heapSize < bestFitSize) { 5486b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth bestFitIndex = i; 5496b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth bestFitSize = heapSize; 5506b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 5516b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 5526b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 5536b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 5546b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (bestFitIndex >= 0) { 5556b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth SkASSERT(fSubHeaps[bestFitIndex]->alignment() == alignment); 5566b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (fSubHeaps[bestFitIndex]->alloc(size, alloc)) { 5576b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fUsedSize += alloc->fSize; 5586b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth return true; 5596b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 5606b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth return false; 5616dc3af4499893045f7b187d5d85bc785b6e44baajvanverth } 5626b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 5636b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth // need to allocate a new subheap 564145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagner std::unique_ptr<GrVkSubHeap>& subHeap = fSubHeaps.push_back(); 56568c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth subHeap.reset(new GrVkSubHeap(fGpu, memoryTypeIndex, heapIndex, fSubHeapSize, alignment)); 5666dc3af4499893045f7b187d5d85bc785b6e44baajvanverth // try to recover from failed allocation by only allocating what we need 5676dc3af4499893045f7b187d5d85bc785b6e44baajvanverth if (subHeap->size() == 0) { 5686dc3af4499893045f7b187d5d85bc785b6e44baajvanverth VkDeviceSize alignedSize = align_size(size, alignment); 56968c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth subHeap.reset(new GrVkSubHeap(fGpu, memoryTypeIndex, heapIndex, alignedSize, alignment)); 5706dc3af4499893045f7b187d5d85bc785b6e44baajvanverth if (subHeap->size() == 0) { 5716dc3af4499893045f7b187d5d85bc785b6e44baajvanverth return false; 5726dc3af4499893045f7b187d5d85bc785b6e44baajvanverth } 5736dc3af4499893045f7b187d5d85bc785b6e44baajvanverth } 5746b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fAllocSize += fSubHeapSize; 5756b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (subHeap->alloc(size, alloc)) { 5766b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fUsedSize += alloc->fSize; 5776b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth return true; 5786b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 5796b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 5806b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth return false; 5816b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth} 5826b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 5836e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdanielbool GrVkHeap::singleAlloc(VkDeviceSize size, VkDeviceSize alignment, 58468c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth uint32_t memoryTypeIndex, uint32_t heapIndex, GrVkAlloc* alloc) { 5856b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VkDeviceSize alignedSize = align_size(size, alignment); 5866b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 5876b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth // first try to find an unallocated subheap that fits our allocation request 5886b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth int bestFitIndex = -1; 5896b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VkDeviceSize bestFitSize = 0x7FFFFFFF; 5906b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth for (auto i = 0; i < fSubHeaps.count(); ++i) { 5916e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdaniel if (fSubHeaps[i]->memoryTypeIndex() == memoryTypeIndex && 5926e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdaniel fSubHeaps[i]->alignment() == alignment && 5936e90d42d3d5b8e51e60afbe97b27a0c16c2bacf1egdaniel fSubHeaps[i]->unallocated()) { 5946b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth VkDeviceSize heapSize = fSubHeaps[i]->size(); 595d6f8034b886d59a3c722bf3932195143f2bf5eb8jvanverth if (heapSize >= alignedSize && heapSize < bestFitSize) { 5966b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth bestFitIndex = i; 5976b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth bestFitSize = heapSize; 5986b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 5996b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 6006b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 6016b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 6026b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (bestFitIndex >= 0) { 6036b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth SkASSERT(fSubHeaps[bestFitIndex]->alignment() == alignment); 6046b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (fSubHeaps[bestFitIndex]->alloc(size, alloc)) { 6056b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fUsedSize += alloc->fSize; 6066b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth return true; 6076b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 6086b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth return false; 6096b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 6106b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 6116b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth // need to allocate a new subheap 612145dbcd165d9d27298eb8888bc240e2d06a95464Ben Wagner std::unique_ptr<GrVkSubHeap>& subHeap = fSubHeaps.push_back(); 61368c3d30702c8af5ae249c78b30a9ea2351f875edjvanverth subHeap.reset(new GrVkSubHeap(fGpu, memoryTypeIndex, heapIndex, alignedSize, alignment)); 6146b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fAllocSize += alignedSize; 6156b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (subHeap->alloc(size, alloc)) { 6166b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fUsedSize += alloc->fSize; 6176b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth return true; 6186b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 6196b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 6206b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth return false; 6216b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth} 6226b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 6236b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverthbool GrVkHeap::free(const GrVkAlloc& alloc) { 6246dc3af4499893045f7b187d5d85bc785b6e44baajvanverth // a size of 0 means we're using the system heap 6256dc3af4499893045f7b187d5d85bc785b6e44baajvanverth if (0 == alloc.fSize) { 6266dc3af4499893045f7b187d5d85bc785b6e44baajvanverth const GrVkInterface* iface = fGpu->vkInterface(); 6276dc3af4499893045f7b187d5d85bc785b6e44baajvanverth GR_VK_CALL(iface, FreeMemory(fGpu->device(), alloc.fMemory, nullptr)); 6286dc3af4499893045f7b187d5d85bc785b6e44baajvanverth return true; 6296dc3af4499893045f7b187d5d85bc785b6e44baajvanverth } 6306dc3af4499893045f7b187d5d85bc785b6e44baajvanverth 6316b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth for (auto i = 0; i < fSubHeaps.count(); ++i) { 6326b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth if (fSubHeaps[i]->memory() == alloc.fMemory) { 6336b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fSubHeaps[i]->free(alloc); 6346b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth fUsedSize -= alloc.fSize; 6356b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth return true; 6366b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 6376b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth } 6386b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 6396b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth return false; 6406b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth} 6416b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 6426b6ffc4ab6ecee9f46425a5467ef0fbebbb8c9cdjvanverth 643