0

Trying to use INTEL_performance_query extension of OpenGL to get general metrics of the GPU usage. The problem is that for most operations, including listing extensions, it is needed a context which requires X-server, and some Display.

Unfortunately, I don't have any of them. (Pure SSH access to a server). However, I know an Intel real graphic card is installed and configured.

main.cpp

#include <cassert>
#include <exception>
#include <iostream>
#include <unordered_set>

#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glx.h>


void uselessSetup()
{
    using glXCreateContextAttribsARBProc = GLXContext (*)(Display*, GLXFBConfig, GLXContext, bool, const int*);
    using glXMakeContextCurrentARBProc = bool (*)(Display*, GLXDrawable, GLXDrawable, GLXContext);
    static glXCreateContextAttribsARBProc glXCreateContextAttribsARB = nullptr;
    static glXMakeContextCurrentARBProc   glXMakeContextCurrentARB   = nullptr;
    glXCreateContextAttribsARB = reinterpret_cast<glXCreateContextAttribsARBProc>(glXGetProcAddressARB( reinterpret_cast<const GLubyte *>("glXCreateContextAttribsARB")));
    glXMakeContextCurrentARB   = reinterpret_cast<glXMakeContextCurrentARBProc>(glXGetProcAddressARB( reinterpret_cast<const GLubyte *>("glXMakeContextCurrent")));
    
    Display* display = XOpenDisplay( nullptr );

    static int visualAttribs[] = { None };
    int numberOfFramebufferConfigurations = 0;
    GLXFBConfig* fbConfigs = glXChooseFBConfig( display, DefaultScreen(display), visualAttribs, &numberOfFramebufferConfigurations );

    int context_attribs[] =
    {
        GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
        GLX_CONTEXT_MINOR_VERSION_ARB, 2,
        GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB,
        GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
        None
    };

    GLXContext openGLContext = glXCreateContextAttribsARB( nullptr, nullptr, 0, true, context_attribs);

    int pbufferAttribs[] =
    {
        GLX_PBUFFER_WIDTH,  32,
        GLX_PBUFFER_HEIGHT, 32,
        None
    };

    GLXPbuffer pbuffer = glXCreatePbuffer( display, fbConfigs[0], pbufferAttribs );

    // clean up:
    XFree( fbConfigs );
    XSync( display, false );

    if ( !glXMakeContextCurrentARB( display, pbuffer, pbuffer, openGLContext ) )
    {
        std::string_view msg = "Error: could not create headless context.";
        std::cerr << msg << std::endl;
        assert(false);
        throw std::runtime_error(msg.data());
    }

    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        std::string msg = std::string{"Error: "} + reinterpret_cast<const char*>(glewGetErrorString(err));
        std::cerr << msg << std::endl;
        assert(false);
        throw std::runtime_error(msg);
    }
}

std::unordered_set<std::string> supportedExtensions()
{
    std::unordered_set<std::string> ret;

    GLint n=0;
    glGetIntegerv(GL_NUM_EXTENSIONS, &n);
    std::cout << "There are: " << n << " extensions" << std::endl;
    for (GLint i=0; i<n; i++)
    {
        const std::string extension = reinterpret_cast<const char*>(glGetStringi(GL_EXTENSIONS, i));
        ret.insert(extension);

    }
    return ret;
}


int main(int, char**)
{
    // I CANT DO THIS!!!
    //uselessSetup();

    std::cout << "OpenGL version: " << reinterpret_cast<const char*>(glGetString(GL_VERSION)) << std::endl;
    std::cout << "Vendor        : " << reinterpret_cast<const char*>(glGetString(GL_VENDOR))  << std::endl;
    std::cout << "Renderer      : " << reinterpret_cast<const char*>(glGetString(GL_RENDERER))  << std::endl;

    const auto extensions = supportedExtensions();

    std::cout << "Supported extensions:" << std::endl;
    for (const auto& ext: extensions)
    {
        std::cout << "    " << ext << std::endl;
    }

    if ( extensions.find("INTEL_performance_query")!=extensions.cend())
    {
        std::cerr << "INTEL_performance_query not supported" << std::endl;
    }

    return 0;
}

CMake:

cmake_minimum_required(VERSION 3.13)
cmake_policy( SET CMP0076 NEW )

project("GPU_profiler")

set(TARGET "GPU_profiler")
add_executable(${TARGET})

target_compile_options( ${TARGET} PRIVATE -Wall -pedantic -Wno-padded)
target_compile_features( ${TARGET} PUBLIC cxx_std_17)

find_package(GLEW REQUIRED)
include_directories(${GLEW_INCLUDE_DIRS})

#Build this project
set ( SOURCES main.cpp)
set ( HEADERS "")
set ( LIBS
    ${GLEW_LIBRARIES}
    GL
    GLX
    X11
)

target_sources( ${TARGET} PRIVATE ${SOURCES} PRIVATE ${HEADERS})
target_link_libraries(${TARGET} ${LIBS})

How can I get access to those graphic card values and extensions (which should not require a drawing context)?


Related:

Using OpenGL Without X-Window System Mesa driver is not a solution.

http://renderingpipeline.com/2012/05/windowless-opengl/ This works only when an X-server is available. It's actually the solution shown above as "uselessSetup"

OpenGL without X.org in linux I Could create a context, but out of the 2 available devices, the first returns "Not allowed to force software rendering when API explicitly selects a hardware device". While the second is a virtual mesa driver (without access to real OpenGL hardware).

genpfault
  • 51,148
  • 11
  • 85
  • 139
Adrian Maire
  • 14,354
  • 9
  • 45
  • 85
  • "*which should not require a drawing context*" Why do you believe that this is the case? – Nicol Bolas Sep 28 '21 at 15:34
  • you could try running an X server – user253751 Sep 28 '21 at 15:38
  • @NicolBolas: Might be that this is a too vague sentence. The point is, it needs to work without X-server, GUI, desktop, or window. Just plain console root(or user) session. It might also be that what I try to achieve is not possible with OpenGL extensions and I should look for intel performance-metrics lib. – Adrian Maire Sep 28 '21 at 16:48
  • @user253751: While this would certainly solve (and it actually does) the problem. I can only install an x-server on my own machine, and not on all the machines of future users of my program. – Adrian Maire Sep 28 '21 at 16:49
  • Compile a modern [`eglinfo`](https://gitlab.freedesktop.org/mesa/demos/-/blob/main/src/egl/opengl/eglinfo.c) and run it to see if the machine supports `EGL_MESA_platform_surfaceless`. [`EGL_MESA_platform_gbm`/`EGL_KHR_platform_gbm`](https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_platform_gbm.txt) might also work but would require more moving parts (read: faffing about with GBM to get a native surface) to spin up a GL context. – genpfault Sep 28 '21 at 17:31

0 Answers0