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 | |
47 | namespace 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) |
57 | static const char* gPhysXGpuLibraryName = PHYSX_GPU_SHARED_LIB_NAME; |
58 | |
59 | #undef GETSTRING |
60 | #undef STRINGIFY |
61 | |
62 | void PxSetPhysXGpuLoadHook(const PxGpuLoadHook* hook) |
63 | { |
64 | gPhysXGpuLibraryName = hook->getPhysXGpuDllName(); |
65 | } |
66 | |
67 | namespace grid |
68 | { |
69 | class Server; |
70 | class ClientContextPredictionManager; |
71 | } |
72 | |
73 | namespace 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 | |