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
15class GrVkMemoryAllocator : public SkRefCnt {
16public:
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 will be accessed on the host and copied to and from a GPU resource (transfer
42 // buffers). Will always be mappable and coherent memory.
43 kCpuOnly,
44 // Buffers that typically will be updated multiple times by the host and read on the gpu
45 // (e.g. uniform or vertex buffers). Will always be mappable memory, and will prefer to be
46 // in device local memory.
47 kCpuWritesGpuReads,
48 // Buffers which are typically writted to by the GPU and then read on the host. Will always
49 // be mappable memory, and will prefer coherent and cached memory.
50 kGpuWritesCpuReads,
51 };
52
53 // DEPRECATED: Use and implement allocateImageMemory instead
54 virtual bool allocateMemoryForImage(VkImage, AllocationPropertyFlags, GrVkBackendMemory*) {
55 // The default implementation here is so clients can delete this virtual as the switch to
56 // the new one which returns a VkResult.
57 return false;
58 }
59
60 virtual VkResult allocateImageMemory(VkImage image, AllocationPropertyFlags flags,
61 GrVkBackendMemory* memory) {
62 bool result = this->allocateMemoryForImage(image, flags, memory);
63 // VK_ERROR_INITIALIZATION_FAILED is a bogus result to return from this function, but it is
64 // just something to return that is not VK_SUCCESS and can't be interpreted by a caller to
65 // mean something specific happened like device lost or oom. This will be removed once we
66 // update clients to implement this virtual.
67 return result ? VK_SUCCESS : VK_ERROR_INITIALIZATION_FAILED;
68 }
69
70 // DEPRECATED: Use and implement allocateBufferMemory instead
71 virtual bool allocateMemoryForBuffer(VkBuffer, BufferUsage, AllocationPropertyFlags,
72 GrVkBackendMemory*) {
73 // The default implementation here is so clients can delete this virtual as the switch to
74 // the new one which returns a VkResult.
75 return false;
76 }
77
78 virtual VkResult allocateBufferMemory(VkBuffer buffer,
79 BufferUsage usage,
80 AllocationPropertyFlags flags,
81 GrVkBackendMemory* memory) {
82 bool result = this->allocateMemoryForBuffer(buffer, usage, flags, memory);
83 // VK_ERROR_INITIALIZATION_FAILED is a bogus result to return from this function, but it is
84 // just something to return that is not VK_SUCCESS and can't be interpreted by a caller to
85 // mean something specific happened like device lost or oom. This will be removed once we
86 // update clients to implement this virtual.
87 return result ? VK_SUCCESS : VK_ERROR_INITIALIZATION_FAILED;
88 }
89
90
91 // Fills out the passed in GrVkAlloc struct for the passed in GrVkBackendMemory.
92 virtual void getAllocInfo(const GrVkBackendMemory&, GrVkAlloc*) const = 0;
93
94 // Maps the entire allocation and returns a pointer to the start of the allocation. The
95 // implementation may map more memory than just the allocation, but the returned pointer must
96 // point at the start of the memory for the requested allocation.
97 virtual void* mapMemory(const GrVkBackendMemory&) { return nullptr; }
98 virtual VkResult mapMemory(const GrVkBackendMemory& memory, void** data) {
99 *data = this->mapMemory(memory);
100 // VK_ERROR_INITIALIZATION_FAILED is a bogus result to return from this function, but it is
101 // just something to return that is not VK_SUCCESS and can't be interpreted by a caller to
102 // mean something specific happened like device lost or oom. This will be removed once we
103 // update clients to implement this virtual.
104 return *data ? VK_SUCCESS : VK_ERROR_INITIALIZATION_FAILED;
105 }
106 virtual void unmapMemory(const GrVkBackendMemory&) = 0;
107
108 // The following two calls are used for managing non-coherent memory. The offset is relative to
109 // the start of the allocation and not the underlying VkDeviceMemory. Additionaly the client
110 // must make sure that the offset + size passed in is less that or equal to the allocation size.
111 // It is the responsibility of the implementation to make sure all alignment requirements are
112 // followed. The client should not have to deal with any sort of alignment issues.
113 virtual void flushMappedMemory(const GrVkBackendMemory&, VkDeviceSize, VkDeviceSize) {}
114 virtual VkResult flushMemory(const GrVkBackendMemory& memory, VkDeviceSize offset,
115 VkDeviceSize size) {
116 this->flushMappedMemory(memory, offset, size);
117 return VK_SUCCESS;
118 }
119 virtual void invalidateMappedMemory(const GrVkBackendMemory&, VkDeviceSize, VkDeviceSize) {}
120 virtual VkResult invalidateMemory(const GrVkBackendMemory& memory, VkDeviceSize offset,
121 VkDeviceSize size) {
122 this->invalidateMappedMemory(memory, offset, size);
123 return VK_SUCCESS;
124 }
125
126 virtual void freeMemory(const GrVkBackendMemory&) = 0;
127
128 // Returns the total amount of memory that is allocated and in use by an allocation for this
129 // allocator.
130 virtual uint64_t totalUsedMemory() const = 0;
131
132 // Returns the total amount of memory that is allocated by this allocator.
133 virtual uint64_t totalAllocatedMemory() const = 0;
134};
135
136GR_MAKE_BITFIELD_CLASS_OPS(GrVkMemoryAllocator::AllocationPropertyFlags)
137
138#endif
139