2
2
3
3
#include " nbl/video/IPhysicalDevice.h"
4
4
#include " nbl/video/utilities/renderdoc.h"
5
- #include " nbl/video/utilities/ngfx.h"
6
5
7
- // TODO: temporary hopefully
8
- #include " C:\Program Files\NVIDIA Corporation\Nsight Graphics 2024.1.0\SDKs\NsightGraphicsSDK\0.8.0\include\NGFX_Injection.h"
6
+ #include " nbl/system/CSystemWin32.h"
7
+
8
+ #ifdef NBL_BUILD_WITH_NGFX
9
+ #include " NGFX_Injection.h"
10
+ #endif
9
11
10
12
#if defined(_NBL_POSIX_API_)
11
13
#include < dlfcn.h>
14
16
namespace nbl ::video
15
17
{
16
18
17
-
18
19
std::span<IPhysicalDevice* const > IAPIConnection::getPhysicalDevices () const
19
20
{
20
21
static_assert (sizeof (std::unique_ptr<IPhysicalDevice>) == sizeof (void *));
@@ -59,70 +60,134 @@ IAPIConnection::IAPIConnection(const SFeatures& enabledFeatures)
59
60
60
61
bool IAPIConnection::SNGFXIntegration::injectNGFXToProcess ()
61
62
{
62
- uint32_t numInstallations = 0 ;
63
- auto result = NGFX_Injection_EnumerateInstallations (&numInstallations, nullptr );
64
- if (numInstallations == 0 || NGFX_INJECTION_RESULT_OK != result)
63
+ #ifdef NBL_BUILD_WITH_NGFX
64
+ if (m_loaded) // ! this check is mandatory!
65
65
{
66
- useNGFX = false ;
67
- return false ;
68
- }
66
+ uint32_t numInstallations = 0 ;
67
+ auto result = NGFX_Injection_EnumerateInstallations (&numInstallations, nullptr );
68
+ if (numInstallations == 0 || NGFX_INJECTION_RESULT_OK != result)
69
+ {
70
+ useNGFX = false ;
71
+ return false ;
72
+ }
69
73
70
- std::vector<NGFX_Injection_InstallationInfo> installations (numInstallations);
71
- result = NGFX_Injection_EnumerateInstallations (&numInstallations, installations.data ());
72
- if (numInstallations == 0 || NGFX_INJECTION_RESULT_OK != result)
73
- {
74
- useNGFX = false ;
75
- return false ;
76
- }
74
+ std::vector<NGFX_Injection_InstallationInfo> installations (numInstallations);
75
+ result = NGFX_Injection_EnumerateInstallations (&numInstallations, installations.data ());
76
+ if (numInstallations == 0 || NGFX_INJECTION_RESULT_OK != result)
77
+ {
78
+ useNGFX = false ;
79
+ return false ;
80
+ }
77
81
78
- // get latest installation
79
- NGFX_Injection_InstallationInfo versionInfo = installations.back ();
82
+ // get latest installation
83
+ NGFX_Injection_InstallationInfo versionInfo = installations.back ();
80
84
81
- uint32_t numActivities = 0 ;
82
- result = NGFX_Injection_EnumerateActivities (&versionInfo, &numActivities, nullptr );
83
- if (numActivities == 0 || NGFX_INJECTION_RESULT_OK != result)
84
- {
85
- useNGFX = false ;
86
- return false ;
87
- }
85
+ uint32_t numActivities = 0 ;
86
+ result = NGFX_Injection_EnumerateActivities (&versionInfo, &numActivities, nullptr );
87
+ if (numActivities == 0 || NGFX_INJECTION_RESULT_OK != result)
88
+ {
89
+ useNGFX = false ;
90
+ return false ;
91
+ }
88
92
89
- std::vector<NGFX_Injection_Activity> activities (numActivities);
90
- result = NGFX_Injection_EnumerateActivities (&versionInfo, &numActivities, activities.data ());
91
- if (NGFX_INJECTION_RESULT_OK != result)
92
- {
93
- useNGFX = false ;
94
- return false ;
95
- }
93
+ std::vector<NGFX_Injection_Activity> activities (numActivities);
94
+ result = NGFX_Injection_EnumerateActivities (&versionInfo, &numActivities, activities.data ());
95
+ if (NGFX_INJECTION_RESULT_OK != result)
96
+ {
97
+ useNGFX = false ;
98
+ return false ;
99
+ }
96
100
97
- const NGFX_Injection_Activity* pActivityToInject = nullptr ;
98
- for (const NGFX_Injection_Activity& activity : activities)
99
- {
100
- if (activity.type == NGFX_INJECTION_ACTIVITY_FRAME_DEBUGGER) // only want frame debugger
101
+ const NGFX_Injection_Activity* pActivityToInject = nullptr ;
102
+ for (const NGFX_Injection_Activity& activity : activities)
101
103
{
102
- pActivityToInject = &activity;
103
- break ;
104
+ if (activity.type == NGFX_INJECTION_ACTIVITY_FRAME_DEBUGGER) // only want frame debugger
105
+ {
106
+ pActivityToInject = &activity;
107
+ break ;
108
+ }
104
109
}
105
- }
106
110
107
- if (!pActivityToInject) {
108
- useNGFX = false ;
109
- return false ;
110
- }
111
+ if (!pActivityToInject) {
112
+ useNGFX = false ;
113
+ return false ;
114
+ }
111
115
112
- result = NGFX_Injection_InjectToProcess (&versionInfo, pActivityToInject);
113
- if (NGFX_INJECTION_RESULT_OK != result)
114
- {
115
- useNGFX = false ;
116
- return false ;
117
- }
116
+ result = NGFX_Injection_InjectToProcess (&versionInfo, pActivityToInject);
117
+ if (NGFX_INJECTION_RESULT_OK != result)
118
+ {
119
+ useNGFX = false ;
120
+ return false ;
121
+ }
122
+
123
+ useNGFX = true ;
124
+
125
+ return true ;
126
+ } // optional TOOD: could log on "else"
127
+ #endif // NBL_BUILD_WITH_NGFX
118
128
119
- useNGFX = true ;
120
- return true ;
129
+ return false ;
121
130
}
122
131
123
132
bool IAPIConnection::SNGFXIntegration::executeNGFXCommand ()
124
133
{
125
- return NGFX_Injection_ExecuteActivityCommand () == NGFX_INJECTION_RESULT_OK;
134
+ #ifdef NBL_BUILD_WITH_NGFX
135
+ if (m_loaded) // ! this check is mandatory!
136
+ return NGFX_Injection_ExecuteActivityCommand () == NGFX_INJECTION_RESULT_OK; // optional TOOD: could log on "else"
137
+ #endif // NBL_BUILD_WITH_NGFX
138
+
139
+ return false ;
126
140
}
127
141
142
+ IAPIConnection::SNGFXIntegration::SNGFXIntegration ()
143
+ : useNGFX(false /* ??*/ ), m_loaded([]() -> bool
144
+ {
145
+ #ifdef NBL_BUILD_WITH_NGFX
146
+ // ! absolute path to official install NGFX SDK runtime directory
147
+ auto getOfficialRuntimeDirectory = []()
148
+ {
149
+ const char * sdk = std::getenv (" NGFX_SDK" );
150
+ const char * version = std::getenv (" NGFX_VERSION" );
151
+ const bool composed = sdk && version;
152
+
153
+ if (composed)
154
+ {
155
+ const auto directory = system::path (sdk) / system::path (version) / " lib" / " x64" ;
156
+
157
+ if (std::filesystem::exists (directory))
158
+ return directory;
159
+ }
160
+
161
+ return system::path (" " );
162
+ };
163
+
164
+ // ! batch request with priority order & custom Nabla runtime search, I'm assuming we are loading the runtime from official SDK not custom location
165
+ // ! one question is if we should have any constraints for min/max version, maybe force the "version"
166
+ // ! to match the "NGFX_VERSION" define so to "what we built with", or don't have any - just like now
167
+
168
+ #if defined(_NBL_PLATFORM_WINDOWS_)
169
+ static constexpr std::string_view NGFXMODULE = " NGFX_Injection.dll" ;
170
+ HMODULE isAlreadyLoaded = GetModuleHandleA (NGFXMODULE.data ());
171
+
172
+ if (!isAlreadyLoaded)
173
+ {
174
+ const auto dll = getOfficialRuntimeDirectory () / NGFXMODULE.data ();
175
+ const HRESULT hook = system::CSystemWin32::delayLoadDLL (NGFXMODULE.data (), { NGFX_INJECTION_DLL_DIR, dll.parent_path () });
176
+
177
+ // ! don't be scared if you see "No symbols loaded" - you will not hit "false" in this case, the DLL will get loaded if found,
178
+ // ! proc addresses will be resolved correctly but status will scream "FAILED" because we don't have any PDB to load
179
+ if (FAILED (hook))
180
+ return false ;
181
+ }
182
+ #else
183
+ #error "TODO!"
184
+ #endif
185
+
186
+ return true ;
187
+ #else
188
+ return false ; // no NGFX build -> no API to load
189
+ #endif
190
+ }())
191
+ {}
192
+
128
193
}
0 commit comments