opengl 多线程渲染中的问题

eglMakeCurrent详解
本文详细介绍了EGL API中的eglMakeCurrent函数,该函数用于将渲染上下文绑定到绘图和读取表面。文章深入探讨了函数参数的意义及使用场景,并解释了如何确保正确配置上下文和表面。

Name

eglMakeCurrent — attach an EGL rendering context to EGL surfaces

把EGL的渲染上下文贴到EGL的表面上

C Specification

EGLBoolean eglMakeCurrent( EGLDisplay display,
  EGLSurface draw,
  EGLSurface read,
  EGLContext context);
 

Parameters

display

Specifies the EGL display connection.

draw

Specifies the EGL draw surface.

read

Specifies the EGL read surface.

context

Specifies the EGL rendering context to be attached to the surfaces.

Description

eglMakeCurrent binds context to the current rendering thread and to the draw and read surfaces. draw is used for all GL operations except for any pixel data read back (glReadPixelsglCopyTexImage2D, and glCopyTexSubImage2D), which is taken from the frame buffer values of read.

If the calling thread has already a current rendering context, that context is flushed and marked as no longer current.

The first time that context is made current, the viewport and scissor dimensions are set to the size of the draw surface. The viewport and scissor are not modified whencontext is subsequently made current.

To release the current context without assigning a new one, call eglMakeCurrent with draw and read set to EGL_NO_SURFACE and context set to EGL_NO_CONTEXT.

Use eglGetCurrentContexteglGetCurrentDisplay, and eglGetCurrentSurface to query the current rendering context and associated display connection and surfaces.



首先 第一

在 eglMakeCurrent函数中,有下面这段检查,意思是说,要不然read draw buffer都为空,要不然就都不能为空。

eglapi.c

if (!draw_surf || !read_surf) {
      /* surfaces may be NULL if surfaceless */
      if (!disp->Extensions.KHR_surfaceless_context)
         RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);

      if ((!draw_surf && draw != EGL_NO_SURFACE) ||
          (!read_surf && read != EGL_NO_SURFACE))
         RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
      if (draw_surf || read_surf)
         RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
   }


然后在eglContext.c中有以下代码

这里ctx表示着当前需要绑定的context,然后draw表示需要读的surface,那么可以看出surface也必须是已经绑定了本个线程的context

里面有一句话。假如draw或者read的surface已经在别的线程被绑定了,那么这里会产生一个错误,那就是EGL_BAD_ACESS

/*
    * The spec says
    *
    * "If ctx is current to some other thread, or if either draw or read are
    * bound to contexts in another thread, an EGL_BAD_ACCESS error is
    * generated."and at most one context may be bound to a particular surface at a given
    * time"
    */

  if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
      if (draw->CurrentContext->Binding != t ||
          draw->CurrentContext->ClientAPI != ctx->ClientAPI)
         return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
   }


### OpenGL 多线程渲染实现方案 在 OpenGL 中实现多线程渲染需要明确线程与上下文的绑定机制,以及如何通过资源共享和同步机制提升性能。以下是多线程渲染的主要实现方式及其特点: #### 1. 主线程渲染(默认模式) 所有 OpenGL 操作均在主线程中完成。这种模式简单易用,适合初学者或对性能要求不高的场景[^1]。然而,由于所有任务都在单一线程中执行,可能导致 CPU 和 GPU 的资源利用率不足。 #### 2. 后台加载资源线程 子线程负责加载纹理、模型、着色器等资源,而主线程专注于上传这些资源到 GPU 并进行渲染。这种方式能够有效分离资源加载与渲染逻辑,减少主线程阻塞[^2]。例如,可以在子线程中读取文件并解码纹理数据,然后将结果传递给主线程以供渲染使用。 #### 3. 多 Context 渲染 每个线程绑定一个独立的 OpenGL 上下文,并通过共享机制访问相同的资源(如纹理、缓冲区)。此方法允许多个线程同时准备渲染命令,从而提高效率[^1]。需要注意的是,不同上下文之间的资源共享依赖于 OpenGL 的 `wglShareLists`(Windows)或 `glXCreateContext`(Linux/X11)等函数[^3]。 #### 4. 多线程命令录制 类似于 Vulkan 的多线程命令录制模型,多个线程可以独立生成渲染命令,最后由主线程统一提交给 GPU。这种方法要求应用程序设计合理的任务划分策略,并确保线程间的数据一致性[^4]。代码示例如下: ```cpp // 假设存在多个线程分别生成渲染命令 void ThreadTask(int threadId) { // 创建独立的上下文并与主上下文共享资源 GLuint context = CreateSharedContext(mainContext); // 录制渲染命令 glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[threadId]); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr); glDrawArrays(GL_TRIANGLES, 0, vertexCount[threadId]); // 销毁上下文 DestroyContext(context); } // 主线程提交命令 void SubmitCommands() { for (int i = 0; i < threadCount; ++i) { // 确保所有子线程完成任务 WaitForThreadCompletion(i); } // 提交最终渲染命令 glFlush(); } ``` #### 5. 真正的并行渲染 OpenGL 核心规范本身并不直接支持多线程并行渲染,但可以通过扩展(如 `GL_ARB_draw_buffers` 或 `GL_NV_command_list`)实现更高效的并行处理[^1]。这通常需要结合硬件特性进行深度优化,适用于高性能需求的实时渲染应用。 --- ### 注意事项 - **上下文绑定**:每个线程必须显式绑定其对应的 OpenGL 上下文。 - **资源共享**:确保所有参与渲染的上下文正确配置了资源共享选项。 - **同步机制**:避免因线程竞争导致的数据不一致问题,可使用 `fence sync` 或条件变量实现同步[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值