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