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: Geometry shader grief

  1. #1
    Newbie Newbie
    Join Date
    Dec 2017
    Posts
    3

    Geometry shader grief

    I'm still learning but this geometry shader is giving me no end of trouble and asking for some help.

    My system is a MacBook Pro 2015 with Intel Iris which supports OpenGL 4.1

    I'm drawing a plane using an index buffer with

    Code :
    glDrawElements(GL_TRIANGLE_STRIP, this->size(), GL_UNSIGNED_SHORT, 0);

    Which using a the following vertex and fragment shader works perfectly. But when the geometry shader comes in I get nothing. I've tried all kinds of combination but it still gives me absolutely nothing as output. Anyone got ideas what I am doing wrong?

    Here's the shaders (should simply be pass through)
    Code :
        // Vertex
        const char* vert = R"glsl(
        #version 410
     
        layout (location = 0) in vec2 in_position;
     
        uniform mat4 MVP;
     
        void main() {
            gl_Position = MVP * vec4(in_position.x, 0.0f, in_position.y, 1.0f);
        }
     
        )glsl";
     
        // Geometry
        const char* geom = R"glsl(
        #version 410
     
        layout(triangles) in;
        layout(triangle_strip, max_vertices = 3) out;
     
        void main() {
     
            for (int i = 0; i < 3; ++i) {
                gl_Position = gl_in[i].gl_Position;
                EmitVertex();
            }
            EndPrimitive();
        }
        )glsl";
     
        // Fragment
        const char* frag = R"glsl(
        #version 410
     
        out vec4 out_color;
     
        void main() {
            out_color = vec4(1.0f);
        }
        )glsl";

    I've tried passing the colour through from vertex-geom-fragment, varying inputs, not using an MVP transform and all kinds of things. Am I missing something vital with this simple setup? I'm not setting up and glProgramParameteri because I assumed they were not necessary with geom layouts.

    Thanks
    Fred

  2. #2
    Member Regular Contributor
    Join Date
    Jul 2012
    Posts
    448
    What you posted does not look bad.

    So:
    as usual, check for any OpenGL errors
    copy/paste a GS example from the net and compare with what you have

  3. #3
    Newbie Newbie
    Join Date
    Dec 2017
    Posts
    3

    Still hunting...

    Good thinking. It seems like I am actually getting error code 0x502 which is GL_INVALID_OPERATION when drawing this shape. I tried to create a minimal working example but I don't really know what I am doing wrong at this point. Been doing trial and error the last 2 days without luck. Here's the code in it's entirety:

    It works perfectly without the geometry shader but with it I get error 0x502. How would I go about hunting this down? Could it somehow be that geometry shaders are not supported on my GPU or something similarly silly?

    OpenGL 4.1, latest glbinding and glfw

    Code :
     
    #include <iostream>
     
    #define GLFW_INCLUDE_NONE
    #include <glbinding/gl/gl.h>
    #include <glbinding/Binding.h>
     
    #define GLFW_DLL
    #include <GLFW/glfw3.h>
     
    using namespace gl;
     
     
    void error_callback(int error, const char* description) {
        fprintf(stderr, "Error: %s\n", description);
    }
     
     
    void create_program(GLuint &handle, GLuint *shaders) {
     
        handle = glCreateProgram();
     
        for (int i = 0; i < (sizeof(shaders) / sizeof(shaders[0])); ++i) {
            glAttachShader(handle, shaders[i]);
        }
     
        glLinkProgram(handle);
     
        // clean up after successful linking
        for (int i = 0; i < (sizeof(shaders) / sizeof(shaders[0])); ++i) {
            glDetachShader(handle, shaders[i]);
        }
    }
     
    // Comment to toggle geometry shader
    #define GEOMETRY_SHADER
     
     
    #ifdef GEOMETRY_SHADER
    #define NUM_SHADERS 3
    #else
    #define NUM_SHADERS 2
    #endif
     
    // Globals
    GLuint prog;
    GLuint vbo[1];
    GLuint vao; // not needed?
    GLuint shaders[NUM_SHADERS];
     
     
    // Vertex shader
    const char* vert = R"glsl(
    #version 410
     
    layout (location = 0) in vec2 in_position;
     
    out gs_PerVertex {
        vec4 color;
    } vs_out;
     
    //uniform mat4 MVP;
     
    void main() {
     
        gl_Position = vec4(in_position.x, in_position.y, 0.0f, 1.0f);
    //    vs_out.color = vec4(1.0f); // white
    }
     
    )glsl";
     
    // Geometry shader
    const char* geom = R"glsl(
    #version 410
     
    layout(triangles) in;
    layout(triangle_strip, max_vertices=3) out;
     
    // Input block
    in gs_PerVertex {
        vec4 color;
    } gs_in[];
     
    // Output block
    out gs_PerVertex {
        vec4 color;
    } gs_out;
     
    void main() {
     
        for (int i = 0; i < 3; ++i) {
            gl_Position = gl_in[i].gl_Position + vec4(0.3);
    //        gs_out.color = gs_in[i].color;
            EmitVertex();
        }
        EndPrimitive();
     
    }
    )glsl";
     
    // Fragment shader
    const char* frag = R"glsl(
    #version 410
     
    in gs_PerVertex {
        vec4 color;
    } gs_in;
     
    //    in vec4 color;
    out vec4 out_color;
     
    void main() {
     
    //    out_color = gs_in.color;
        out_color = vec4(1.0f);
     
    }
    )glsl";
     
     
    void compile_info(const GLuint shader) {
        GLint status(0);
        glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
     
        if (1 != status) {
            GLint maxLength(0);
            GLint logLength(0);
     
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
     
            GLchar log[maxLength];
            glGetShaderInfoLog(shader, maxLength, &logLength, log);
            fprintf(stderr, "Compiling shader %u failed: %s", shader, log);
     
        }
    }
     
    void create_shader(GLuint &shader, GLenum type, const char* src) {
     
        shader = glCreateShader(type);
     
        glShaderSource(shader, 1, &src, NULL);
        glCompileShader(shader);
     
        // check for errors
        compile_info(shader);
    }
     
    void link_info(const GLuint program) {
        GLint status(0);
        glGetProgramiv(program, GL_LINK_STATUS, &status);
     
        if (1 != status) {
            GLint maxLength(0);
            GLint logLength(0);
     
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
     
            GLchar log[maxLength];
            glGetProgramInfoLog(program, maxLength, &logLength, log);
     
            fprintf(stderr, "Linking of program failed: %s\n", log);
        }
    }
     
    void create_program(GLuint &_p, GLint *_s) {
        _p = glCreateProgram();
     
        if(_p == 0)
            fprintf(stderr, "Could not create shader program.\n");
     
        for (int i = 0; i < (sizeof(_s) / sizeof(_s[0])); ++i) {
            glAttachShader(_p, _s[i]);
        }
     
        glLinkProgram(_p);
     
        // Check for errors.
        link_info(_p);
     
        // Clean up.
        for (int i = 0; i < (sizeof(_s) / sizeof(_s[0])); ++i) {
            glDetachShader(_p, _s[i]);
        }
    }
     
     
    /// Check for errors. Poll gl for all error messages and print to
    /// stderr.
    // TODO convert these messages to strings (with glfw?)
    void check_errors() {
        GLenum err;
        while ((err = glGetError()) != GL_NO_ERROR) {
            fprintf(stderr, "OpenGl encountered an error with code: %d\n", err);
        }
    }
     
    struct Point2D {
        float x, y;
    };
     
    const Point2D vertices_data[] = {
        {-0.5, -0.5},
        {0.5, -0.5},
        {-0.5, 0.5},
     
        {-0.5, 0.5},
        {0.5, -0.5},
        {0.5, 0.5}
    };
     
    int init_resources() {
     
        // Generate shader and shader program handles
    #ifdef GEOMETRY_SHADER
        create_shader(shaders[0], GL_VERTEX_SHADER, vert);
        create_shader(shaders[1], GL_GEOMETRY_SHADER, geom);
        create_shader(shaders[2], GL_FRAGMENT_SHADER, frag);
    #else
        create_shader(shaders[0], GL_VERTEX_SHADER, vert);
        create_shader(shaders[1], GL_FRAGMENT_SHADER, frag);
    #endif
     
        create_program(prog, shaders);
     
        GLint a_pos = glGetAttribLocation(prog, "in_position");
     
        if (a_pos == -1) {
            fprintf(stderr, "Could not find attribute in shader.");
        }
     
        glGenBuffers(1, vbo);
        glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices_data), vertices_data, GL_STATIC_DRAW);
     
        glGenVertexArrays(1, &vao);
        glBindVertexArray(vao);
     
        glEnableVertexAttribArray(a_pos);
        glVertexAttribPointer(/*index:*/a_pos, /*size:*/2, /*type:*/GL_FLOAT, /*norm:*/GL_FALSE, 0, 0);
     
        glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
     
        glBindVertexArray(0);
     
        check_errors();
     
        return 1;
    }
     
    void draw_scene() {
        glBindVertexArray(vao);
        glUseProgram(prog);
     
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);
     
        glBindVertexArray(0);
     
        check_errors();    
    }
     
     
    void free_resources() {
        glDeleteProgram(prog);
    }
     
     
    int main(int argc, const char * argv[]) {
        GLFWwindow *window;
        int width, height;
     
        glfwSetErrorCallback(error_callback);
     
        if (!glfwInit())
            return -1;
     
        glfwDefaultWindowHints(); // ?
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true);
        glfwWindowHint(GLFW_RESIZABLE, false);
        glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true); // ?
     
        window = glfwCreateWindow(640, 480, "Hello", NULL, NULL);
     
        if (!window) {
            glfwTerminate();
            return -1;
        }
     
        glfwGetFramebufferSize(window, &width, &height);
        glfwMakeContextCurrent(window);
        glbinding::Binding::initialize(false);
     
        init_resources();
     
        // Just draw once to check for errors
        draw_scene();
        glfwSwapBuffers(window);
     
        // Main loop
        while(!glfwWindowShouldClose(window)) {
            glfwPollEvents();
    //        draw_scene();
    //        glfwSwapBuffers(window);
        }
     
        // Clean up.
        free_resources();
     
        glUseProgram(0);
        glDisableVertexAttribArray(0);
     
        glfwDestroyWindow(window);
        glfwTerminate();
     
        return 0;
    }

  4. #4
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,575
    Quote Originally Posted by planetexp View Post
    It works perfectly without the geometry shader but with it I get error 0x502. How would I go about hunting this down?
    Find which command generates the error. Set a breakpoint inside check_errors() when, then start adding more calls. Once you've identified the command (a call to check_errors() immediately before it succeeds, a call immediately after reports an error), refer to its documentation in the reference pages or (preferably) the specification to see the conditions which can cause that particular error.

    Quote Originally Posted by planetexp View Post
    Could it somehow be that geometry shaders are not supported on my GPU or something similarly silly?

    OpenGL 4.1, latest glbinding and glfw
    Geometry shaders are a requirement of OpenGL 3.2 and above.

  5. #5
    Advanced Member Frequent Contributor arekkusu's Avatar
    Join Date
    Nov 2003
    Posts
    873
    Quote Originally Posted by planetexp View Post
    I don't really know what I am doing
    Your error has nothing to do with OpenGL. You need to understand how pointers work:
    Code :
    void create_program(GLuint &handle, GLuint *shaders) {
    ...
        for (int i = 0; i < (sizeof(shaders) / sizeof(shaders[0])); ++i)

    On x86_64, sizeof(GLuint *) is 8, and sizeof((GLuint *)[0]) is 4, so this always loops twice.


    How would I go about hunting this down?
    * Learn to use your platform's debugger.

    * Learn how to introspect GL state. You're checking errors, compile state, and link state. But not the object state; glGetProgram will tell you everything about your linked program (like how many shaders are attached to it). glValidateProgram's log in this case would have helpfully informed you: "Validation Failed: Program does not contain fragment shader. Results will be undefined."

  6. #6
    Newbie Newbie
    Join Date
    Dec 2017
    Posts
    3
    Quote Originally Posted by arekkusu View Post
    Your error has nothing to do with OpenGL. You need to understand how pointers work:
    Holy sweet jesus, I didn't realise I just passing a pointer. This was the issue. There was another create_program() function that I was calling as well. I didn't think to look there. Thanks a million!

    Quote Originally Posted by arekkusu View Post
    Thank you for the link, I've been looking how to debug on macOS for ages.

    Programming is like a giant game of Where's Waldo sometimes...

    Cheers
    Fred

Posting Permissions

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