Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 6 of 6

Thread: GLSL line rendering is slower than fix function.

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Junior Member Regular Contributor
    Join Date
    Dec 2002
    Posts
    120

    GLSL line rendering is slower than fix function.

    Recently I plan to switch my old fix function rendering method to GLSL, but the GLSL method is a lot slower than the fix function.

    Here is my Vertex Shader

    Code :
    #version 330 core
     
     
    uniform mat4 u_MVPMatrix;        // A constant representing the combined model/view/projection matrix.
     
     
    layout(location = 0) in vec4 a_Position;        // Per-vertex position information we will pass in.
     
     
    // The entry point for our vertex shader.  
    void main()                                                     
    {
        // gl_Position is a special variable used to store the final position.
        // Multiply the vertex by the matrix to get the final point in normalized screen coordinates.
        gl_Position = u_MVPMatrix * a_Position;                                 
    }

    Fragment Shader

    Code :
    #version 330 core
     
     
    precision mediump float;           // Set the default precision to medium. We don't need as high of a 
                                    // precision in the fragment shader.
    out vec4 v_Color;              // This is the color from the vertex shader interpolated across the
                                      // triangle per fragment.
    uniform vec4 LineColor;
     
     
    // The entry point for our fragment shader.
    void main()                            
    {                                  
        // Pass through the color
        v_Color=LineColor;
    }


    Code :
                ShaderSelect tempS = SelectShaders;
                //Buffer
                tempS.UseProgram();
     
     
                EnableVertexAttribArrayARB(0);
                VertexAttribPointerfARB(0, 3, 0, 0, vertices);
     
     
                glUniform4fARB(tempS.mLineColor, color[0], color[1], color[2], color[3]);
     
     
                glUniformMatrix4fvARB(tempS.mMVPMatrixHandle, 1, 0, CombineMatrix); // Fix combine matrix
     
                Gl.glDrawArrays(Gl.GL_LINE_LOOP, 0, num);
     
     
                DisableVertexAttribArray(0);
     
     
                tempS.Disable();

    This is the Fix Function
    Code :
                    Gl.glEnableClientState(Gl.GL_VERTEX_ARRAY);
                    Gl.glVertexPointer(3, Gl.GL_DOUBLE, 0, point);
                    if (closed)
                        Gl.glDrawArrays(Gl.GL_LINE_LOOP, 0, num);
                    else
                        Gl.glDrawArrays(Gl.GL_LINE_STRIP, 0, num);
                    //                Gl.glFinish();
                    Gl.glDisableClientState(Gl.GL_VERTEX_ARRAY);
    By rendering 100000 of circle and each circle with 40 points.

    Fix function give 7 to 8 fps.
    GLSL give only 1 to 2 fps.


    Is it by design? Or do I did anything wrong on the code?

  2. #2
    Senior Member OpenGL Guru Dark Photon's Avatar
    Join Date
    Oct 2004
    Location
    Druidia
    Posts
    4,156
    Quote Originally Posted by HanWu View Post
    Recently I plan to switch my old fix function rendering method to GLSL, but the GLSL method is a lot slower than the fix function.
    ...
    By rendering 100000 of circle and each circle with 40 points.

    Fix function give 7 to 8 fps.
    GLSL give only 1 to 2 fps.

    Is it by design? Or do I did anything wrong on the code?
    Both of your implementations are very inefficient. You're doing more to profile your CPU than your GPU or the GL driver.

    There's no need to:

    • constantly unbind a program after use,
    • re-bind a program that's already bound,
    • disable a vertex attribute after use,
    • needlessly re-enable it again for the next batch (glDraw* call),
    • continually re-set a vertex attribute to the same value (not sure if you're doing this with color or not), or even
    • to have separate batches for each circle.

    The first 5 can be trivially cleaned up. Also, now that you're playing with GLSL, consider using hardware geometry instancing, either via Instanced arrays or glDraw*Instanced* calls and gl_InstanceID in the shader. You could potentially render all of your 100k circles with one draw call.

    There are other techniques you can use to stop re-uploading your shape data to the GPU every frame and re-specifying your batch parameters for every batch (e.g. VBOs, and VAOs or bindless), potentially netting you even more speed-up for both the shader and fixed-function test cases.

    Just out of curiosity, what GPU and GL driver/version are you using?
    Last edited by Dark Photon; 10-31-2017 at 07:41 AM.

  3. #3
    Senior Member OpenGL Pro
    Join Date
    Jan 2007
    Posts
    1,716
    Another observation - you're mixing the GL_ARB_shader_objects extension with GLSL 330 shaders - that's not a good practice because GL_ARB_shader_objects was never actually promoted to core (and therefore has limited or no guarantee of compatibility with later functionality), so you really should be just using the core GL 2.0 entry points instead.

  4. #4
    Junior Member Regular Contributor
    Join Date
    Dec 2002
    Posts
    120
    Quote Originally Posted by mhagain View Post
    Another observation - you're mixing the GL_ARB_shader_objects extension with GLSL 330 shaders - that's not a good practice because GL_ARB_shader_objects was never actually promoted to core (and therefore has limited or no guarantee of compatibility with later functionality), so you really should be just using the core GL 2.0 entry points instead.
    Hi, Thanks for the advise.

  5. #5
    Junior Member Regular Contributor
    Join Date
    Dec 2002
    Posts
    120
    Thanks for the advise. After did some modification on the code

    Code :
    /// only call once
    ShaderSelect tempS = SelectShaders;
                //Buffer
                tempS.UseProgram();
    EnableVertexAttribArrayARB(0);
     /// only call once end
     
     
    /// loop for 100000 circle
     
    // each circle position at different location and store in vertices
                VertexAttribPointerfARB(0, 3, 0, 0, vertices);
    // each circle has different color.
                glUniform4fARB(tempS.mLineColor, color[0], color[1], color[2], color[3]);
                glUniformMatrix4fvARB(tempS.mMVPMatrixHandle, 1, 0, CombineMatrix); // Fix combine matrix
                Gl.glDrawArrays(Gl.GL_LINE_LOOP, 0, num);
     
     
     /// only call once
                DisableVertexAttribArray(0);
    tempS.Disable();
    /// only call once end

    By doing this, I can have up to 5 to 6 fps but still a bit slower than the fix function.

  6. #6
    Senior Member OpenGL Pro
    Join Date
    Jan 2007
    Posts
    1,716
    Is that glUniform4fARB (again, please stop using the -ARB versions of these) intended to replace a glColor4f in the fixed version? If so, you should replace it with a glVertexAttrib4f (don't use -ARB, the -ARB versions are for the GL_ARB_vertex_program extension, not for GL 2.0+) then rework your shaders to pass this attrib from VS to FS for use as a colour.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •