| 1 | // | 
| 2 | // Redistribution and use in source and binary forms, with or without | 
| 3 | // modification, are permitted provided that the following conditions | 
| 4 | // are met: | 
| 5 | //  * Redistributions of source code must retain the above copyright | 
| 6 | //    notice, this list of conditions and the following disclaimer. | 
| 7 | //  * Redistributions in binary form must reproduce the above copyright | 
| 8 | //    notice, this list of conditions and the following disclaimer in the | 
| 9 | //    documentation and/or other materials provided with the distribution. | 
| 10 | //  * Neither the name of NVIDIA CORPORATION nor the names of its | 
| 11 | //    contributors may be used to endorse or promote products derived | 
| 12 | //    from this software without specific prior written permission. | 
| 13 | // | 
| 14 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY | 
| 15 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
| 16 | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 
| 17 | // PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR | 
| 18 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 
| 19 | // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 
| 20 | // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 
| 21 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 
| 22 | // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
| 23 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
| 24 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
| 25 | // | 
| 26 | // Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved. | 
| 27 |  | 
| 28 | #ifndef PXCUDACONTEXTMANAGER_PXCUDAMEMORYMANAGER_H | 
| 29 | #define PXCUDACONTEXTMANAGER_PXCUDAMEMORYMANAGER_H | 
| 30 |  | 
| 31 | #include "foundation/PxPreprocessor.h" | 
| 32 |  | 
| 33 | #if PX_SUPPORT_GPU_PHYSX | 
| 34 |  | 
| 35 | #include "task/PxTaskDefine.h" | 
| 36 |  | 
| 37 | // some macros to keep the source code more readable | 
| 38 | #define PX_ALLOC_INFO(name, ID) __FILE__, __LINE__, name, physx::PxAllocId::ID | 
| 39 | #define PX_ALLOC_INFO_PARAMS_DECL(p0, p1, p2, p3)  const char* file = p0, int line = p1, const char* allocName = p2, physx::PxAllocId::Enum allocId = physx::PxAllocId::p3 | 
| 40 | #define PX_ALLOC_INFO_PARAMS_DEF()  const char* file, int line, const char* allocName, physx::PxAllocId::Enum allocId | 
| 41 | #define PX_ALLOC_INFO_PARAMS_INPUT()  file, line, allocName, allocId | 
| 42 | #define PX_ALLOC_INFO_PARAMS_INPUT_INFO(info) info.getFileName(), info.getLine(), info.getAllocName(), info.getAllocId() | 
| 43 |  | 
| 44 | #ifndef NULL // don't want to include <string.h> | 
| 45 | #define NULL 0 | 
| 46 | #endif | 
| 47 |  | 
| 48 | namespace physx | 
| 49 | { | 
| 50 |  | 
| 51 | PX_PUSH_PACK_DEFAULT | 
| 52 |  | 
| 53 | /** \brief ID of the Feature which owns/allocated memory from the heap | 
| 54 |  * | 
| 55 |  * Maximum of 64k IDs allowed. | 
| 56 |  */ | 
| 57 | struct PxAllocId | 
| 58 | { | 
| 59 |     /** | 
| 60 |      * \brief ID of the Feature which owns/allocated memory from the heap | 
| 61 |      */ | 
| 62 | 	enum Enum | 
| 63 | 	{ | 
| 64 | 		UNASSIGNED,		//!< default | 
| 65 | 		APEX,			//!< APEX stuff not further classified | 
| 66 | 		PARTICLES,		//!< all particle related | 
| 67 | 		GPU_UTIL,		//!< e.g. RadixSort (used in SPH and deformable self collision) | 
| 68 | 		CLOTH,			//!< all cloth related | 
| 69 | 		NUM_IDS			//!< number of IDs, be aware that ApexHeapStats contains PxAllocIdStats[NUM_IDS] | 
| 70 | 	}; | 
| 71 | }; | 
| 72 |  | 
| 73 | /// \brief memory type managed by a heap | 
| 74 | struct PxCudaBufferMemorySpace | 
| 75 | { | 
| 76 |     /** | 
| 77 |      * \brief memory type managed by a heap | 
| 78 |      */ | 
| 79 | 	enum Enum | 
| 80 | 	{ | 
| 81 | 		T_GPU, | 
| 82 | 		T_PINNED_HOST, | 
| 83 | 		T_WRITE_COMBINED, | 
| 84 | 		T_HOST, | 
| 85 | 		COUNT | 
| 86 | 	}; | 
| 87 | }; | 
| 88 |  | 
| 89 | /// \brief class to track allocation statistics, see PxgMirrored | 
| 90 | class PxAllocInfo | 
| 91 | { | 
| 92 | public: | 
| 93 |     /** | 
| 94 |      * \brief AllocInfo default constructor | 
| 95 |      */ | 
| 96 | 	PxAllocInfo() {} | 
| 97 |  | 
| 98 |     /** | 
| 99 |      * \brief AllocInfo constructor that initializes all of the members | 
| 100 |      */ | 
| 101 | 	PxAllocInfo(const char* file, int line, const char* allocName, PxAllocId::Enum allocId) | 
| 102 | 		: mFileName(file) | 
| 103 | 		, mLine(line) | 
| 104 | 		, mAllocName(allocName) | 
| 105 | 		, mAllocId(allocId) | 
| 106 | 	{} | 
| 107 |  | 
| 108 | 	/// \brief get the allocation file name | 
| 109 | 	inline	const char*			getFileName() const | 
| 110 | 	{ | 
| 111 | 		return mFileName; | 
| 112 | 	} | 
| 113 |  | 
| 114 | 	/// \brief get the allocation line | 
| 115 | 	inline	int					getLine() const | 
| 116 | 	{ | 
| 117 | 		return mLine; | 
| 118 | 	} | 
| 119 |  | 
| 120 | 	/// \brief get the allocation name | 
| 121 | 	inline	const char*			getAllocName() const | 
| 122 | 	{ | 
| 123 | 		return mAllocName; | 
| 124 | 	} | 
| 125 |  | 
| 126 | 	/// \brief get the allocation ID | 
| 127 | 	inline	PxAllocId::Enum		getAllocId() const | 
| 128 | 	{ | 
| 129 | 		return mAllocId; | 
| 130 | 	} | 
| 131 |  | 
| 132 | private: | 
| 133 | 	const char*			mFileName; | 
| 134 | 	int					mLine; | 
| 135 | 	const char*			mAllocName; | 
| 136 | 	PxAllocId::Enum		mAllocId; | 
| 137 | }; | 
| 138 |  | 
| 139 | /// \brief statistics collected per AllocationId by HeapManager. | 
| 140 | struct PxAllocIdStats | 
| 141 | { | 
| 142 | 	size_t size;		//!< currently allocated memory by this ID | 
| 143 | 	size_t maxSize;		//!< max allocated memory by this ID | 
| 144 | 	size_t elements;	//!< number of current allocations by this ID | 
| 145 | 	size_t maxElements;	//!< max number of allocations by this ID | 
| 146 | }; | 
| 147 |  | 
| 148 | class PxCudaMemoryManager; | 
| 149 | typedef size_t PxCudaBufferPtr; | 
| 150 |  | 
| 151 | /// \brief Hint flag to tell how the buffer will be used | 
| 152 | struct PxCudaBufferFlags | 
| 153 | { | 
| 154 | /// \brief Enumerations for the hint flag to tell how the buffer will be used | 
| 155 | 	enum Enum | 
| 156 | 	{ | 
| 157 | 		F_READ			= (1 << 0), | 
| 158 | 		F_WRITE			= (1 << 1), | 
| 159 | 		F_READ_WRITE	= F_READ | F_WRITE | 
| 160 | 	}; | 
| 161 | }; | 
| 162 |  | 
| 163 |  | 
| 164 | /// \brief Memory statistics struct returned by CudaMemMgr::getStats() | 
| 165 | struct PxCudaMemoryManagerStats | 
| 166 | { | 
| 167 |  | 
| 168 | 	size_t			heapSize;		//!< Size of all pages allocated for this memory type (allocated + free). | 
| 169 | 	size_t			totalAllocated; //!< Size occupied by the current allocations. | 
| 170 | 	size_t			maxAllocated;	//!< High water mark of allocations since the SDK was created. | 
| 171 | 	PxAllocIdStats	allocIdStats[PxAllocId::NUM_IDS]; //!< Stats for each allocation ID, see PxAllocIdStats | 
| 172 | }; | 
| 173 |  | 
| 174 |  | 
| 175 | /// \brief Buffer type: made of hint flags and the memory space (Device Memory, Pinned Host Memory, ...) | 
| 176 | struct PxCudaBufferType | 
| 177 | { | 
| 178 | 	/// \brief PxCudaBufferType copy constructor | 
| 179 | 	PX_INLINE PxCudaBufferType(const PxCudaBufferType& t) | 
| 180 | 		: memorySpace(t.memorySpace) | 
| 181 | 		, flags(t.flags) | 
| 182 | 	{} | 
| 183 | 	 | 
| 184 | 	/// \brief PxCudaBufferType constructor to explicitely assign members | 
| 185 | 	PX_INLINE PxCudaBufferType(PxCudaBufferMemorySpace::Enum _memSpace, PxCudaBufferFlags::Enum _flags) | 
| 186 | 		: memorySpace(_memSpace) | 
| 187 | 		, flags(_flags) | 
| 188 | 	{} | 
| 189 |  | 
| 190 | 	PxCudaBufferMemorySpace::Enum	memorySpace; 	//!< specifies which memory space for the buffer  | 
| 191 | 	PxCudaBufferFlags::Enum			flags;			//!< specifies the usage flags for the buffer | 
| 192 | }; | 
| 193 |  | 
| 194 |  | 
| 195 | /// \brief Buffer which keeps informations about allocated piece of memory. | 
| 196 | class PxCudaBuffer | 
| 197 | { | 
| 198 | public: | 
| 199 | 	/// Retrieves the manager over which the buffer was allocated. | 
| 200 | 	virtual	PxCudaMemoryManager*			getCudaMemoryManager() const = 0; | 
| 201 |  | 
| 202 | 	/// Releases the buffer and the memory it used, returns true if successful. | 
| 203 | 	virtual	bool						free() = 0; | 
| 204 |  | 
| 205 | 	/// Realloc memory. Use to shrink or resize the allocated chunk of memory of this buffer. | 
| 206 | 	/// Returns true if successful. Fails if the operation would change the address and need a memcopy. | 
| 207 | 	/// In that case the user has to allocate, copy and free the memory with separate steps. | 
| 208 | 	/// Realloc to size 0 always returns false and doesn't change the state. | 
| 209 | 	virtual	bool						realloc(size_t size, PX_ALLOC_INFO_PARAMS_DECL(NULL, 0, NULL, UNASSIGNED)) = 0; | 
| 210 |  | 
| 211 | 	/// Returns the type of the allocated memory. | 
| 212 | 	virtual	const PxCudaBufferType&		getType() const = 0; | 
| 213 |  | 
| 214 | 	/// Returns the pointer to the allocated memory. | 
| 215 | 	virtual	PxCudaBufferPtr				getPtr() const = 0; | 
| 216 |  | 
| 217 | 	/// Returns the size of the allocated memory. | 
| 218 | 	virtual	size_t						getSize() const = 0; | 
| 219 |  | 
| 220 | protected: | 
| 221 |     /// \brief protected destructor | 
| 222 |     virtual ~PxCudaBuffer() {} | 
| 223 | }; | 
| 224 |  | 
| 225 |  | 
| 226 | /// \brief Allocator class for different kinds of CUDA related memory. | 
| 227 | class PxCudaMemoryManager | 
| 228 | { | 
| 229 | public: | 
| 230 | 	/// Allocate memory of given type and size. Returns a CudaBuffer if successful. Returns NULL if failed. | 
| 231 | 	virtual PxCudaBuffer*				alloc(const PxCudaBufferType& type, size_t size, PX_ALLOC_INFO_PARAMS_DECL(NULL, 0, NULL, UNASSIGNED)) = 0; | 
| 232 |  | 
| 233 | 	/// Basic heap allocator without PxCudaBuffer | 
| 234 | 	virtual PxCudaBufferPtr				alloc(PxCudaBufferMemorySpace::Enum memorySpace, size_t size, PX_ALLOC_INFO_PARAMS_DECL(NULL, 0, NULL, UNASSIGNED)) = 0; | 
| 235 |  | 
| 236 | 	/// Basic heap deallocator without PxCudaBuffer | 
| 237 | 	virtual bool						free(PxCudaBufferMemorySpace::Enum memorySpace, PxCudaBufferPtr addr) = 0; | 
| 238 |  | 
| 239 | 	/// Basic heap realloc without PxCudaBuffer | 
| 240 | 	virtual bool						realloc(PxCudaBufferMemorySpace::Enum memorySpace, PxCudaBufferPtr addr, size_t size, PX_ALLOC_INFO_PARAMS_DECL(NULL, 0, NULL, UNASSIGNED)) = 0; | 
| 241 |  | 
| 242 | 	/// Retrieve stats for the memory of given type. See PxCudaMemoryManagerStats. | 
| 243 | 	virtual void						getStats(const PxCudaBufferType& type, PxCudaMemoryManagerStats& outStats) = 0; | 
| 244 |  | 
| 245 | 	/// Ensure that a given amount of free memory is available. Triggers CUDA allocations in size of (2^n * pageSize) if necessary. | 
| 246 | 	/// Returns false if page allocations failed. | 
| 247 | 	virtual bool						reserve(const PxCudaBufferType& type, size_t size) = 0; | 
| 248 |  | 
| 249 | 	/// Set the page size. The managed memory grows by blocks 2^n * pageSize. Page allocations trigger CUDA driver allocations, | 
| 250 | 	/// so the page size should be reasonably big. Returns false if input size was invalid, i.e. not power of two. | 
| 251 | 	/// Default is 2 MB. | 
| 252 | 	virtual bool						setPageSize(const PxCudaBufferType& type, size_t size) = 0; | 
| 253 |  | 
| 254 | 	/// Set the upper limit until which pages of a given memory type can be allocated. | 
| 255 | 	/// Reducing the max when it is already hit does not shrink the memory until it is deallocated by releasing the buffers which own the memory. | 
| 256 | 	virtual bool						setMaxMemorySize(const PxCudaBufferType& type, size_t size) = 0; | 
| 257 |  | 
| 258 | 	/// Returns the base size. The base memory block stays persistently allocated over the SDKs life time. | 
| 259 | 	virtual size_t						getBaseSize(const PxCudaBufferType& type) = 0; | 
| 260 |  | 
| 261 | 	/// Returns the currently set page size. The memory grows and shrinks in blocks of size (2^n pageSize) | 
| 262 | 	virtual size_t						getPageSize(const PxCudaBufferType& type) = 0; | 
| 263 |  | 
| 264 | 	/// Returns the upper limit until which the manager is allowed to allocate additional pages from the CUDA driver. | 
| 265 | 	virtual size_t						getMaxMemorySize(const PxCudaBufferType& type) = 0; | 
| 266 |  | 
| 267 | 	/// Get device mapped pinned host mem ptr. Operation only valid for memory space PxCudaBufferMemorySpace::T_PINNED_HOST. | 
| 268 | 	virtual PxCudaBufferPtr				getMappedPinnedPtr(PxCudaBufferPtr hostPtr) = 0; | 
| 269 |  | 
| 270 | protected: | 
| 271 |     /// \brief protected destructor | 
| 272 |     virtual ~PxCudaMemoryManager() {} | 
| 273 | }; | 
| 274 |  | 
| 275 | PX_POP_PACK | 
| 276 |  | 
| 277 |  | 
| 278 | } // end physx namespace | 
| 279 |  | 
| 280 | #endif // PX_SUPPORT_GPU_PHYSX | 
| 281 | #endif // PXCUDACONTEXTMANAGER_PXCUDAMEMORYMANAGER_H | 
| 282 |  |