【问题标题】:Multiple context with different version具有不同版本的多个上下文
【发布时间】:2011-09-21 05:47:02
【问题描述】:

我正在尝试在多个 OpenGL 上下文之间共享列表。这是一个很棒的功能,因为它允许我执行并行渲染线程。

但由于我使用的是 CreateContextAttribs,因此我提供了请求特定 OpenGL 实现的可能性。因此,可能会发生某些上下文正在实现 3.2+ 版本,而另一个上下文正在实现 2.1 版本。

实际上工作得很好,但我怀疑这种作案手法隐藏了一些副作用。使用具有不同版本的上下文时可能出现的问题列表是什么?

除此之外,我查询每个上下文版本的实现扩展,因为我认为不同的版本可以支持不同的扩展,对吗?那么函数指针呢?我必须为具有不同版本的每个上下文重新查询它们(实际上,指针会根据版本而变化)?

【问题讨论】:

    标签: opengl opengl-3


    【解决方案1】:

    这是一个很棒的功能,因为它允许我执行并行渲染线程。

    从多个线程并行访问 GPU 是严重的性能杀手。不要这样做。 GPU 将在内部并行化任何渲染。你所做的任何其他事情都是把原木扔进它的轮子里。

    如果您想加快资产上传速度,请查看缓冲区对象和异步访问。但不要同时在不同的线程中执行多个 OpenGL 上下文。


    但由于我使用的是 CreateContextAttribs,因此我提供了请求特定 OpenGL 实现的可能性。因此,可能会发生某些上下文正在实现 3.2+ 版本,而另一个上下文正在实现 2.1 版本。

    实际上工作得很好,但我怀疑这种作案手法隐藏了一些副作用。使用具有不同版本的上下文时可能出现的问题列表是什么?

    这实际上是一个非常好的问题。 specification 明确回答:

    1) Can different GL context versions share data?
    
        PROPOSED: Yes, with restrictions as defined by the supported feature
        sets. For example, program and shader objects cannot be shared with
        OpenGL 1.x contexts, which do not support them.
    
        NOTE: When the new object model is introduced, sharing must be
        established at creation time, since the object handle namespace is
        also shared. wglShareLists would therefore fail if either context
        parameter to it were to be a context supporting the new object
        model.
    

    除此之外,我查询每个上下文版本的实现扩展,因为我认为不同的版本可以支持不同的扩展,对吗?

    确实,为每个上下文查询支持的扩展集是正确的做法。

    那么函数指针呢?我必须为具有不同版本的每个上下文重新查询它们(实际上,指针会根据版本而变化)?

    在 Windows 上,扩展函数指针与上下文相关联。做到这一点的明智方法是有一些

    typedef struct OpenGLExtFunctions_S {
        GLvoid (*glFoobarEXT)(GLenum, ...);
        /* OpenGL function pointers */
    } OpenGLExtFunctions;
    
    /* currentContextFunction must be thread loacal since
       contexts are active in one thread only */
    __declspec(thread) OpenGLExtFunctions *currentContextFunctions;
    
    #define glFoobarEXT (currentContextFunctions->glFoobarEXT);
    #define ...
    

    并用一些帮助函数包装wglMakeCurrentwglMakeContextCurrent,将currentContextFunctions 指针设置为当前上下文之一。像 GLEW 这样的扩展包装库会为您完成所有这些繁重的工作,因此您不必费心自己动手。

    在 X11/GLX 上事情要简单得多:glXGetProcAddress 返回的函数指针对于所有上下文必须相同,因此无需切换它们。

    【讨论】:

    • 感谢您的批评,但我发现在不同线程中的着色器编译和纹理上传实际上执行“更快”(即不影响实际渲染的 FPS)。还有......真正的问题呢?
    • @Luca Piccioni:着色器编译和纹理上传,这是在单独的线程中真正有意义的仅有的两件事,因为它们都不会真正限制 GPU。着色器由 CPU 编译,纹理上传分为两个过程,首先上传到 CPU 内存中的缓冲区,然后延迟上传到 GPU 内存。
    • 我已经对此进行了实验。我的问题来自以下情况:由 2.1 上下文生成的着色器,可以由具有不同版本的上下文执行吗?我可以混合来自具有其他版本的不同上下文的不同着色器对象吗?除了这种情况,问题以更笼统的方式发布。
    • @Luca Piccioni:我也回答了你的其他问题。查看我的编辑。
    • 谢谢,但我不使用 GLEW,因为我在 .NET 平台上开发自己的项目。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-18
    • 1970-01-01
    • 2015-12-04
    • 2021-07-25
    • 2020-10-29
    相关资源
    最近更新 更多