1 /* 2 * Copyright 2018 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef GrVkMemoryAllocator_DEFINED 9 #define GrVkMemoryAllocator_DEFINED 10 11 #include "include/core/SkRefCnt.h" 12 #include "include/core/SkString.h" 13 #include "include/gpu/GrTypes.h" 14 #include "include/gpu/vk/GrVkTypes.h" 15 16 class GrVkMemoryAllocator : public SkRefCnt { 17 public: 18 enum class AllocationPropertyFlags { 19 kNone = 0, 20 // Allocation will be placed in its own VkDeviceMemory and not suballocated from some larger 21 // block. 22 kDedicatedAllocation = 0x1, 23 // Says that the backing memory can only be accessed by the device. Additionally the device 24 // may lazily allocate the memory. This cannot be used with buffers that will be host 25 // visible. Setting this flag does not guarantee that we will allocate memory that respects 26 // it, but we will try to prefer memory that can respect it. 27 kLazyAllocation = 0x2, 28 // The allocation will be mapped immediately and stay mapped until it is destroyed. This 29 // flag is only valid for buffers which are host visible (i.e. must have a usage other than 30 // BufferUsage::kGpuOnly). 31 kPersistentlyMapped = 0x4, 32 // Allocation can only be accessed by the device using a protected context. 33 kProtected = 0x8, 34 }; 35 36 GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(AllocationPropertyFlags); 37 38 enum class BufferUsage { 39 // Buffers that will only be accessed from the device (large const buffers). Will always be 40 // in device local memory. 41 kGpuOnly, 42 // Buffers that typically will be updated multiple times by the host and read on the gpu 43 // (e.g. uniform or vertex buffers). CPU writes will generally be sequential in the buffer 44 // and will try to take advantage of the write-combined nature of the gpu buffers. Thus this 45 // will always be mappable and coherent memory, and it will prefer to be in device local 46 // memory. 47 kCpuWritesGpuReads, 48 // Buffers that will be accessed on the host and copied to another GPU resource (transfer 49 // buffers). Will always be mappable and coherent memory. 50 kTransfersFromCpuToGpu, 51 // Buffers which are typically writted to by the GPU and then read on the host. Will always 52 // be mappable memory, and will prefer cached memory. 53 kTransfersFromGpuToCpu, 54 }; 55 56 // DEPRECATED: Use and implement allocateImageMemory instead allocateMemoryForImage(VkImage, AllocationPropertyFlags, GrVkBackendMemory*)57 virtual bool allocateMemoryForImage(VkImage, AllocationPropertyFlags, GrVkBackendMemory*) { 58 // The default implementation here is so clients can delete this virtual as the switch to 59 // the new one which returns a VkResult. 60 return false; 61 } 62 allocateImageMemory(VkImage image, AllocationPropertyFlags flags, GrVkBackendMemory* memory)63 virtual VkResult allocateImageMemory(VkImage image, AllocationPropertyFlags flags, 64 GrVkBackendMemory* memory) { 65 bool result = this->allocateMemoryForImage(image, flags, memory); 66 // VK_ERROR_INITIALIZATION_FAILED is a bogus result to return from this function, but it is 67 // just something to return that is not VK_SUCCESS and can't be interpreted by a caller to 68 // mean something specific happened like device lost or oom. This will be removed once we 69 // update clients to implement this virtual. 70 return result ? VK_SUCCESS : VK_ERROR_INITIALIZATION_FAILED; 71 } 72 73 // DEPRECATED: Use and implement allocateBufferMemory instead allocateMemoryForBuffer(VkBuffer, BufferUsage, AllocationPropertyFlags, GrVkBackendMemory*)74 virtual bool allocateMemoryForBuffer(VkBuffer, BufferUsage, AllocationPropertyFlags, 75 GrVkBackendMemory*) { 76 // The default implementation here is so clients can delete this virtual as the switch to 77 // the new one which returns a VkResult. 78 return false; 79 } 80 allocateBufferMemory(VkBuffer buffer, BufferUsage usage, AllocationPropertyFlags flags, GrVkBackendMemory* memory)81 virtual VkResult allocateBufferMemory(VkBuffer buffer, 82 BufferUsage usage, 83 AllocationPropertyFlags flags, 84 GrVkBackendMemory* memory) { 85 bool result = this->allocateMemoryForBuffer(buffer, usage, flags, memory); 86 // VK_ERROR_INITIALIZATION_FAILED is a bogus result to return from this function, but it is 87 // just something to return that is not VK_SUCCESS and can't be interpreted by a caller to 88 // mean something specific happened like device lost or oom. This will be removed once we 89 // update clients to implement this virtual. 90 return result ? VK_SUCCESS : VK_ERROR_INITIALIZATION_FAILED; 91 } 92 93 94 // Fills out the passed in GrVkAlloc struct for the passed in GrVkBackendMemory. 95 virtual void getAllocInfo(const GrVkBackendMemory&, GrVkAlloc*) const = 0; 96 97 // Maps the entire allocation and returns a pointer to the start of the allocation. The 98 // implementation may map more memory than just the allocation, but the returned pointer must 99 // point at the start of the memory for the requested allocation. mapMemory(const GrVkBackendMemory&)100 virtual void* mapMemory(const GrVkBackendMemory&) { return nullptr; } mapMemory(const GrVkBackendMemory& memory, void** data)101 virtual VkResult mapMemory(const GrVkBackendMemory& memory, void** data) { 102 *data = this->mapMemory(memory); 103 // VK_ERROR_INITIALIZATION_FAILED is a bogus result to return from this function, but it is 104 // just something to return that is not VK_SUCCESS and can't be interpreted by a caller to 105 // mean something specific happened like device lost or oom. This will be removed once we 106 // update clients to implement this virtual. 107 return *data ? VK_SUCCESS : VK_ERROR_INITIALIZATION_FAILED; 108 } 109 virtual void unmapMemory(const GrVkBackendMemory&) = 0; 110 111 // The following two calls are used for managing non-coherent memory. The offset is relative to 112 // the start of the allocation and not the underlying VkDeviceMemory. Additionaly the client 113 // must make sure that the offset + size passed in is less that or equal to the allocation size. 114 // It is the responsibility of the implementation to make sure all alignment requirements are 115 // followed. The client should not have to deal with any sort of alignment issues. flushMappedMemory(const GrVkBackendMemory&, VkDeviceSize, VkDeviceSize)116 virtual void flushMappedMemory(const GrVkBackendMemory&, VkDeviceSize, VkDeviceSize) {} flushMemory(const GrVkBackendMemory& memory, VkDeviceSize offset, VkDeviceSize size)117 virtual VkResult flushMemory(const GrVkBackendMemory& memory, VkDeviceSize offset, 118 VkDeviceSize size) { 119 this->flushMappedMemory(memory, offset, size); 120 return VK_SUCCESS; 121 } invalidateMappedMemory(const GrVkBackendMemory&, VkDeviceSize, VkDeviceSize)122 virtual void invalidateMappedMemory(const GrVkBackendMemory&, VkDeviceSize, VkDeviceSize) {} invalidateMemory(const GrVkBackendMemory& memory, VkDeviceSize offset, VkDeviceSize size)123 virtual VkResult invalidateMemory(const GrVkBackendMemory& memory, VkDeviceSize offset, 124 VkDeviceSize size) { 125 this->invalidateMappedMemory(memory, offset, size); 126 return VK_SUCCESS; 127 } 128 129 virtual void freeMemory(const GrVkBackendMemory&) = 0; 130 131 // Returns the total amount of memory that is allocated and in use by an allocation for this 132 // allocator. 133 virtual uint64_t totalUsedMemory() const = 0; 134 135 // Returns the total amount of memory that is allocated by this allocator. 136 virtual uint64_t totalAllocatedMemory() const = 0; 137 vmaDefragment()138 virtual void vmaDefragment() {} dumpVmaStats(SkString *out, const char *sep = �) const139 virtual void dumpVmaStats(SkString *out, const char *sep = ", ") const {} 140 }; 141 142 GR_MAKE_BITFIELD_CLASS_OPS(GrVkMemoryAllocator::AllocationPropertyFlags) 143 144 #endif 145