22
33#include " nbl/video/IPhysicalDevice.h"
44#include " nbl/video/utilities/renderdoc.h"
5- #include " nbl/video/utilities/ngfx.h"
65
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
911
1012#if defined(_NBL_POSIX_API_)
1113 #include < dlfcn.h>
1416namespace nbl ::video
1517{
1618
17-
1819std::span<IPhysicalDevice* const > IAPIConnection::getPhysicalDevices () const
1920{
2021 static_assert (sizeof (std::unique_ptr<IPhysicalDevice>) == sizeof (void *));
@@ -59,70 +60,134 @@ IAPIConnection::IAPIConnection(const SFeatures& enabledFeatures)
5960
6061bool IAPIConnection::SNGFXIntegration::injectNGFXToProcess ()
6162{
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!
6565 {
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+ }
6973
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+ }
7781
78- // get latest installation
79- NGFX_Injection_InstallationInfo versionInfo = installations.back ();
82+ // get latest installation
83+ NGFX_Injection_InstallationInfo versionInfo = installations.back ();
8084
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+ }
8892
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+ }
96100
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)
101103 {
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+ }
104109 }
105- }
106110
107- if (!pActivityToInject) {
108- useNGFX = false ;
109- return false ;
110- }
111+ if (!pActivityToInject) {
112+ useNGFX = false ;
113+ return false ;
114+ }
111115
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
118128
119- useNGFX = true ;
120- return true ;
129+ return false ;
121130}
122131
123132bool IAPIConnection::SNGFXIntegration::executeNGFXCommand ()
124133{
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 ;
126140}
127141
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+
128193}
0 commit comments