Thank you, that works!
Let me write some details of the solution in case anyone else needs it.
I’m using GLEW for entry points and GLFW3 for window management.
GLEW
GLEW uses glXGetProcAddress(), so no problem here.
It loads entry points in glewInit()
, which is implemented like this:
GLboolean r = GL_FALSE;
r = ((glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindFramebuffer")) == NULL) || r;
r = ((glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBindRenderbuffer")) == NULL) || r;
r = ((glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)glewGetProcAddress((const GLubyte*)"glBlitFramebuffer")) == NULL) || r;
r = ((glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)glewGetProcAddress((const GLubyte*)"glCheckFramebufferStatus")) == NULL) || r;
.....
where glewGetProcAddress
is
#else /* __linux */
# define glewGetProcAddress(name) (*glXGetProcAddressARB)(name)
#endif
where glXGetProcAddressARB
is defined as follows:
extern void ( * glXGetProcAddressARB (const GLubyte *procName)) (void);
and is taken from libGLX.
GLFW
GLFW3 under all abstraction layers loads glXSwapBuffers
with dlsym, which hides it from the debugger. First, let’s expose native intrinsics of GLFW:
#ifdef __linux__
#define GLFW_EXPOSE_NATIVE_X11
#define GLFW_EXPOSE_NATIVE_GLX
#include <GLFW/glfw3native.h>
#include <GL/glx.h>
#endif
then replace glfwSwapBuffers(window)
with
#ifdef __linux__
glXSwapBuffers(glfwGetX11Display(), glfwGetGLXWindow(window));
#else
glfwSwapBuffers(window);
#endif
Launch
When launching OpenGL app it’s important to use libNomad.Injection.so
instead of libNvda.Graphics.Interception.so
.
Final command line for my app is this:
LD_PRELOAD=/path/to/nvidia/NVIDIA-Nsight-Graphics-2021.4/target/linux-desktop-nomad-x64/libNomad.Injection.so NV_TPS_LAUNCH_TOKEN="Frame Debugger" ./start_demo
Now I’m happy to see my app’s frame from the inside again!