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