xref: /aosp_15_r20/external/deqp/external/vulkancts/framework/vulkan/vkMemUtil.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 #ifndef _VKMEMUTIL_HPP
2 #define _VKMEMUTIL_HPP
3 /*-------------------------------------------------------------------------
4  * Vulkan CTS Framework
5  * --------------------
6  *
7  * Copyright (c) 2019 Google Inc.
8  * Copyright (c) 2019 The Khronos Group Inc.
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Memory management utilities.
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vkDefs.hpp"
28 #include "tcuMaybe.hpp"
29 #include "deUniquePtr.hpp"
30 #include "deSharedPtr.hpp"
31 #include <vector>
32 
33 namespace vk
34 {
35 
36 /*--------------------------------------------------------------------*//*!
37  * \brief Memory allocation interface
38  *
39  * Allocation represents block of device memory and is allocated by
40  * Allocator implementation. Test code should use Allocator for allocating
41  * memory, unless there is a reason not to (for example testing vkAllocMemory).
42  *
43  * Allocation doesn't necessarily correspond to a whole VkDeviceMemory, but
44  * instead it may represent sub-allocation. Thus whenever VkDeviceMemory
45  * (getMemory()) managed by Allocation is passed to Vulkan API calls,
46  * offset given by getOffset() must be used.
47  *
48  * If host-visible memory was requested, host pointer to the memory can
49  * be queried with getHostPtr(). No offset is needed when accessing host
50  * pointer, i.e. the pointer is already adjusted in case of sub-allocation.
51  *
52  * Memory mappings are managed solely by Allocation, i.e. unmapping or
53  * re-mapping VkDeviceMemory owned by Allocation is not allowed.
54  *//*--------------------------------------------------------------------*/
55 class Allocation
56 {
57 public:
58     virtual ~Allocation(void);
59 
60     //! Get VkDeviceMemory backing this allocation
getMemory(void) const61     VkDeviceMemory getMemory(void) const
62     {
63         return m_memory;
64     }
65 
66     //! Get offset in VkDeviceMemory for this allocation
getOffset(void) const67     VkDeviceSize getOffset(void) const
68     {
69         return m_offset;
70     }
71 
72     //! Get host pointer for this allocation. Only available for host-visible allocations
getHostPtr(void) const73     void *getHostPtr(void) const
74     {
75         DE_ASSERT(m_hostPtr);
76         return m_hostPtr;
77     }
78 
79 protected:
80     Allocation(VkDeviceMemory memory, VkDeviceSize offset, void *hostPtr);
81 
82 private:
83     const VkDeviceMemory m_memory;
84     const VkDeviceSize m_offset;
85     void *const m_hostPtr;
86 };
87 
88 void flushAlloc(const DeviceInterface &vkd, VkDevice device, const Allocation &alloc);
89 void invalidateAlloc(const DeviceInterface &vkd, VkDevice device, const Allocation &alloc);
90 
91 //! Memory allocation requirements
92 class MemoryRequirement
93 {
94 public:
95     static const MemoryRequirement Any;
96     static const MemoryRequirement HostVisible;
97     static const MemoryRequirement Coherent;
98     static const MemoryRequirement LazilyAllocated;
99     static const MemoryRequirement Protected;
100     static const MemoryRequirement Local;
101     static const MemoryRequirement Cached;
102     static const MemoryRequirement NonLocal;
103     static const MemoryRequirement DeviceAddress;
104     static const MemoryRequirement DeviceAddressCaptureReplay;
105 
operator |(MemoryRequirement requirement) const106     inline MemoryRequirement operator|(MemoryRequirement requirement) const
107     {
108         return MemoryRequirement(m_flags | requirement.m_flags);
109     }
110 
operator &(MemoryRequirement requirement) const111     inline MemoryRequirement operator&(MemoryRequirement requirement) const
112     {
113         return MemoryRequirement(m_flags & requirement.m_flags);
114     }
115 
116     bool matchesHeap(VkMemoryPropertyFlags heapFlags) const;
117 
operator bool(void) const118     inline operator bool(void) const
119     {
120         return m_flags != 0u;
121     }
122 
123 private:
124     explicit MemoryRequirement(uint32_t flags);
125 
126     const uint32_t m_flags;
127 
128     enum Flags
129     {
130         FLAG_HOST_VISIBLE                  = 1u << 0u,
131         FLAG_COHERENT                      = 1u << 1u,
132         FLAG_LAZY_ALLOCATION               = 1u << 2u,
133         FLAG_PROTECTED                     = 1u << 3u,
134         FLAG_LOCAL                         = 1u << 4u,
135         FLAG_CACHED                        = 1u << 5u,
136         FLAG_NON_LOCAL                     = 1u << 6u,
137         FLAG_DEVICE_ADDRESS                = 1u << 7u,
138         FLAG_DEVICE_ADDRESS_CAPTURE_REPLAY = 1u << 8u,
139     };
140 };
141 
142 //! Memory allocator interface
143 class Allocator
144 {
145 public:
Allocator(void)146     Allocator(void)
147     {
148     }
~Allocator(void)149     virtual ~Allocator(void)
150     {
151     }
152 
153     virtual de::MovePtr<Allocation> allocate(const VkMemoryAllocateInfo &allocInfo, VkDeviceSize alignment) = 0;
154     virtual de::MovePtr<Allocation> allocate(const VkMemoryRequirements &memRequirements,
155                                              MemoryRequirement requirement)                                 = 0;
156 };
157 
158 //! Allocator that backs every allocation with its own VkDeviceMemory
159 class SimpleAllocator : public Allocator
160 {
161 public:
162     struct OffsetParams
163     {
164         const vk::VkDeviceSize nonCoherentAtomSize;
165         const vk::VkDeviceSize offset;
166     };
167     typedef tcu::Maybe<OffsetParams> OptionalOffsetParams;
168 
169     SimpleAllocator(const DeviceInterface &vk, VkDevice device, const VkPhysicalDeviceMemoryProperties &deviceMemProps,
170                     const OptionalOffsetParams &offsetParams = tcu::Nothing);
171 
172     de::MovePtr<Allocation> allocate(const VkMemoryAllocateInfo &allocInfo, VkDeviceSize alignment);
173     de::MovePtr<Allocation> allocate(const VkMemoryRequirements &memRequirements, MemoryRequirement requirement);
174 
175 private:
176     const DeviceInterface &m_vk;
177     const VkDevice m_device;
178     const VkPhysicalDeviceMemoryProperties m_memProps;
179     const tcu::Maybe<OffsetParams> m_offsetParams;
180 };
181 
182 de::MovePtr<Allocation> allocateExtended(const InstanceInterface &vki, const DeviceInterface &vkd,
183                                          const VkPhysicalDevice &physDevice, const VkDevice device,
184                                          const VkMemoryRequirements &memReqs, const MemoryRequirement requirement,
185                                          const void *pNext);
186 de::MovePtr<Allocation> allocateDedicated(const InstanceInterface &vki, const DeviceInterface &vkd,
187                                           const VkPhysicalDevice &physDevice, const VkDevice device,
188                                           const VkBuffer buffer, MemoryRequirement requirement);
189 de::MovePtr<Allocation> allocateDedicated(const InstanceInterface &vki, const DeviceInterface &vkd,
190                                           const VkPhysicalDevice &physDevice, const VkDevice device,
191                                           const VkImage image, MemoryRequirement requirement);
192 
193 void *mapMemory(const DeviceInterface &vkd, VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size,
194                 VkMemoryMapFlags flags);
195 void flushMappedMemoryRange(const DeviceInterface &vkd, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset,
196                             VkDeviceSize size);
197 void invalidateMappedMemoryRange(const DeviceInterface &vkd, VkDevice device, VkDeviceMemory memory,
198                                  VkDeviceSize offset, VkDeviceSize size);
199 
200 uint32_t selectMatchingMemoryType(const VkPhysicalDeviceMemoryProperties &deviceMemProps, uint32_t allowedMemTypeBits,
201                                   MemoryRequirement requirement);
202 uint32_t getCompatibleMemoryTypes(const VkPhysicalDeviceMemoryProperties &deviceMemProps,
203                                   MemoryRequirement requirement);
204 #ifdef CTS_USES_VULKANSC
205 uint32_t getSEUSafeMemoryTypes(const VkPhysicalDeviceMemoryProperties &deviceMemProps);
206 #endif // CTS_USES_VULKANSC
207 
208 void bindImagePlanesMemory(const vk::DeviceInterface &vkd, const vk::VkDevice device, const vk::VkImage image,
209                            const uint32_t numPlanes, std::vector<de::SharedPtr<Allocation>> &allocations,
210                            vk::Allocator &allocator, const vk::MemoryRequirement requirement);
211 
212 de::MovePtr<Allocation> bindImage(const DeviceInterface &vk, const VkDevice device, Allocator &allocator,
213                                   const VkImage image, const MemoryRequirement requirement);
214 
215 de::MovePtr<Allocation> bindBuffer(const DeviceInterface &vk, const VkDevice device, Allocator &allocator,
216                                    const VkBuffer buffer, const MemoryRequirement requirement);
217 
218 void zeroBuffer(const DeviceInterface &vk, const VkDevice device, const Allocation &alloc, const VkDeviceSize size);
219 
220 } // namespace vk
221 
222 #endif // _VKMEMUTIL_HPP
223