adding visible gpu devices: 0是什么意思_GPU 服务端构建openGL context 上下文基本流程

问题背景:

       最近因为项目开发需要,需要在服务端构建OpenGL渲染环境,但由于缺乏服务端开发经验,我们遇到了一些相对棘手的问题,如何在服务端构建稳定可行的OpenGL context上下文环境便是其中一个较为棘手的一个,由于服务端环境相较于客户端环境相对复杂,因为在服务端没有用于画面渲染的显示设备,而OpenGL Context 上下文环境的构建又强依赖于display。所以为了解决这个问题我们前后实验了多种方案,包括在我们的服务器环境下安装虚拟显示设备、安装X window等方案但均无法正常构建OpenGL Context上下文环境。为此我们经过查阅相关资料最终采取了英伟达(NVIDIA)的技术方案。在GPU服务器上安装英伟达的显卡,在构建OpenGL context上下文环境时使用外接Display构建OpenGL环境的方法。具体流程如下:

     下面我们先看一下在正常存在display设备环境下如何创建OpenGL contxt

#include   static const EGLint configAttribs[] = {          EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,          EGL_BLUE_SIZE, 8,          EGL_GREEN_SIZE, 8,          EGL_RED_SIZE, 8,          EGL_DEPTH_SIZE, 8,          EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,          EGL_NONE  };      static const int pbufferWidth = 9;  static const int pbufferHeight = 9;  static const EGLint pbufferAttribs[] = {        EGL_WIDTH, pbufferWidth,        EGL_HEIGHT, pbufferHeight,        EGL_NONE,  };int main(int argc, char *argv[]){  // 1. Initialize EGL  EGLDisplay eglDpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);  EGLint major, minor;  eglInitialize(eglDpy, &major, &minor);  // 2. Select an appropriate configuration  EGLint numConfigs;  EGLConfig eglCfg;  eglChooseConfig(eglDpy, configAttribs, &eglCfg, 1, &numConfigs);  // 3. Create a surface  EGLSurface eglSurf = eglCreatePbufferSurface(eglDpy, eglCfg,                                                pbufferAttribs);  // 4. Bind the API  eglBindAPI(EGL_OPENGL_API);  // 5. Create a context and make it current  EGLContext eglCtx = eglCreateContext(eglDpy, eglCfg, EGL_NO_CONTEXT,                                        NULL);  eglMakeCurrent(eglDpy, eglSurf, eglSurf, eglCtx);  // from now on use your OpenGL context  // 6. Terminate EGL when finished  eglTerminate(eglDpy);  return 0;}

        我们先简单看一下在EGL环境下创建OpenGL conext的具体步骤,第一步是获取一个显示对象(eglGetDisplay),在上述代码中是获取默认显示设备,display可以(但非必须)是附加于系统上的物理显示设备。接下来我们需要在display上初始化EGL。除了初始化EGL之外,这个函数还会返回这个特定的display所支持的EGL版本,如果应用程序依赖于特定的EGL版本这将非常方便。一个display设备可以支持一系列的配置,因此我们需要指定应用程序中需要使用的配置。在我们的应用示例中,对于我们的配置需要一系列的属性配置,比如8-bits位深的颜色通道以及生成一个离屏渲染buffer的能力或者生成一个特定尺寸的surface。然后EGL能够返回一组能够匹配这些要求的配置。

       现在我们开始创建一个surface,什么是surface呢?粗略的说一个surface就代表了屏幕上的一个窗口,只是你不需要屏幕。所以呢这是一个有限大小的画布。除了实际的像素数据,surface还可以包含辅助缓冲区,比如模版或者深度缓冲区。这里我们仅仅创建一个被称之为pbuffer(eglCreatePBufferSurface())用于离屏渲染的EGL Surface。

现在基本所有的工作准备就绪,唯一需要的就是我们需要告诉EGL我们想要用什么API来渲染这个surface。在这个示例中,我们选择了标准的OpenGL(eglBindAPI()),另一种选择是使用OpenGL es。此时我们可以在这个surface上创建OpenGL context(eglCreateContext()),并切换到当前环境(eglMakeCurrent())以便于进行相关openGL操作。

   上面的示例是我们通过eglGetDisplay()去获取一个默认的display目标,但是如果我们系统中有多个gpu,并且我们希望使用一个特定的gpu(可能不是通过X server进行管理)进行渲染任务那该怎么办呢?又或者我们希望在工作站上基于一个不是由X server管理的display设备创建离屏的context和buffer又该怎么做呢?

  EGL提供了另外一种更加强大的获取display设备的机制eglGetPlatformDisplay(),它允许我们指定确切的display设备,因此我们可以在多GPU配置中配置工作的GPU。

下面是通过eglGetPlatformDisplay()获取display的示例代码。

#define EGL_EGLEXT_PROTOTYPES#include #include main(){  static const int MAX_DEVICES = 4;  EGLDeviceEXT eglDevs[MAX_DEVICES];  EGLint numDevices;  PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT =    (PFNEGLQUERYDEVICESEXTPROC)    eglGetProcAddress("eglQueryDevicesEXT");  eglQueryDevicesEXT(MAX_DEVICES, eglDevs, &numDevices);  printf(“Detected %d devices\n”, numDevices);  PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT =    (PFNEGLGETPLATFORMDISPLAYEXTPROC)    eglGetProcAddress("eglGetPlatformDisplayEXT");  eglDpy = eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT,                                     eglDevs[0], 0);  // ...}

       这个示例首先通过eglQueryDevicesEXT()查询可用的EGL设备,与所有的EGL创建例程一样,eglQueryDevicesEXT填充一个设备数组并返回找到的设备数量。注意eglQueryDevicesEXT()是一个EGL扩展,对应的EGL可能支持也可能不支持,所以你需要引入对应EGL扩展的头文件,并且通过设置EGL_EXT_PROTOTYPES预处理宏lai启用对应的扩展。为了得到想要的扩展函数,我们必须通过eglGetProcAddress()来获得对应的函数指针,它可以通过传入函数名称作为型参并最终返回函数指针。这里为了清晰起见,这里省略了所有的错误检查,但是为了代码的质量我们还是需要处理eglGetProcAddress()返回为NULL的情况。

   在获得一系列的有效设备后,我们可以选择一个合适的设备作为我们的目标设备。另外一个扩展函数eglGetPlatformDisplayEXT()可以允许我们使用我们选择的设备作为EGL的display设备。其他后续的创建OpenGL context的步骤与我们第一的示例的后续步骤一致。

如果想详细研究可以参考NVIDIA的官方文档:https://devblogs.nvidia.com/egl-eye-opengl-visualization-without-x-server/

具体实现代码请参考:https://github.com/multimedia-advanced-org/CreateGLContextNoDisplay

fae25ca8f6092c6565872cfa41269044.png

  ab4b3a8221d9b50f454601218f74dbc3.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值