| 1 | /* |
| 2 | * Copyright (c) 2008-2015, NVIDIA CORPORATION. All rights reserved. |
| 3 | * |
| 4 | * NVIDIA CORPORATION and its licensors retain all intellectual property |
| 5 | * and proprietary rights in and to this software, related documentation |
| 6 | * and any modifications thereto. Any use, reproduction, disclosure or |
| 7 | * distribution of this software and related documentation without an express |
| 8 | * license agreement from NVIDIA CORPORATION is strictly prohibited. |
| 9 | */ |
| 10 | |
| 11 | #ifndef PX_CUDA_MEMORY_MANAGER_H |
| 12 | #define PX_CUDA_MEMORY_MANAGER_H |
| 13 | |
| 14 | #include "foundation/PxSimpleTypes.h" |
| 15 | |
| 16 | // some macros to keep the source code more readable |
| 17 | #define NV_ALLOC_INFO(name, ID) __FILE__, __LINE__, name, physx::PxAllocId::ID |
| 18 | #define NV_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 |
| 19 | #define NV_ALLOC_INFO_PARAMS_DEF() const char* file, int line, const char* allocName, physx::PxAllocId::Enum allocId |
| 20 | #define NV_ALLOC_INFO_PARAMS_INPUT() file, line, allocName, allocId |
| 21 | #define NV_ALLOC_INFO_PARAMS_INPUT_INFO(info) info.getFileName(), info.getLine(), info.getAllocName(), info.getAllocId() |
| 22 | |
| 23 | #ifndef NULL // don't want to include <string.h> |
| 24 | #define NULL 0 |
| 25 | #endif |
| 26 | |
| 27 | #ifndef PX_DOXYGEN |
| 28 | namespace physx |
| 29 | { |
| 30 | #endif |
| 31 | |
| 32 | PX_PUSH_PACK_DEFAULT |
| 33 | |
| 34 | /** \brief ID of the Feature which owns/allocated memory from the heap |
| 35 | * |
| 36 | * Maximum of 64k IDs allowed. |
| 37 | */ |
| 38 | struct PxAllocId |
| 39 | { |
| 40 | /** |
| 41 | * \brief ID of the Feature which owns/allocated memory from the heap |
| 42 | */ |
| 43 | enum Enum |
| 44 | { |
| 45 | UNASSIGNED, //!< default |
| 46 | APEX, //!< APEX stuff not further classified |
| 47 | PARTICLES, //!< all particle related |
| 48 | GPU_UTIL, //!< e.g. RadixSort (used in SPH and deformable self collision) |
| 49 | CLOTH, //!< all cloth related |
| 50 | NUM_IDS //!< number of IDs, be aware that ApexHeapStats contains PxAllocIdStats[NUM_IDS] |
| 51 | }; |
| 52 | }; |
| 53 | |
| 54 | /// \brief memory type managed by a heap |
| 55 | struct PxCudaBufferMemorySpace |
| 56 | { |
| 57 | /** |
| 58 | * \brief memory type managed by a heap |
| 59 | */ |
| 60 | enum Enum |
| 61 | { |
| 62 | T_GPU, |
| 63 | T_PINNED_HOST, |
| 64 | T_WRITE_COMBINED, |
| 65 | T_HOST, |
| 66 | COUNT |
| 67 | }; |
| 68 | }; |
| 69 | |
| 70 | /// \brief class to track allocation statistics, see PxgMirrored |
| 71 | class PxAllocInfo |
| 72 | { |
| 73 | public: |
| 74 | /** |
| 75 | * \brief AllocInfo default constructor |
| 76 | */ |
| 77 | PxAllocInfo() {} |
| 78 | |
| 79 | /** |
| 80 | * \brief AllocInfo constructor that initializes all of the members |
| 81 | */ |
| 82 | PxAllocInfo(const char* file, int line, const char* allocName, PxAllocId::Enum allocId) |
| 83 | : mFileName(file) |
| 84 | , mLine(line) |
| 85 | , mAllocName(allocName) |
| 86 | , mAllocId(allocId) |
| 87 | {} |
| 88 | |
| 89 | /// \brief get the allocation file name |
| 90 | inline const char* getFileName() const |
| 91 | { |
| 92 | return mFileName; |
| 93 | } |
| 94 | |
| 95 | /// \brief get the allocation line |
| 96 | inline int getLine() const |
| 97 | { |
| 98 | return mLine; |
| 99 | } |
| 100 | |
| 101 | /// \brief get the allocation name |
| 102 | inline const char* getAllocName() const |
| 103 | { |
| 104 | return mAllocName; |
| 105 | } |
| 106 | |
| 107 | /// \brief get the allocation ID |
| 108 | inline PxAllocId::Enum getAllocId() const |
| 109 | { |
| 110 | return mAllocId; |
| 111 | } |
| 112 | |
| 113 | private: |
| 114 | const char* mFileName; |
| 115 | int mLine; |
| 116 | const char* mAllocName; |
| 117 | PxAllocId::Enum mAllocId; |
| 118 | }; |
| 119 | |
| 120 | /// \brief statistics collected per AllocationId by HeapManager. |
| 121 | struct PxAllocIdStats |
| 122 | { |
| 123 | size_t size; //!< currently allocated memory by this ID |
| 124 | size_t maxSize; //!< max allocated memory by this ID |
| 125 | size_t elements; //!< number of current allocations by this ID |
| 126 | size_t maxElements; //!< max number of allocations by this ID |
| 127 | }; |
| 128 | |
| 129 | class PxCudaMemoryManager; |
| 130 | typedef size_t PxCudaBufferPtr; |
| 131 | |
| 132 | /// \brief Hint flag to tell how the buffer will be used |
| 133 | struct PxCudaBufferFlags |
| 134 | { |
| 135 | /// \brief Enumerations for the hint flag to tell how the buffer will be used |
| 136 | enum Enum |
| 137 | { |
| 138 | F_READ = (1 << 0), |
| 139 | F_WRITE = (1 << 1), |
| 140 | F_READ_WRITE = F_READ | F_WRITE |
| 141 | }; |
| 142 | }; |
| 143 | |
| 144 | |
| 145 | /// \brief Memory statistics struct returned by CudaMemMgr::getStats() |
| 146 | struct PxCudaMemoryManagerStats |
| 147 | { |
| 148 | |
| 149 | size_t heapSize; //!< Size of all pages allocated for this memory type (allocated + free). |
| 150 | size_t totalAllocated; //!< Size occupied by the current allocations. |
| 151 | size_t maxAllocated; //!< High water mark of allocations since the SDK was created. |
| 152 | PxAllocIdStats allocIdStats[PxAllocId::NUM_IDS]; //!< Stats for each allocation ID, see PxAllocIdStats |
| 153 | }; |
| 154 | |
| 155 | |
| 156 | /// \brief Buffer type: made of hint flags and the memory space (Device Memory, Pinned Host Memory, ...) |
| 157 | struct PxCudaBufferType |
| 158 | { |
| 159 | /// \brief PxCudaBufferType copy constructor |
| 160 | PX_INLINE PxCudaBufferType(const PxCudaBufferType& t) |
| 161 | : memorySpace(t.memorySpace) |
| 162 | , flags(t.flags) |
| 163 | {} |
| 164 | |
| 165 | /// \brief PxCudaBufferType constructor to explicitely assign members |
| 166 | PX_INLINE PxCudaBufferType(PxCudaBufferMemorySpace::Enum _memSpace, PxCudaBufferFlags::Enum _flags) |
| 167 | : memorySpace(_memSpace) |
| 168 | , flags(_flags) |
| 169 | {} |
| 170 | |
| 171 | PxCudaBufferMemorySpace::Enum memorySpace; //!< specifies which memory space for the buffer |
| 172 | PxCudaBufferFlags::Enum flags; //!< specifies the usage flags for the buffer |
| 173 | }; |
| 174 | |
| 175 | |
| 176 | /// \brief Buffer which keeps informations about allocated piece of memory. |
| 177 | class PxCudaBuffer |
| 178 | { |
| 179 | public: |
| 180 | /// Retrieves the manager over which the buffer was allocated. |
| 181 | virtual PxCudaMemoryManager* getCudaMemoryManager() const = 0; |
| 182 | |
| 183 | /// Releases the buffer and the memory it used, returns true if successful. |
| 184 | virtual bool free() = 0; |
| 185 | |
| 186 | /// Realloc memory. Use to shrink or resize the allocated chunk of memory of this buffer. |
| 187 | /// Returns true if successful. Fails if the operation would change the address and need a memcopy. |
| 188 | /// In that case the user has to allocate, copy and free the memory with separate steps. |
| 189 | /// Realloc to size 0 always returns false and doesn't change the state. |
| 190 | virtual bool realloc(size_t size, NV_ALLOC_INFO_PARAMS_DECL(NULL, 0, NULL, UNASSIGNED)) = 0; |
| 191 | |
| 192 | /// Returns the type of the allocated memory. |
| 193 | virtual const PxCudaBufferType& getType() const = 0; |
| 194 | |
| 195 | /// Returns the pointer to the allocated memory. |
| 196 | virtual PxCudaBufferPtr getPtr() const = 0; |
| 197 | |
| 198 | /// Returns the size of the allocated memory. |
| 199 | virtual size_t getSize() const = 0; |
| 200 | |
| 201 | protected: |
| 202 | /// \brief protected destructor |
| 203 | virtual ~PxCudaBuffer() {} |
| 204 | }; |
| 205 | |
| 206 | |
| 207 | /// \brief Allocator class for different kinds of CUDA related memory. |
| 208 | class PxCudaMemoryManager |
| 209 | { |
| 210 | public: |
| 211 | /// Allocate memory of given type and size. Returns a CudaBuffer if successful. Returns NULL if failed. |
| 212 | virtual PxCudaBuffer* alloc(const PxCudaBufferType& type, size_t size, NV_ALLOC_INFO_PARAMS_DECL(NULL, 0, NULL, UNASSIGNED)) = 0; |
| 213 | |
| 214 | /// Basic heap allocator without PxCudaBuffer |
| 215 | virtual PxCudaBufferPtr alloc(PxCudaBufferMemorySpace::Enum memorySpace, size_t size, NV_ALLOC_INFO_PARAMS_DECL(NULL, 0, NULL, UNASSIGNED)) = 0; |
| 216 | |
| 217 | /// Basic heap deallocator without PxCudaBuffer |
| 218 | virtual bool free(PxCudaBufferMemorySpace::Enum memorySpace, PxCudaBufferPtr addr) = 0; |
| 219 | |
| 220 | /// Basic heap realloc without PxCudaBuffer |
| 221 | virtual bool realloc(PxCudaBufferMemorySpace::Enum memorySpace, PxCudaBufferPtr addr, size_t size, NV_ALLOC_INFO_PARAMS_DECL(NULL, 0, NULL, UNASSIGNED)) = 0; |
| 222 | |
| 223 | /// Retrieve stats for the memory of given type. See PxCudaMemoryManagerStats. |
| 224 | virtual void getStats(const PxCudaBufferType& type, PxCudaMemoryManagerStats& outStats) = 0; |
| 225 | |
| 226 | /// Ensure that a given amount of free memory is available. Triggers CUDA allocations in size of (2^n * pageSize) if necessary. |
| 227 | /// Returns false if page allocations failed. |
| 228 | virtual bool reserve(const PxCudaBufferType& type, size_t size) = 0; |
| 229 | |
| 230 | /// Set the page size. The managed memory grows by blocks 2^n * pageSize. Page allocations trigger CUDA driver allocations, |
| 231 | /// so the page size should be reasonably big. Returns false if input size was invalid, i.e. not power of two. |
| 232 | /// Default is 2 MB. |
| 233 | virtual bool setPageSize(const PxCudaBufferType& type, size_t size) = 0; |
| 234 | |
| 235 | /// Set the upper limit until which pages of a given memory type can be allocated. |
| 236 | /// 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. |
| 237 | virtual bool setMaxMemorySize(const PxCudaBufferType& type, size_t size) = 0; |
| 238 | |
| 239 | /// Returns the base size. The base memory block stays persistently allocated over the SDKs life time. |
| 240 | virtual size_t getBaseSize(const PxCudaBufferType& type) = 0; |
| 241 | |
| 242 | /// Returns the currently set page size. The memory grows and shrinks in blocks of size (2^n pageSize) |
| 243 | virtual size_t getPageSize(const PxCudaBufferType& type) = 0; |
| 244 | |
| 245 | /// Returns the upper limit until which the manager is allowed to allocate additional pages from the CUDA driver. |
| 246 | virtual size_t getMaxMemorySize(const PxCudaBufferType& type) = 0; |
| 247 | |
| 248 | /// Get device mapped pinned host mem ptr. Operation only valid for memory space PxCudaBufferMemorySpace::T_PINNED_HOST. |
| 249 | virtual PxCudaBufferPtr getMappedPinnedPtr(PxCudaBufferPtr hostPtr) = 0; |
| 250 | |
| 251 | protected: |
| 252 | /// \brief protected destructor |
| 253 | virtual ~PxCudaMemoryManager() {} |
| 254 | }; |
| 255 | |
| 256 | PX_POP_PACK |
| 257 | |
| 258 | #ifndef PX_DOXYGEN |
| 259 | } // end physx namespace |
| 260 | #endif |
| 261 | |
| 262 | #endif |
| 263 | |