// 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-2020 NVIDIA Corporation. All rights reserved. // Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. // Copyright (c) 2001-2004 NovodeX AG. All rights reserved. #pragma once #include #include "CuCheckSuccess.h" #include "NvCloth/Allocator.h" // todo: rename file to CuHostAllocator.h namespace nv { namespace cloth { template class CuHostAllocator { public: typedef T value_type; CuHostAllocator(CUcontext ctx = nullptr) : mContext(ctx), mDevicePtr(0) {} template CuHostAllocator(const CuHostAllocator& other) : mContext(other.mContext), mDevicePtr(0) {} template struct rebind { typedef CuHostAllocator other; }; T* allocate(size_t num, const char*, int) { void* ptr = nullptr; checkSuccess(cuMemHostAlloc(&ptr, num * sizeof(T), Flags)); #if PX_VC #pragma warning(push) #pragma warning(disable : 4127) // conditional expression is constant #endif if (Flags & CU_MEMHOSTALLOC_DEVICEMAP) checkSuccess(cuMemHostGetDevicePointer(&mDevicePtr, ptr, 0)); #if PX_VC #pragma warning(pop) #endif return static_cast(ptr); } void deallocate(void* ptr) { checkSuccess(cuMemFreeHost(ptr)); } #if PX_VC template void construct(U* p, T&& val) { new (static_cast(p)) U(std::forward(val)); } #else typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; template void construct(U* p, Args&&... args) { ::new (static_cast(p)) U(std::forward(args)...); } #endif void destroy(T* ptr) { PX_UNUSED(ptr); ptr->~T(); } CUcontext mContext; CUdeviceptr mDevicePtr; // device pointer of last allocation }; template bool operator == (const CuHostAllocator&, const CuHostAllocator&) { return true; } template bool operator!=(const CuHostAllocator&, const CuHostAllocator&) { return false; } //Use CuHostVectorImpl instead of nv::cloth::Array> //This entire class is just to make sure that the mDevicePtr from the CuHostAllocator is properly swapped together with mData template class CuHostVectorImpl : public ps::Array> { typedef ps::Array> Super; typedef CuHostAllocator Alloc; public: explicit CuHostVectorImpl(const physx::PxEMPTY v):Super(v){} PX_INLINE explicit CuHostVectorImpl(const Alloc& alloc = Alloc()):Super(alloc){} PX_INLINE explicit CuHostVectorImpl(uint32_t size, const T& a = T(), const Alloc& alloc = Alloc()):Super(size,a,alloc){} template PX_INLINE explicit CuHostVectorImpl(const ps::Array& other, const Alloc& alloc = Alloc()):Super(other,alloc){} PX_INLINE CuHostVectorImpl(const CuHostVectorImpl& other, const Alloc& alloc = Alloc()):Super(other,alloc){} PX_INLINE explicit CuHostVectorImpl(const T* first, const T* last, const Alloc& alloc = Alloc()):Super(first,last,alloc){} void swap(CuHostVectorImpl& other) { NV_CLOTH_ASSERT(this->mContext == other.mContext); ps::swap(this->mDevicePtr, other.mDevicePtr); Super::swap(other); } }; template struct CuHostVector { typedef CuHostVectorImpl Type; }; template T* getDevicePointer(nv::cloth::CuHostVectorImpl& vector) { // cached device pointer only valid if non-empty return vector.empty() ? 0 : reinterpret_cast(vector.getAllocator().mDevicePtr); } namespace ps { //Make sure we call the correct swap function when using the free function swap template PX_INLINE void swap(nv::cloth::CuHostVectorImpl& x, nv::cloth::CuHostVectorImpl& y) { x.swap(y); } } } // namespace cloth } // namespace nv