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 getCallbacks(void) const53 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 AllocationCallbackRecordvk::AllocationCallbackRecord107 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 getRecordsBegin(void) const148 RecordIterator getRecordsBegin (void) const { return m_records.begin(); } getRecordsEnd(void) const149 RecordIterator getRecordsEnd (void) const { return m_records.end(); } getNumRecords(void) const150 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 AllocationCallbackViolationvk::AllocationCallbackViolation204 AllocationCallbackViolation (void) 205 : reason(REASON_LAST) 206 {} 207 AllocationCallbackViolationvk::AllocationCallbackViolation208 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