Skip to content

Commit 2b3bdaa

Browse files
author
devsh
committed
Detect Nsight launching the app through an envvar, attempt to post-inject
1 parent 12bbe91 commit 2b3bdaa

File tree

4 files changed

+73
-66
lines changed

4 files changed

+73
-66
lines changed

include/nbl/video/IAPIConnection.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,20 +74,22 @@ class NBL_API2 IAPIConnection : public core::IReferenceCounted
7474
virtual bool endCapture() = 0;
7575

7676
protected:
77-
IAPIConnection(const SFeatures& enabledFeatures);
78-
79-
bool loadRenderdoc();
77+
static void loadDebuggers();
8078

81-
bool loadNGFX() const;
79+
IAPIConnection(const SFeatures& enabledFeatures);
8280
void executeNGFXCommand();
8381

84-
8582
std::vector<std::unique_ptr<IPhysicalDevice>> m_physicalDevices;
86-
8783
SFeatures m_enabledFeatures = {};
8884

89-
EDebuggerType m_debugger = EDebuggerType::None;
90-
renderdoc_api_t* m_rdoc_api = nullptr;
85+
static inline renderdoc_api_t* m_rdoc_api = nullptr;
86+
87+
private:
88+
static inline EDebuggerType m_debugger = EDebuggerType::None;
89+
90+
static bool loadNGFX();
91+
static bool loadRenderdoc();
92+
9193
};
9294

9395
}

src/nbl/video/CVulkanConnection.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ core::smart_refctd_ptr<CVulkanConnection> CVulkanConnection::create(core::smart_
299299
api->m_physicalDevices.reserve(vk_physicalDevices.size());
300300
for (auto vk_physicalDevice : vk_physicalDevices)
301301
{
302-
auto device = CVulkanPhysicalDevice::create(core::smart_refctd_ptr(sys),api.get(),api->m_rdoc_api,vk_physicalDevice);
302+
auto device = CVulkanPhysicalDevice::create(core::smart_refctd_ptr(sys),api.get(),IAPIConnection::m_rdoc_api,vk_physicalDevice);
303303
if (!device)
304304
{
305305
LOG(api->getDebugCallback()->getLogger(), "Vulkan device %p found but doesn't meet minimum Nabla requirements. Skipping!", system::ILogger::ELL_WARNING, vk_physicalDevice);

src/nbl/video/IAPIConnection.cpp

Lines changed: 61 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,27 @@
1616
namespace nbl::video
1717
{
1818

19-
std::span<IPhysicalDevice* const> IAPIConnection::getPhysicalDevices() const
19+
void IAPIConnection::loadDebuggers()
2020
{
21-
static_assert(sizeof(std::unique_ptr<IPhysicalDevice>) == sizeof(void*));
21+
// there's a debugger already attached to the process
22+
if (m_debugger!=EDebuggerType::None)
23+
return;
2224

23-
IPhysicalDevice* const* const begin = reinterpret_cast<IPhysicalDevice* const*>(m_physicalDevices.data());
24-
return {begin,m_physicalDevices.size()};
25+
// NGFX takes precedence, but don't want to use NGFX SDK unless NSight launched our application.
26+
// Otherwise we end up starting random NSight GUI instances if only the NGFX DLL is found (interferes with Renderdoccing)
27+
if (std::getenv("NVTX_INJECTION64_PATH"))
28+
{
29+
if (loadNGFX())
30+
m_debugger = EDebuggerType::NSight;
31+
return;
32+
}
33+
34+
// now load renderdoc
35+
if (loadRenderdoc())
36+
m_debugger = EDebuggerType::Renderdoc;
2537
}
2638

27-
bool IAPIConnection::loadNGFX() const
39+
bool IAPIConnection::loadNGFX()
2840
{
2941
#ifdef NBL_BUILD_WITH_NGFX
3042
//! absolute path to official install NGFX SDK runtime directory
@@ -67,47 +79,42 @@ bool IAPIConnection::loadNGFX() const
6779
#error "TODO!"
6880
#endif
6981

82+
if (isAlreadyLoaded)
83+
return true;
84+
7085
// now call the APIs for the first time
71-
if (!isAlreadyLoaded)
86+
uint32_t numInstallations = 0;
87+
auto result = NGFX_Injection_EnumerateInstallations(&numInstallations, nullptr);
88+
if (numInstallations==0 || NGFX_INJECTION_RESULT_OK!=result)
89+
return false;
90+
91+
std::vector<NGFX_Injection_InstallationInfo> installations(numInstallations);
92+
result = NGFX_Injection_EnumerateInstallations(&numInstallations,installations.data());
93+
if (NGFX_INJECTION_RESULT_OK!=result)
94+
return false;
95+
assert(installations.size()==numInstallations);
96+
97+
// get latest installation
98+
const NGFX_Injection_InstallationInfo& versionInfo = installations.back();
99+
100+
uint32_t numActivities = 0;
101+
result = NGFX_Injection_EnumerateActivities(&versionInfo, &numActivities, nullptr);
102+
if (numActivities==0 || NGFX_INJECTION_RESULT_OK!=result)
103+
return false;
104+
105+
std::vector<NGFX_Injection_Activity> activities(numActivities);
106+
result = NGFX_Injection_EnumerateActivities(&versionInfo, &numActivities, activities.data());
107+
if (NGFX_INJECTION_RESULT_OK != result)
108+
return false;
109+
assert(activities.size()==numActivities);
110+
111+
for (const auto& activity : activities)
112+
if (activity.type==NGFX_INJECTION_ACTIVITY_FRAME_DEBUGGER)
72113
{
73-
uint32_t numInstallations = 0;
74-
auto result = NGFX_Injection_EnumerateInstallations(&numInstallations, nullptr);
75-
if (numInstallations==0 || NGFX_INJECTION_RESULT_OK!=result)
76-
return false;
77-
78-
std::vector<NGFX_Injection_InstallationInfo> installations(numInstallations);
79-
result = NGFX_Injection_EnumerateInstallations(&numInstallations,installations.data());
80-
if (NGFX_INJECTION_RESULT_OK!=result)
81-
return false;
82-
assert(installations.size()==numInstallations);
83-
84-
// get latest installation
85-
const NGFX_Injection_InstallationInfo& versionInfo = installations.back();
86-
87-
uint32_t numActivities = 0;
88-
result = NGFX_Injection_EnumerateActivities(&versionInfo, &numActivities, nullptr);
89-
if (numActivities==0 || NGFX_INJECTION_RESULT_OK!=result)
90-
return false;
91-
92-
std::vector<NGFX_Injection_Activity> activities(numActivities);
93-
result = NGFX_Injection_EnumerateActivities(&versionInfo, &numActivities, activities.data());
94-
if (NGFX_INJECTION_RESULT_OK != result)
95-
return false;
96-
assert(activities.size()==numActivities);
97-
98-
// only want frame debugger
99-
const auto itActivityToInject = std::find_if(activities.begin(),activities.end(),[](const NGFX_Injection_Activity& activity)->bool{
100-
return activity.type==NGFX_INJECTION_ACTIVITY_FRAME_DEBUGGER;
101-
});
102-
if (itActivityToInject==activities.end())
103-
return false;
104-
105-
result = NGFX_Injection_InjectToProcess(&versionInfo,&(*itActivityToInject));
106-
if (NGFX_INJECTION_RESULT_OK!=result)
107-
return false;
114+
result = NGFX_Injection_InjectToProcess(&versionInfo,&activity);
115+
if (result==NGFX_INJECTION_RESULT_DRIVER_STILL_LOADED)
116+
return true;
108117
}
109-
110-
return true;
111118
#endif
112119
// no NGFX build -> no API to load
113120
return false;
@@ -136,23 +143,21 @@ bool IAPIConnection::loadRenderdoc()
136143
return false;
137144
}
138145

139-
IAPIConnection::IAPIConnection(const SFeatures& enabledFeatures)
140-
: m_physicalDevices()
141-
, m_rdoc_api(nullptr)
142-
, m_enabledFeatures(enabledFeatures)
146+
IAPIConnection::IAPIConnection(const SFeatures& enabledFeatures) : m_physicalDevices(), m_enabledFeatures(enabledFeatures)
143147
{
144-
// NGFX takes precedence
145-
if (loadNGFX())
146-
m_debugger = EDebuggerType::NSight;
147-
if (isRunningInGraphicsDebugger())
148-
return;
149-
150-
// now load renderdoc
151-
if (loadRenderdoc())
152-
m_debugger = EDebuggerType::Renderdoc;
148+
loadDebuggers();
153149
}
154150

151+
std::span<IPhysicalDevice* const> IAPIConnection::getPhysicalDevices() const
152+
{
153+
static_assert(sizeof(std::unique_ptr<IPhysicalDevice>) == sizeof(void*));
154+
155+
IPhysicalDevice* const* const begin = reinterpret_cast<IPhysicalDevice* const*>(m_physicalDevices.data());
156+
return {begin,m_physicalDevices.size()};
157+
}
155158

159+
// Current NGFX SDK API is extremely dumb, this will literally pop up a new NSight window every frame.
160+
// It also still fails to capture anything happening off the Queue that's acquiring and presenting to the swapchain or before the very first acquire.
156161
void IAPIConnection::executeNGFXCommand()
157162
{
158163
assert(m_debugger==EDebuggerType::NSight);

0 commit comments

Comments
 (0)