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#include "PxPhysXConfig.h"
29
30#if PX_SUPPORT_GPU_PHYSX
31
32#include "foundation/Px.h"
33#include "gpu/PxGpu.h"
34#include "cudamanager/PxCudaContextManager.h"
35#include "PxPhysics.h"
36
37#include "PsFoundation.h"
38
39#if PX_WINDOWS
40#include "common/windows/PxWindowsDelayLoadHook.h"
41#include "windows/PsWindowsInclude.h"
42#include "windows/CmWindowsModuleUpdateLoader.h"
43#elif PX_LINUX
44#include <dlfcn.h>
45#endif // ~PX_LINUX
46
47namespace physx
48{
49 // alias shared foundation to something usable
50 namespace Ps = shdfnd;
51}
52
53#define STRINGIFY(x) #x
54#define GETSTRING(x) STRINGIFY(x)
55
56#define PHYSX_GPU_SHARED_LIB_NAME GETSTRING(PX_PHYSX_GPU_SHARED_LIB_NAME)
57static const char* gPhysXGpuLibraryName = PHYSX_GPU_SHARED_LIB_NAME;
58
59#undef GETSTRING
60#undef STRINGIFY
61
62void PxSetPhysXGpuLoadHook(const PxGpuLoadHook* hook)
63{
64 gPhysXGpuLibraryName = hook->getPhysXGpuDllName();
65}
66
67namespace grid
68{
69 class Server;
70 class ClientContextPredictionManager;
71}
72
73namespace physx
74{
75#if PX_VC
76#pragma warning(disable: 4191) //'operator/operation' : unsafe conversion from 'type of expression' to 'type required'
77#endif
78
79 class PxFoundation;
80 class PxPhysXGpu;
81
82 typedef physx::PxPhysXGpu* (PxCreatePhysXGpu_FUNC)();
83 typedef physx::PxCudaContextManager* (PxCreateCudaContextManager_FUNC)(physx::PxFoundation& foundation, const physx::PxCudaContextManagerDesc& desc, physx::PxProfilerCallback* profilerCallback);
84 typedef int (PxGetSuggestedCudaDeviceOrdinal_FUNC)(physx::PxErrorCallback& errc);
85 typedef grid::ClientContextPredictionManager* (PxCreateClientContextManager_FUNC)(grid::Server* server, physx::PxU32 maxNbSleepMsg);
86
87 PxCreatePhysXGpu_FUNC* g_PxCreatePhysXGpu_Func = NULL;
88 PxCreateCudaContextManager_FUNC* g_PxCreateCudaContextManager_Func = NULL;
89 PxGetSuggestedCudaDeviceOrdinal_FUNC* g_PxGetSuggestedCudaDeviceOrdinal_Func = NULL;
90
91 PxCreateClientContextManager_FUNC* g_CreateClientContextManager_Func = NULL;
92
93#if PX_WINDOWS
94
95 typedef void (PxSetPhysXGpuDelayLoadHook_FUNC)(const PxDelayLoadHook* delayLoadHook);
96
97#define DEFAULT_PHYSX_GPU_GUID "D79FA4BF-177C-4841-8091-4375D311D6A3"
98
99 void PxLoadPhysxGPUModule(const char* appGUID)
100 {
101 static HMODULE s_library;
102
103 if (s_library == NULL)
104 s_library = GetModuleHandle(gPhysXGpuLibraryName);
105
106 if (s_library == NULL)
107 {
108 Cm::CmModuleUpdateLoader moduleLoader(UPDATE_LOADER_DLL_NAME);
109 s_library = moduleLoader.LoadModule(gPhysXGpuLibraryName, appGUID == NULL ? DEFAULT_PHYSX_GPU_GUID : appGUID);
110 }
111
112 if (s_library)
113 {
114 g_PxCreatePhysXGpu_Func = (PxCreatePhysXGpu_FUNC*)GetProcAddress(s_library, "PxCreatePhysXGpu");
115 g_PxCreateCudaContextManager_Func = (PxCreateCudaContextManager_FUNC*)GetProcAddress(s_library, "PxCreateCudaContextManager");
116 g_PxGetSuggestedCudaDeviceOrdinal_Func = (PxGetSuggestedCudaDeviceOrdinal_FUNC*)GetProcAddress(s_library, "PxGetSuggestedCudaDeviceOrdinal");
117 g_CreateClientContextManager_Func = (PxCreateClientContextManager_FUNC*)GetProcAddress(s_library, "PxCreateCudaClientContextManager");
118 }
119
120 // Check for errors
121 if (s_library == NULL)
122 {
123 Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, "Failed to load PhysXGpu dll!");
124 return;
125 }
126
127 if (g_PxCreatePhysXGpu_Func == NULL || g_PxCreateCudaContextManager_Func == NULL || g_PxGetSuggestedCudaDeviceOrdinal_Func == NULL)
128 {
129 Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, "PhysXGpu dll is incompatible with this version of PhysX!");
130 return;
131 }
132 }
133
134#elif PX_LINUX
135
136 void PxLoadPhysxGPUModule(const char*)
137 {
138 static void* s_library;
139
140 if (s_library == NULL)
141 {
142 // load libcuda.so here since gcc configured with --as-needed won't link to it
143 // if there is no call from the binary to it.
144 void* hLibCuda = dlopen(file: "libcuda.so", RTLD_NOW | RTLD_GLOBAL);
145 if (hLibCuda)
146 {
147 s_library = dlopen(file: gPhysXGpuLibraryName, RTLD_NOW);
148 }
149 else
150 {
151 Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, messageFmt: "libcuda.so!");
152 return;
153 }
154 }
155
156 // no UpdateLoader
157 if (s_library)
158 {
159 *reinterpret_cast<void**>(&g_PxCreatePhysXGpu_Func) = dlsym(handle: s_library, name: "PxCreatePhysXGpu");
160 *reinterpret_cast<void**>(&g_PxCreateCudaContextManager_Func) = dlsym(handle: s_library, name: "PxCreateCudaContextManager");
161 *reinterpret_cast<void**>(&g_PxGetSuggestedCudaDeviceOrdinal_Func) = dlsym(handle: s_library, name: "PxGetSuggestedCudaDeviceOrdinal");
162 *reinterpret_cast<void**>(&g_CreateClientContextManager_Func ) = dlsym(handle: s_library, name: "PxCreateCudaClientContextManager");
163 }
164
165 // Check for errors
166 if (s_library == NULL)
167 {
168 Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, messageFmt: "Failed to load %s.", gPhysXGpuLibraryName);
169 return;
170 }
171 if (g_PxCreatePhysXGpu_Func == NULL || g_PxCreateCudaContextManager_Func == NULL || g_PxGetSuggestedCudaDeviceOrdinal_Func == NULL)
172 {
173 Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, messageFmt: "%s is incompatible with this version of PhysX!", gPhysXGpuLibraryName);
174 return;
175 }
176 }
177
178#else
179 void PxLoadPhysxGPUModule(const char*)
180 {
181 Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, "GPU module disabled");
182 }
183#endif // PX_LINUX
184
185} // end physx namespace
186
187#endif // PX_SUPPORT_GPU_PHYSX
188

source code of qtquick3dphysics/src/3rdparty/PhysX/source/physx/src/gpu/PxPhysXGpuModuleLoader.cpp