OpenGL: secondary thread for loading resources?

后端 未结 3 2081
谎友^
谎友^ 2020-12-09 05:55

Working with C and Win32, I would like to know how to implement a secondary OpenGL thread for loading resources(textures and VBOs).

From what I found, this should be

相关标签:
3条回答
  • 2020-12-09 06:10

    You don't need a new context because you can reuse the same device context of the first one. Btw, you can specify another device context, but depending on your platform you should take care about it (on Windows, device contextes must have the same pixel format), otherwise you could fail to share objects between two contextes

    Create both context in the main thread, the second one sharing with the first one. Then, make the first one current on the main thread, while making the other one current on the secondary thread. Note that you can share with any render context: all sharing contextes "see" the same object by its name, indeed they share an object name space. Two different object name spaces (i.e. two non-sharing contextes) can have defined the same object (i.e. texture object name is 1), but the same name actually points to different object depending on the current context.

    Objects created by the secondary thread are visible concurrently and consistently. However, not all objects can be shared across contextes. Keep in mind that sometimes it happens that the driver supports unexpected objects, and other times it happens that driver doesn't support correctly an expected object.

    OpenGL is becoming an object oriented language. You can see a certain pattern for creating objects:

    • Generate name (GenTextures, GenBuffers)
    • Define object (BindTexture, BindBuffer)
    • Object existence (IsTexture, IsShader, IsFramebuffer)
    • Delete name (and object)

    (Note that an object created with Gen routines exists only when they are bound)

    Object classes could be

    • Display lists
    • Texture objects
    • Buffer objects
    • Shader objects and program objects
    • Renderbuffer objects
    • Framebuffer objects
    • Query objects
    • Sync objects
    • Transform feedback objects

    I would suggest to use a "runtime" test, like the following:

    private bool TestSharingObject(RenderContext rContextShare)
    {
        uint texture = 0;
    
        // rContextShader is a context sharing with this RenderCOntext
    
        this.MakeCurrent(true);
    
        if (Caps.TextureObject.Supported == true) {
            // Generate texture name
            Gl.GenTextures(1, out texture);
            // Ensure existing texture object
            Gl.BindTexture(Gl.TEXTURE_2D, texture);
            Gl.BindTexture(Gl.TEXTURE_2D, 0);
            // Self test
            if (Gl.IsTexture(texture) == false)
                throw new NotSupportedException();
        }
    
        // Make current sharing context
        rContextShare.MakeCurrent(true);
    
        return ((texture != 0) && (Gl.IsTexture(texture) == true));
    }
    

    Another suggestion would be to run on secondary thread operations that are CPU intensive, and not directly affecting drawing system windows buffers. A good example would be a shader compilation, since the compilation runs on CPU side; keep also in mind that the driver could async your operations, and that OpenGL implementations may pipeline different operations..

    0 讨论(0)
  • 2020-12-09 06:16

    It works!, only if wglShareLists is done by the main thread for all the worker thread. Using message map, pass the reference of rendering context and make the main thread create the rendering context, use wglShareLists by main thread alone. Then call wglMakeCurrent on the worker thread with the rendering context created by main thread. It is imperative that wglShareLists is called before any gl operation is done on the rendering context. This is due to the requirement on parameter hglrc2(the OpenGL rendering context to share display lists with hglrc1), that it should not contain any existing display lists when wglShareLists is called.

    0 讨论(0)
  • 2020-12-09 06:18

    Load resources however you need to in your secondary thread and then pass ownership of them back to your primary for the GL calls.

    Sharing "lists" between GL contexts should work. Doing all your GL calls on your primary thread does work :)

    0 讨论(0)
提交回复
热议问题