Home | History | Annotate | Download | only in vulkan
      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, VkSystemAllocationScope allocationScope) = 0;
     48 	virtual void					free					(void* mem) = 0;
     49 
     50 	virtual void					notifyInternalAllocation(size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope) = 0;
     51 	virtual void					notifyInternalFree		(size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope) = 0;
     52 
     53 	const VkAllocationCallbacks*	getCallbacks			(void) const { return &m_callbacks;	}
     54 
     55 private:
     56 	const VkAllocationCallbacks		m_callbacks;
     57 };
     58 
     59 struct AllocationCallbackRecord
     60 {
     61 	enum Type
     62 	{
     63 		TYPE_ALLOCATION		= 0,		//! Call to pfnAllocation
     64 		TYPE_REALLOCATION,				//! Call to pfnReallocation
     65 		TYPE_FREE,						//! Call to pfnFree
     66 		TYPE_INTERNAL_ALLOCATION,		//! Call to pfnInternalAllocation
     67 		TYPE_INTERNAL_FREE,				//! Call to pfnInternalFree
     68 
     69 		TYPE_LAST
     70 	};
     71 
     72 	Type	type;
     73 
     74 	union
     75 	{
     76 		struct
     77 		{
     78 			size_t						size;
     79 			size_t						alignment;
     80 			VkSystemAllocationScope		scope;
     81 			void*						returnedPtr;
     82 		} allocation;
     83 
     84 		struct
     85 		{
     86 			void*						original;
     87 			size_t						size;
     88 			size_t						alignment;
     89 			VkSystemAllocationScope		scope;
     90 			void*						returnedPtr;
     91 		} reallocation;
     92 
     93 		struct
     94 		{
     95 			void*						mem;
     96 		} free;
     97 
     98 		// \note Used for both INTERNAL_ALLOCATION and INTERNAL_FREE
     99 		struct
    100 		{
    101 			size_t						size;
    102 			VkInternalAllocationType	type;
    103 			VkSystemAllocationScope		scope;
    104 		} internalAllocation;
    105 	} data;
    106 
    107 									AllocationCallbackRecord	(void) : type(TYPE_LAST) {}
    108 
    109 	static AllocationCallbackRecord	allocation					(size_t size, size_t alignment, VkSystemAllocationScope scope, void* returnedPtr);
    110 	static AllocationCallbackRecord	reallocation				(void* original, size_t size, size_t alignment, VkSystemAllocationScope scope, void* returnedPtr);
    111 	static AllocationCallbackRecord	free						(void* mem);
    112 	static AllocationCallbackRecord	internalAllocation			(size_t size, VkInternalAllocationType type, VkSystemAllocationScope scope);
    113 	static AllocationCallbackRecord	internalFree				(size_t size, VkInternalAllocationType type, VkSystemAllocationScope scope);
    114 };
    115 
    116 class ChainedAllocator : public AllocationCallbacks
    117 {
    118 public:
    119 									ChainedAllocator		(const VkAllocationCallbacks* nextAllocator);
    120 									~ChainedAllocator		(void);
    121 
    122 	void*							allocate				(size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
    123 	void*							reallocate				(void* original, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
    124 	void							free					(void* mem);
    125 
    126 	void							notifyInternalAllocation(size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope);
    127 	void							notifyInternalFree		(size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope);
    128 
    129 private:
    130 	const VkAllocationCallbacks*	m_nextAllocator;
    131 };
    132 
    133 class AllocationCallbackRecorder : public ChainedAllocator
    134 {
    135 public:
    136 							AllocationCallbackRecorder	(const VkAllocationCallbacks* allocator, deUint32 callCountHint = 1024);
    137 							~AllocationCallbackRecorder	(void);
    138 
    139 	void*					allocate					(size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
    140 	void*					reallocate					(void* original, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
    141 	void					free						(void* mem);
    142 
    143 	void					notifyInternalAllocation	(size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope);
    144 	void					notifyInternalFree			(size_t size, VkInternalAllocationType allocationType, VkSystemAllocationScope allocationScope);
    145 
    146 	typedef de::AppendList<AllocationCallbackRecord>::const_iterator	RecordIterator;
    147 
    148 	RecordIterator			getRecordsBegin				(void) const { return m_records.begin();	}
    149 	RecordIterator			getRecordsEnd				(void) const { return m_records.end();		}
    150 	std::size_t				getNumRecords				(void) const { return m_records.size();		}
    151 
    152 private:
    153 	typedef de::AppendList<AllocationCallbackRecord> Records;
    154 
    155 	Records					m_records;
    156 };
    157 
    158 //! Allocator that starts returning null after N allocs
    159 class DeterministicFailAllocator : public ChainedAllocator
    160 {
    161 public:
    162 	enum Mode
    163 	{
    164 		MODE_DO_NOT_COUNT = 0,	//!< Do not count allocations, all allocs will succeed
    165 		MODE_COUNT_AND_FAIL,	//!< Count allocations, fail when reaching alloc N
    166 
    167 		MODE_LAST
    168 	};
    169 
    170 							DeterministicFailAllocator	(const VkAllocationCallbacks* allocator, Mode mode, deUint32 numPassingAllocs);
    171 							~DeterministicFailAllocator	(void);
    172 
    173 	void					reset						(Mode mode, deUint32 numPassingAllocs);
    174 
    175 	void*					allocate					(size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
    176 	void*					reallocate					(void* original, size_t size, size_t alignment, VkSystemAllocationScope allocationScope);
    177 
    178 private:
    179 	Mode					m_mode;
    180 	deUint32				m_numPassingAllocs;
    181 	volatile deUint32		m_allocationNdx;
    182 };
    183 
    184 struct AllocationCallbackViolation
    185 {
    186 	enum Reason
    187 	{
    188 		REASON_DOUBLE_FREE = 0,
    189 		REASON_FREE_NOT_ALLOCATED_PTR,
    190 		REASON_REALLOC_NOT_ALLOCATED_PTR,
    191 		REASON_REALLOC_FREED_PTR,
    192 		REASON_NEGATIVE_INTERNAL_ALLOCATION_TOTAL,
    193 		REASON_INVALID_ALLOCATION_SCOPE,
    194 		REASON_INVALID_INTERNAL_ALLOCATION_TYPE,
    195 		REASON_INVALID_ALIGNMENT,
    196 		REASON_REALLOC_DIFFERENT_ALIGNMENT,
    197 
    198 		REASON_LAST
    199 	};
    200 
    201 	AllocationCallbackRecord	record;
    202 	Reason						reason;
    203 
    204 	AllocationCallbackViolation (void)
    205 		: reason(REASON_LAST)
    206 	{}
    207 
    208 	AllocationCallbackViolation (const AllocationCallbackRecord& record_, Reason reason_)
    209 		: record(record_)
    210 		, reason(reason_)
    211 	{}
    212 };
    213 
    214 struct AllocationCallbackValidationResults
    215 {
    216 	std::vector<AllocationCallbackRecord>		liveAllocations;
    217 	size_t										internalAllocationTotal[VK_INTERNAL_ALLOCATION_TYPE_LAST][VK_SYSTEM_ALLOCATION_SCOPE_LAST];
    218 	std::vector<AllocationCallbackViolation>	violations;
    219 
    220 												AllocationCallbackValidationResults	(void);
    221 
    222 	void										clear								(void);
    223 };
    224 
    225 void							validateAllocationCallbacks		(const AllocationCallbackRecorder& recorder, AllocationCallbackValidationResults* results);
    226 bool							checkAndLog						(tcu::TestLog& log, const AllocationCallbackValidationResults& results, deUint32 allowedLiveAllocScopeBits);
    227 bool							validateAndLog					(tcu::TestLog& log, const AllocationCallbackRecorder& recorder, deUint32 allowedLiveAllocScopeBits);
    228 
    229 size_t							getLiveSystemAllocationTotal	(const AllocationCallbackValidationResults& validationResults);
    230 
    231 std::ostream&					operator<<						(std::ostream& str, const AllocationCallbackRecord& record);
    232 std::ostream&					operator<<						(std::ostream& str, const AllocationCallbackViolation& violation);
    233 
    234 const VkAllocationCallbacks*	getSystemAllocator				(void);
    235 
    236 } // vk
    237 
    238 #endif // _VKALLOCATIONCALLBACKUTIL_HPP
    239