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