diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PxShared/include/cudamanager | |
| download | physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip | |
Initial commit:
PhysX 3.4.0 Update @ 21294896
APEX 1.4.0 Update @ 21275617
[CL 21300167]
Diffstat (limited to 'PxShared/include/cudamanager')
| -rw-r--r-- | PxShared/include/cudamanager/PxCudaContextManager.h | 418 | ||||
| -rw-r--r-- | PxShared/include/cudamanager/PxCudaMemoryManager.h | 281 | ||||
| -rw-r--r-- | PxShared/include/cudamanager/PxGpuCopyDesc.h | 86 | ||||
| -rw-r--r-- | PxShared/include/cudamanager/PxGpuCopyDescQueue.h | 149 |
4 files changed, 934 insertions, 0 deletions
diff --git a/PxShared/include/cudamanager/PxCudaContextManager.h b/PxShared/include/cudamanager/PxCudaContextManager.h new file mode 100644 index 00000000..8e84b3b4 --- /dev/null +++ b/PxShared/include/cudamanager/PxCudaContextManager.h @@ -0,0 +1,418 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + + +#ifndef PXCUDACONTEXTMANAGER_PXCUDACONTEXTMANAGER_H +#define PXCUDACONTEXTMANAGER_PXCUDACONTEXTMANAGER_H + +#include "foundation/PxPreprocessor.h" + +#if PX_SUPPORT_GPU_PHYSX + +#include "foundation/PxSimpleTypes.h" +#include "foundation/PxErrorCallback.h" +#include "foundation/PxFlags.h" +#include "task/PxTaskDefine.h" +#include "cudamanager/PxCudaMemoryManager.h" + +/* Forward decl to avoid inclusion of cuda.h */ +typedef struct CUctx_st *CUcontext; +typedef struct CUgraphicsResource_st *CUgraphicsResource; + +namespace physx +{ + +class PxGpuDispatcher; + + +/** \brief Possible graphic/CUDA interoperability modes for context */ +struct PxCudaInteropMode +{ + /** + * \brief Possible graphic/CUDA interoperability modes for context + */ + enum Enum + { + NO_INTEROP = 0, + D3D10_INTEROP, + D3D11_INTEROP, + OGL_INTEROP, + + COUNT + }; +}; + +struct PxCudaInteropRegisterFlag +{ + enum Enum + { + eNONE = 0x00, + eREAD_ONLY = 0x01, + eWRITE_DISCARD = 0x02, + eSURFACE_LDST = 0x04, + eTEXTURE_GATHER = 0x08 + }; +}; + +/** +\brief collection of set bits defined in NxCudaInteropRegisterFlag. + +@see NxCudaInteropRegisterFlag +*/ +typedef PxFlags<PxCudaInteropRegisterFlag::Enum, uint32_t> PxCudaInteropRegisterFlags; +PX_FLAGS_OPERATORS(PxCudaInteropRegisterFlag::Enum, uint32_t) + +//! \brief Descriptor used to create a PxCudaContextManager +class PxCudaContextManagerDesc +{ +public: + /** + * \brief The CUDA context to manage + * + * If left NULL, the PxCudaContextManager will create a new context. If + * graphicsDevice is also not NULL, this new CUDA context will be bound to + * that graphics device, enabling the use of CUDA/Graphics interop features. + * + * If ctx is not NULL, the specified context must be applied to the thread + * that is allocating the PxCudaContextManager at creation time (aka, it + * cannot be popped). The PxCudaContextManager will take ownership of the + * context until the manager is released. All access to the context must be + * gated by lock acquisition. + * + * If the user provides a context for the PxCudaContextManager, the context + * _must_ have either been created on the GPU ordinal returned by + * PxGetSuggestedCudaDeviceOrdinal() or on your graphics device. + * + * It is perfectly acceptable to allocate device or host pinned memory from + * the context outside the scope of the PxCudaMemoryManager, so long as you + * manage its eventual cleanup. + */ + CUcontext *ctx; + + /** + * \brief D3D device pointer or OpenGl context handle + * + * Only applicable when ctx is NULL, thus forcing a new context to be + * created. In that case, the created context will be bound to this + * graphics device. + */ + void *graphicsDevice; + +#if PX_SUPPORT_GPU_PHYSX + /** + * \brief Application-specific GUID + * + * If your application employs PhysX modules that use CUDA you need to use a GUID + * so that patches for new architectures can be released for your game.You can obtain a GUID for your + * application from Nvidia. + */ + const char* appGUID; +#endif + /** + * \brief The CUDA/Graphics interop mode of this context + * + * If ctx is NULL, this value describes the nature of the graphicsDevice + * pointer provided by the user. Else it describes the nature of the + * context provided by the user. + */ + PxCudaInteropMode::Enum interopMode; + + + /** + * \brief Size of persistent memory + * + * This memory is allocated up front and stays allocated until the + * PxCudaContextManager is released. Size is in bytes, has to be power of two + * and bigger than the page size. Set to 0 to only use dynamic pages. + * + * Note: On Vista O/S and above, there is a per-memory allocation overhead + * to every CUDA work submission, so we recommend that you carefully tune + * this initial base memory size to closely approximate the amount of + * memory your application will consume. + + Note: This is currently not used by PxSceneFlag::eENABLE_GPU_DYNAMICS. Memory allocation properties are configured + for GPU rigid bodies using PxSceneDesc::gpuDynamicsConfig. + */ + uint32_t memoryBaseSize[PxCudaBufferMemorySpace::COUNT]; + + /** + * \brief Size of memory pages + * + * The memory manager will dynamically grow and shrink in blocks multiple of + * this page size. Size has to be power of two and bigger than 0. + + Note: This is currently not used by PxSceneFlag::eENABLE_GPU_DYNAMICS. Memory allocation properties are configured + for GPU rigid bodies using PxSceneDesc::gpuDynamicsConfig. + */ + uint32_t memoryPageSize[PxCudaBufferMemorySpace::COUNT]; + + /** + * \brief Maximum size of memory that the memory manager will allocate + + Note: This is currently not used by PxSceneFlag::eENABLE_GPU_DYNAMICS. Memory allocation properties are configured + for GPU rigid bodies using PxSceneDesc::gpuDynamicsConfig. + */ + uint32_t maxMemorySize[PxCudaBufferMemorySpace::COUNT]; + + PX_INLINE PxCudaContextManagerDesc() + { + ctx = NULL; + interopMode = PxCudaInteropMode::NO_INTEROP; + graphicsDevice = 0; +#if PX_SUPPORT_GPU_PHYSX + appGUID = NULL; +#endif + for(uint32_t i = 0; i < PxCudaBufferMemorySpace::COUNT; i++) + { + memoryBaseSize[i] = 0; + memoryPageSize[i] = 2 * 1024*1024; + maxMemorySize[i] = UINT32_MAX; + } + } +}; + + +/** + * \brief Manages memory, thread locks, and task scheduling for a CUDA context + * + * A PxCudaContextManager manages access to a single CUDA context, allowing it to + * be shared between multiple scenes. Memory allocations are dynamic: starting + * with an initial heap size and growing on demand by a configurable page size. + * The context must be acquired from the manager before using any CUDA APIs. + * + * The PxCudaContextManager is based on the CUDA driver API and explictly does not + * support the CUDA runtime API (aka, CUDART). + * + * To enable CUDA use by an APEX scene, a PxCudaContextManager must be created + * (supplying your own CUDA context, or allowing a new context to be allocated + * for you), the PxGpuDispatcher for that context is retrieved via the + * getGpuDispatcher() method, and this is assigned to the TaskManager that is + * given to the scene via its NxApexSceneDesc. + */ +class PxCudaContextManager +{ +public: + /** + * \brief Acquire the CUDA context for the current thread + * + * Acquisitions are allowed to be recursive within a single thread. + * You can acquire the context multiple times so long as you release + * it the same count. + * + * The context must be acquired before using most CUDA functions. + * + * It is not necessary to acquire the CUDA context inside GpuTask + * launch functions, because the PxGpuDispatcher will have already + * acquired the context for its worker thread. However it is not + * harmfull to (re)acquire the context in code that is shared between + * GpuTasks and non-task functions. + */ + virtual void acquireContext() = 0; + + /** + * \brief Release the CUDA context from the current thread + * + * The CUDA context should be released as soon as practically + * possible, to allow other CPU threads (including the + * PxGpuDispatcher) to work efficiently. + */ + virtual void releaseContext() = 0; + + /** + * \brief Return the PxCudaMemoryManager instance associated with this + * CUDA context + * Note: This is currently not used by PxSceneFlag::eENABLE_GPU_DYNAMICS. Memory allocation properties are configured + * for GPU rigid bodies using PxSceneDesc::gpuDynamicsConfig. + */ + virtual PxCudaMemoryManager *getMemoryManager() = 0; + + /** + * \brief Return the PxGpuDispatcher instance associated with this + * CUDA context + */ + virtual class physx::PxGpuDispatcher *getGpuDispatcher() = 0; + + /** + * \brief Context manager has a valid CUDA context + * + * This method should be called after creating a PxCudaContextManager, + * especially if the manager was responsible for allocating its own + * CUDA context (desc.ctx == NULL). If it returns false, there is + * no point in assigning this manager's PxGpuDispatcher to a + * TaskManager as it will be unable to execute GpuTasks. + */ + virtual bool contextIsValid() const = 0; + + /* Query CUDA context and device properties, without acquiring context */ + + virtual bool supportsArchSM10() const = 0; //!< G80 + virtual bool supportsArchSM11() const = 0; //!< G92 + virtual bool supportsArchSM12() const = 0; //!< GT200 + virtual bool supportsArchSM13() const = 0; //!< GT260 + virtual bool supportsArchSM20() const = 0; //!< GF100 + virtual bool supportsArchSM30() const = 0; //!< GK100 + virtual bool supportsArchSM35() const = 0; //!< GK110 + virtual bool supportsArchSM50() const = 0; //!< GM100 + virtual bool supportsArchSM52() const = 0; //!< GM200 + virtual bool supportsArchSM60() const = 0; //!< GP100 + virtual bool isIntegrated() const = 0; //!< true if GPU is an integrated (MCP) part + virtual bool canMapHostMemory() const = 0; //!< true if GPU map host memory to GPU (0-copy) + virtual int getDriverVersion() const = 0; //!< returns cached value of cuGetDriverVersion() + virtual size_t getDeviceTotalMemBytes() const = 0; //!< returns cached value of device memory size + virtual int getMultiprocessorCount() const = 0; //!< returns cache value of SM unit count + virtual unsigned int getClockRate() const = 0; //!< returns cached value of SM clock frequency + virtual int getSharedMemPerBlock() const = 0; //!< returns total amount of shared memory available per block in bytes + virtual int getSharedMemPerMultiprocessor() const = 0; //!< returns total amount of shared memory available per multiprocessor in bytes + virtual unsigned int getMaxThreadsPerBlock() const = 0; //!< returns the maximum number of threads per block + virtual const char *getDeviceName() const = 0; //!< returns device name retrieved from driver + virtual PxCudaInteropMode::Enum getInteropMode() const = 0; //!< interop mode the context was created with + + virtual void setUsingConcurrentStreams(bool) = 0; //!< turn on/off using concurrent streams for GPU work + virtual bool getUsingConcurrentStreams() const = 0; //!< true if GPU work can run in concurrent streams + /* End query methods that don't require context to be acquired */ + + /** + * \brief Register a rendering resource with CUDA + * + * This function is called to register render resources (allocated + * from OpenGL) with CUDA so that the memory may be shared + * between the two systems. This is only required for render + * resources that are designed for interop use. In APEX, each + * render resource descriptor that could support interop has a + * 'registerInCUDA' boolean variable. + * + * The function must be called again any time your graphics device + * is reset, to re-register the resource. + * + * Returns true if the registration succeeded. A registered + * resource must be unregistered before it can be released. + * + * \param resource [OUT] the handle to the resource that can be used with CUDA + * \param buffer [IN] GLuint buffer index to be mapped to cuda + * \param flags [IN] cuda interop registration flags + */ + virtual bool registerResourceInCudaGL(CUgraphicsResource &resource, uint32_t buffer, PxCudaInteropRegisterFlags flags = PxCudaInteropRegisterFlags()) = 0; + + /** + * \brief Register a rendering resource with CUDA + * + * This function is called to register render resources (allocated + * from Direct3D) with CUDA so that the memory may be shared + * between the two systems. This is only required for render + * resources that are designed for interop use. In APEX, each + * render resource descriptor that could support interop has a + * 'registerInCUDA' boolean variable. + * + * The function must be called again any time your graphics device + * is reset, to re-register the resource. + * + * Returns true if the registration succeeded. A registered + * resource must be unregistered before it can be released. + * + * \param resource [OUT] the handle to the resource that can be used with CUDA + * \param resourcePointer [IN] A pointer to either IDirect3DResource9, or ID3D10Device, or ID3D11Resource to be registered. + * \param flags [IN] cuda interop registration flags + */ + virtual bool registerResourceInCudaD3D(CUgraphicsResource &resource, void *resourcePointer, PxCudaInteropRegisterFlags flags = PxCudaInteropRegisterFlags()) = 0; + + /** + * \brief Unregister a rendering resource with CUDA + * + * If a render resource was successfully registered with CUDA using + * the registerResourceInCuda***() methods, this function must be called + * to unregister the resource before the it can be released. + */ + virtual bool unregisterResourceInCuda(CUgraphicsResource resource) = 0; + + /** + * \brief Determine if the user has configured a dedicated PhysX GPU in the NV Control Panel + * \note If using CUDA Interop, this will always return false + * \returns 1 if there is a dedicated GPU + * 0 if there is NOT a dedicated GPU + * -1 if the routine is not implemented + */ + virtual int usingDedicatedGPU() const = 0; + + /** + * \brief Release the PxCudaContextManager + * + * When the manager instance is released, it also releases its + * PxGpuDispatcher instance and PxCudaMemoryManager. Before the memory + * manager is released, it frees all allocated memory pages. If the + * PxCudaContextManager created the CUDA context it was responsible + * for, it also frees that context. + * + * Do not release the PxCudaContextManager if there are any scenes + * using its PxGpuDispatcher. Those scenes must be released first + * since there is no safe way to remove a PxGpuDispatcher from a + * TaskManager once the TaskManager has been given to a scene. + * + */ + virtual void release() = 0; + +protected: + + /** + * \brief protected destructor, use release() method + */ + virtual ~PxCudaContextManager() {} +}; + +/** + * \brief Convenience class for holding CUDA lock within a scope + */ +class PxScopedCudaLock +{ +public: + /** + * \brief ScopedCudaLock constructor + */ + PxScopedCudaLock(PxCudaContextManager& ctx) : mCtx(&ctx) + { + mCtx->acquireContext(); + } + + /** + * \brief ScopedCudaLock destructor + */ + ~PxScopedCudaLock() + { + mCtx->releaseContext(); + } + +protected: + + /** + * \brief CUDA context manager pointer (initialized in the constructor) + */ + PxCudaContextManager* mCtx; +}; + +} // end physx namespace + +#endif // PX_SUPPORT_GPU_PHYSX +#endif // PXCUDACONTEXTMANAGER_PXCUDACONTEXTMANAGER_H diff --git a/PxShared/include/cudamanager/PxCudaMemoryManager.h b/PxShared/include/cudamanager/PxCudaMemoryManager.h new file mode 100644 index 00000000..6798faba --- /dev/null +++ b/PxShared/include/cudamanager/PxCudaMemoryManager.h @@ -0,0 +1,281 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXCUDACONTEXTMANAGER_PXCUDAMEMORYMANAGER_H +#define PXCUDACONTEXTMANAGER_PXCUDAMEMORYMANAGER_H + +#include "foundation/PxPreprocessor.h" + +#if PX_SUPPORT_GPU_PHYSX + +#include "task/PxTaskDefine.h" + +// some macros to keep the source code more readable +#define PX_ALLOC_INFO(name, ID) __FILE__, __LINE__, name, physx::PxAllocId::ID +#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 +#define PX_ALLOC_INFO_PARAMS_DEF() const char* file, int line, const char* allocName, physx::PxAllocId::Enum allocId +#define PX_ALLOC_INFO_PARAMS_INPUT() file, line, allocName, allocId +#define PX_ALLOC_INFO_PARAMS_INPUT_INFO(info) info.getFileName(), info.getLine(), info.getAllocName(), info.getAllocId() + +#ifndef NULL // don't want to include <string.h> +#define NULL 0 +#endif + +namespace physx +{ + +PX_PUSH_PACK_DEFAULT + +/** \brief ID of the Feature which owns/allocated memory from the heap + * + * Maximum of 64k IDs allowed. + */ +struct PxAllocId +{ + /** + * \brief ID of the Feature which owns/allocated memory from the heap + */ + enum Enum + { + UNASSIGNED, //!< default + APEX, //!< APEX stuff not further classified + PARTICLES, //!< all particle related + GPU_UTIL, //!< e.g. RadixSort (used in SPH and deformable self collision) + CLOTH, //!< all cloth related + NUM_IDS //!< number of IDs, be aware that ApexHeapStats contains PxAllocIdStats[NUM_IDS] + }; +}; + +/// \brief memory type managed by a heap +struct PxCudaBufferMemorySpace +{ + /** + * \brief memory type managed by a heap + */ + enum Enum + { + T_GPU, + T_PINNED_HOST, + T_WRITE_COMBINED, + T_HOST, + COUNT + }; +}; + +/// \brief class to track allocation statistics, see PxgMirrored +class PxAllocInfo +{ +public: + /** + * \brief AllocInfo default constructor + */ + PxAllocInfo() {} + + /** + * \brief AllocInfo constructor that initializes all of the members + */ + PxAllocInfo(const char* file, int line, const char* allocName, PxAllocId::Enum allocId) + : mFileName(file) + , mLine(line) + , mAllocName(allocName) + , mAllocId(allocId) + {} + + /// \brief get the allocation file name + inline const char* getFileName() const + { + return mFileName; + } + + /// \brief get the allocation line + inline int getLine() const + { + return mLine; + } + + /// \brief get the allocation name + inline const char* getAllocName() const + { + return mAllocName; + } + + /// \brief get the allocation ID + inline PxAllocId::Enum getAllocId() const + { + return mAllocId; + } + +private: + const char* mFileName; + int mLine; + const char* mAllocName; + PxAllocId::Enum mAllocId; +}; + +/// \brief statistics collected per AllocationId by HeapManager. +struct PxAllocIdStats +{ + size_t size; //!< currently allocated memory by this ID + size_t maxSize; //!< max allocated memory by this ID + size_t elements; //!< number of current allocations by this ID + size_t maxElements; //!< max number of allocations by this ID +}; + +class PxCudaMemoryManager; +typedef size_t PxCudaBufferPtr; + +/// \brief Hint flag to tell how the buffer will be used +struct PxCudaBufferFlags +{ +/// \brief Enumerations for the hint flag to tell how the buffer will be used + enum Enum + { + F_READ = (1 << 0), + F_WRITE = (1 << 1), + F_READ_WRITE = F_READ | F_WRITE + }; +}; + + +/// \brief Memory statistics struct returned by CudaMemMgr::getStats() +struct PxCudaMemoryManagerStats +{ + + size_t heapSize; //!< Size of all pages allocated for this memory type (allocated + free). + size_t totalAllocated; //!< Size occupied by the current allocations. + size_t maxAllocated; //!< High water mark of allocations since the SDK was created. + PxAllocIdStats allocIdStats[PxAllocId::NUM_IDS]; //!< Stats for each allocation ID, see PxAllocIdStats +}; + + +/// \brief Buffer type: made of hint flags and the memory space (Device Memory, Pinned Host Memory, ...) +struct PxCudaBufferType +{ + /// \brief PxCudaBufferType copy constructor + PX_INLINE PxCudaBufferType(const PxCudaBufferType& t) + : memorySpace(t.memorySpace) + , flags(t.flags) + {} + + /// \brief PxCudaBufferType constructor to explicitely assign members + PX_INLINE PxCudaBufferType(PxCudaBufferMemorySpace::Enum _memSpace, PxCudaBufferFlags::Enum _flags) + : memorySpace(_memSpace) + , flags(_flags) + {} + + PxCudaBufferMemorySpace::Enum memorySpace; //!< specifies which memory space for the buffer + PxCudaBufferFlags::Enum flags; //!< specifies the usage flags for the buffer +}; + + +/// \brief Buffer which keeps informations about allocated piece of memory. +class PxCudaBuffer +{ +public: + /// Retrieves the manager over which the buffer was allocated. + virtual PxCudaMemoryManager* getCudaMemoryManager() const = 0; + + /// Releases the buffer and the memory it used, returns true if successful. + virtual bool free() = 0; + + /// Realloc memory. Use to shrink or resize the allocated chunk of memory of this buffer. + /// Returns true if successful. Fails if the operation would change the address and need a memcopy. + /// In that case the user has to allocate, copy and free the memory with separate steps. + /// Realloc to size 0 always returns false and doesn't change the state. + virtual bool realloc(size_t size, PX_ALLOC_INFO_PARAMS_DECL(NULL, 0, NULL, UNASSIGNED)) = 0; + + /// Returns the type of the allocated memory. + virtual const PxCudaBufferType& getType() const = 0; + + /// Returns the pointer to the allocated memory. + virtual PxCudaBufferPtr getPtr() const = 0; + + /// Returns the size of the allocated memory. + virtual size_t getSize() const = 0; + +protected: + /// \brief protected destructor + virtual ~PxCudaBuffer() {} +}; + + +/// \brief Allocator class for different kinds of CUDA related memory. +class PxCudaMemoryManager +{ +public: + /// Allocate memory of given type and size. Returns a CudaBuffer if successful. Returns NULL if failed. + virtual PxCudaBuffer* alloc(const PxCudaBufferType& type, size_t size, PX_ALLOC_INFO_PARAMS_DECL(NULL, 0, NULL, UNASSIGNED)) = 0; + + /// Basic heap allocator without PxCudaBuffer + virtual PxCudaBufferPtr alloc(PxCudaBufferMemorySpace::Enum memorySpace, size_t size, PX_ALLOC_INFO_PARAMS_DECL(NULL, 0, NULL, UNASSIGNED)) = 0; + + /// Basic heap deallocator without PxCudaBuffer + virtual bool free(PxCudaBufferMemorySpace::Enum memorySpace, PxCudaBufferPtr addr) = 0; + + /// Basic heap realloc without PxCudaBuffer + virtual bool realloc(PxCudaBufferMemorySpace::Enum memorySpace, PxCudaBufferPtr addr, size_t size, PX_ALLOC_INFO_PARAMS_DECL(NULL, 0, NULL, UNASSIGNED)) = 0; + + /// Retrieve stats for the memory of given type. See PxCudaMemoryManagerStats. + virtual void getStats(const PxCudaBufferType& type, PxCudaMemoryManagerStats& outStats) = 0; + + /// Ensure that a given amount of free memory is available. Triggers CUDA allocations in size of (2^n * pageSize) if necessary. + /// Returns false if page allocations failed. + virtual bool reserve(const PxCudaBufferType& type, size_t size) = 0; + + /// Set the page size. The managed memory grows by blocks 2^n * pageSize. Page allocations trigger CUDA driver allocations, + /// so the page size should be reasonably big. Returns false if input size was invalid, i.e. not power of two. + /// Default is 2 MB. + virtual bool setPageSize(const PxCudaBufferType& type, size_t size) = 0; + + /// Set the upper limit until which pages of a given memory type can be allocated. + /// 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. + virtual bool setMaxMemorySize(const PxCudaBufferType& type, size_t size) = 0; + + /// Returns the base size. The base memory block stays persistently allocated over the SDKs life time. + virtual size_t getBaseSize(const PxCudaBufferType& type) = 0; + + /// Returns the currently set page size. The memory grows and shrinks in blocks of size (2^n pageSize) + virtual size_t getPageSize(const PxCudaBufferType& type) = 0; + + /// Returns the upper limit until which the manager is allowed to allocate additional pages from the CUDA driver. + virtual size_t getMaxMemorySize(const PxCudaBufferType& type) = 0; + + /// Get device mapped pinned host mem ptr. Operation only valid for memory space PxCudaBufferMemorySpace::T_PINNED_HOST. + virtual PxCudaBufferPtr getMappedPinnedPtr(PxCudaBufferPtr hostPtr) = 0; + +protected: + /// \brief protected destructor + virtual ~PxCudaMemoryManager() {} +}; + +PX_POP_PACK + + +} // end physx namespace + +#endif // PX_SUPPORT_GPU_PHYSX +#endif // PXCUDACONTEXTMANAGER_PXCUDAMEMORYMANAGER_H diff --git a/PxShared/include/cudamanager/PxGpuCopyDesc.h b/PxShared/include/cudamanager/PxGpuCopyDesc.h new file mode 100644 index 00000000..5704e327 --- /dev/null +++ b/PxShared/include/cudamanager/PxGpuCopyDesc.h @@ -0,0 +1,86 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXCUDACONTEXTMANAGER_PXGPUCOPYDESC_H +#define PXCUDACONTEXTMANAGER_PXGPUCOPYDESC_H + +#include "foundation/PxPreprocessor.h" + +#if PX_SUPPORT_GPU_PHYSX + +#include "task/PxTaskDefine.h" + +namespace physx +{ + +PX_PUSH_PACK_DEFAULT + +/** + * \brief Input descriptor for the GpuDispatcher's built-in copy kernel + * + * All host memory involved in copy transactions must be page-locked. + * If more than one descriptor is passed to the copy kernel in one launch, + * the descriptors themselves must be in page-locked memory. + */ +struct PxGpuCopyDesc +{ + /** + * \brief Input descriptor for the GpuDispatcher's built-in copy kernel + */ + enum CopyType + { + HostToDevice, + DeviceToHost, + DeviceToDevice, + DeviceMemset32 + }; + + size_t dest; //!< the destination + size_t source; //!< the source (32bit value when type == DeviceMemset) + size_t bytes; //!< the size in bytes + CopyType type; //!< the memory transaction type + + /** + * \brief Copy is optimally performed as 64bit words, requires 64bit alignment. But it can + * gracefully degrade to 32bit copies if necessary + */ + PX_INLINE bool isValid() + { + bool ok = true; + ok &= ((dest & 0x3) == 0); + ok &= ((type == DeviceMemset32) || (source & 0x3) == 0); + ok &= ((bytes & 0x3) == 0); + return ok; + } +}; + +PX_POP_PACK + +} // end physx namespace + +#endif // PX_SUPPORT_GPU_PHYSX +#endif // PXCUDACONTEXTMANAGER_PXGPUCOPYDESC_H diff --git a/PxShared/include/cudamanager/PxGpuCopyDescQueue.h b/PxShared/include/cudamanager/PxGpuCopyDescQueue.h new file mode 100644 index 00000000..3cb0067a --- /dev/null +++ b/PxShared/include/cudamanager/PxGpuCopyDescQueue.h @@ -0,0 +1,149 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved. + +#ifndef PXCUDACONTEXTMANAGER_PXGPUCOPYDESCQUEUE_H +#define PXCUDACONTEXTMANAGER_PXGPUCOPYDESCQUEUE_H + +#include "foundation/PxPreprocessor.h" + +#if PX_SUPPORT_GPU_PHYSX + +#include "foundation/PxAssert.h" +#include "task/PxTaskDefine.h" +#include "task/PxGpuDispatcher.h" +#include "cudamanager/PxGpuCopyDesc.h" +#include "cudamanager/PxCudaContextManager.h" + +/* forward decl to avoid including <cuda.h> */ +typedef struct CUstream_st* CUstream; + +namespace physx +{ + +PX_PUSH_PACK_DEFAULT + +/// \brief Container class for queueing PxGpuCopyDesc instances in pinned (non-pageable) CPU memory +class PxGpuCopyDescQueue +{ +public: + /// \brief PxGpuCopyDescQueue constructor + PxGpuCopyDescQueue(PxGpuDispatcher& d) + : mDispatcher(d) + , mBuffer(0) + , mStream(0) + , mReserved(0) + , mOccupancy(0) + , mFlushed(0) + { + } + + /// \brief PxGpuCopyDescQueue destructor + ~PxGpuCopyDescQueue() + { + if (mBuffer) + { + mDispatcher.getCudaContextManager()->getMemoryManager()->free(PxCudaBufferMemorySpace::T_PINNED_HOST, (size_t) mBuffer); + } + } + + /// \brief Reset the enqueued copy descriptor list + /// + /// Must be called at least once before any copies are enqueued, and each time the launched + /// copies are known to have been completed. The recommended use case is to call this at the + /// start of each simulation step. + void reset(CUstream stream, uint32_t reserveSize) + { + if (reserveSize > mReserved) + { + if (mBuffer) + { + mDispatcher.getCudaContextManager()->getMemoryManager()->free( + PxCudaBufferMemorySpace::T_PINNED_HOST, + (size_t) mBuffer); + mReserved = 0; + } + mBuffer = (PxGpuCopyDesc*) mDispatcher.getCudaContextManager()->getMemoryManager()->alloc( + PxCudaBufferMemorySpace::T_PINNED_HOST, + reserveSize * sizeof(PxGpuCopyDesc), + PX_ALLOC_INFO("PxGpuCopyDescQueue", GPU_UTIL)); + if (mBuffer) + { + mReserved = reserveSize; + } + } + + mOccupancy = 0; + mFlushed = 0; + mStream = stream; + } + + /// \brief Enqueue the specified copy descriptor, or launch immediately if no room is available + void enqueue(PxGpuCopyDesc& desc) + { + PX_ASSERT(desc.isValid()); + if (desc.bytes == 0) + { + return; + } + + if (mOccupancy < mReserved) + { + mBuffer[ mOccupancy++ ] = desc; + } + else + { + mDispatcher.launchCopyKernel(&desc, 1, mStream); + } + } + + /// \brief Launch all copies queued since the last flush or reset + void flushEnqueued() + { + if (mOccupancy > mFlushed) + { + mDispatcher.launchCopyKernel(mBuffer + mFlushed, mOccupancy - mFlushed, mStream); + mFlushed = mOccupancy; + } + } + +private: + PxGpuDispatcher& mDispatcher; + PxGpuCopyDesc* mBuffer; + CUstream mStream; + uint32_t mReserved; + uint32_t mOccupancy; + uint32_t mFlushed; + + void operator=(const PxGpuCopyDescQueue&); // prevent a warning... +}; + +PX_POP_PACK + +} // end physx namespace + +#endif // PX_SUPPORT_GPU_PHYSX +#endif // PXCUDACONTEXTMANAGER_PXGPUCOPYDESCQUEUE_H |