xref: /aosp_15_r20/external/deqp/external/vulkancts/framework/vulkan/vkAllocationCallbackUtil.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 #ifndef _VKALLOCATIONCALLBACKUTIL_HPP
2 #define _VKALLOCATIONCALLBACKUTIL_HPP
3 /*-------------------------------------------------------------------------
4  * Vulkan CTS Framework
5  * --------------------
6  *
7  * Copyright (c) 2015 Google Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Memory allocation callback utilities.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vkDefs.hpp"
27 #include "deAppendList.hpp"
28 
29 #include <vector>
30 #include <ostream>
31 
32 namespace tcu
33 {
34 class TestLog;
35 }
36 
37 namespace vk
38 {
39 
40 class AllocationCallbacks
41 {
42 public:
43     AllocationCallbacks(void);
44     virtual ~AllocationCallbacks(void);
45 
46     virtual void *allocate(size_t size, size_t alignment, VkSystemAllocationScope allocationScope) = 0;
47     virtual void *reallocate(void *original, size_t size, size_t alignment,
48                              VkSystemAllocationScope allocationScope)                              = 0;
49     virtual void free(void *mem)                                                                   = 0;
50 
51     virtual void notifyInternalAllocation(size_t size, VkInternalAllocationType allocationType,
52                                           VkSystemAllocationScope allocationScope) = 0;
53     virtual void notifyInternalFree(size_t size, VkInternalAllocationType allocationType,
54                                     VkSystemAllocationScope allocationScope)       = 0;
55 
getCallbacks(void) const56     const VkAllocationCallbacks *getCallbacks(void) const
57     {
58         return &m_callbacks;
59     }
60 
61 private:
62     const VkAllocationCallbacks m_callbacks;
63 };
64 
65 struct AllocationCallbackRecord
66 {
67     enum Type
68     {
69         TYPE_ALLOCATION = 0,      //! Call to pfnAllocation
70         TYPE_REALLOCATION,        //! Call to pfnReallocation
71         TYPE_FREE,                //! Call to pfnFree
72         TYPE_INTERNAL_ALLOCATION, //! Call to pfnInternalAllocation
73         TYPE_INTERNAL_FREE,       //! Call to pfnInternalFree
74 
75         TYPE_LAST
76     };
77 
78     Type type;
79 
80     union
81     {
82         struct
83         {
84             size_t size;
85             size_t alignment;
86             VkSystemAllocationScope scope;
87             void *returnedPtr;
88         } allocation;
89 
90         struct
91         {
92             void *original;
93             size_t size;
94             size_t alignment;
95             VkSystemAllocationScope scope;
96             void *returnedPtr;
97         } reallocation;
98 
99         struct
100         {
101             void *mem;
102         } free;
103 
104         // \note Used for both INTERNAL_ALLOCATION and INTERNAL_FREE
105         struct
106         {
107             size_t size;
108             VkInternalAllocationType type;
109             VkSystemAllocationScope scope;
110         } internalAllocation;
111     } data;
112 
AllocationCallbackRecordvk::AllocationCallbackRecord113     AllocationCallbackRecord(void) : type(TYPE_LAST)
114     {
115     }
116 
117     static AllocationCallbackRecord allocation(size_t size, size_t alignment, VkSystemAllocationScope scope,
118                                                void *returnedPtr);
119     static AllocationCallbackRecord reallocation(void *original, size_t size, size_t alignment,
120                                                  VkSystemAllocationScope scope, void *returnedPtr);
121     static AllocationCallbackRecord free(void *mem);
122     static AllocationCallbackRecord internalAllocation(size_t size, VkInternalAllocationType type,
123                                                        VkSystemAllocationScope scope);
124     static AllocationCallbackRecord internalFree(size_t size, VkInternalAllocationType type,
125                                                  VkSystemAllocationScope scope);
126 };
127 
128 class ChainedAllocator : public AllocationCallbacks
129 {
130 public:
131     ChainedAllocator(const VkAllocationCallbacks *nextAllocator);
132     ~ChainedAllocator(void);
133 
134     void *allocate(size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
135     void *reallocate(void *original, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
136     void free(void *mem);
137 
138     void notifyInternalAllocation(size_t size, VkInternalAllocationType allocationType,
139                                   VkSystemAllocationScope allocationScope);
140     void notifyInternalFree(size_t size, VkInternalAllocationType allocationType,
141                             VkSystemAllocationScope allocationScope);
142 
143 private:
144     const VkAllocationCallbacks *m_nextAllocator;
145 };
146 
147 class AllocationCallbackRecorder : public ChainedAllocator
148 {
149 public:
150     AllocationCallbackRecorder(const VkAllocationCallbacks *allocator, uint32_t callCountHint = 1024);
151     ~AllocationCallbackRecorder(void);
152 
153     void *allocate(size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
154     void *reallocate(void *original, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
155     void free(void *mem);
156 
157     void notifyInternalAllocation(size_t size, VkInternalAllocationType allocationType,
158                                   VkSystemAllocationScope allocationScope);
159     void notifyInternalFree(size_t size, VkInternalAllocationType allocationType,
160                             VkSystemAllocationScope allocationScope);
161 
162     typedef de::AppendList<AllocationCallbackRecord>::const_iterator RecordIterator;
163 
getRecordsBegin(void) const164     RecordIterator getRecordsBegin(void) const
165     {
166         return m_records.begin();
167     }
getRecordsEnd(void) const168     RecordIterator getRecordsEnd(void) const
169     {
170         return m_records.end();
171     }
getNumRecords(void) const172     std::size_t getNumRecords(void) const
173     {
174         return m_records.size();
175     }
176 
177 private:
178     typedef de::AppendList<AllocationCallbackRecord> Records;
179 
180     Records m_records;
181 };
182 
183 //! Allocator that starts returning null after N allocs
184 class DeterministicFailAllocator : public ChainedAllocator
185 {
186 public:
187     enum Mode
188     {
189         MODE_DO_NOT_COUNT = 0, //!< Do not count allocations, all allocs will succeed
190         MODE_COUNT_AND_FAIL,   //!< Count allocations, fail when reaching alloc N
191 
192         MODE_LAST
193     };
194 
195     DeterministicFailAllocator(const VkAllocationCallbacks *allocator, Mode mode, uint32_t numPassingAllocs);
196     ~DeterministicFailAllocator(void);
197 
198     void reset(Mode mode, uint32_t numPassingAllocs);
199 
200     void *allocate(size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
201     void *reallocate(void *original, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
202 
203 private:
204     Mode m_mode;
205     uint32_t m_numPassingAllocs;
206     volatile uint32_t m_allocationNdx;
207 };
208 
209 struct AllocationCallbackViolation
210 {
211     enum Reason
212     {
213         REASON_DOUBLE_FREE = 0,
214         REASON_FREE_NOT_ALLOCATED_PTR,
215         REASON_REALLOC_NOT_ALLOCATED_PTR,
216         REASON_REALLOC_FREED_PTR,
217         REASON_NEGATIVE_INTERNAL_ALLOCATION_TOTAL,
218         REASON_INVALID_ALLOCATION_SCOPE,
219         REASON_INVALID_INTERNAL_ALLOCATION_TYPE,
220         REASON_INVALID_ALIGNMENT,
221         REASON_REALLOC_DIFFERENT_ALIGNMENT,
222 
223         REASON_LAST
224     };
225 
226     AllocationCallbackRecord record;
227     Reason reason;
228 
AllocationCallbackViolationvk::AllocationCallbackViolation229     AllocationCallbackViolation(void) : reason(REASON_LAST)
230     {
231     }
232 
AllocationCallbackViolationvk::AllocationCallbackViolation233     AllocationCallbackViolation(const AllocationCallbackRecord &record_, Reason reason_)
234         : record(record_)
235         , reason(reason_)
236     {
237     }
238 };
239 
240 struct AllocationCallbackValidationResults
241 {
242     std::vector<AllocationCallbackRecord> liveAllocations;
243     size_t internalAllocationTotal[VK_INTERNAL_ALLOCATION_TYPE_LAST][VK_SYSTEM_ALLOCATION_SCOPE_LAST];
244     std::vector<AllocationCallbackViolation> violations;
245 
246     AllocationCallbackValidationResults(void);
247 
248     void clear(void);
249 };
250 
251 void validateAllocationCallbacks(const AllocationCallbackRecorder &recorder,
252                                  AllocationCallbackValidationResults *results);
253 bool checkAndLog(tcu::TestLog &log, const AllocationCallbackValidationResults &results,
254                  uint32_t allowedLiveAllocScopeBits);
255 bool validateAndLog(tcu::TestLog &log, const AllocationCallbackRecorder &recorder, uint32_t allowedLiveAllocScopeBits);
256 
257 size_t getLiveSystemAllocationTotal(const AllocationCallbackValidationResults &validationResults);
258 
259 std::ostream &operator<<(std::ostream &str, const AllocationCallbackRecord &record);
260 std::ostream &operator<<(std::ostream &str, const AllocationCallbackViolation &violation);
261 
262 const VkAllocationCallbacks *getSystemAllocator(void);
263 
264 } // namespace vk
265 
266 #endif // _VKALLOCATIONCALLBACKUTIL_HPP
267