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 | |