5
$\begingroup$

If I am writing my own function to check shader compile errors, or do anything that interacts with the OpenGL API but ultimately returns as a result of my application code, should I use the C++ void or GLvoid?

I.E.

GLvoid Shader::check_compile_errors(GLuint ComputeShader, std::string type)
{
    const GLint log_length{ 1024 };
    GLchar info_log[log_length];
    GLint success;

    if (type == "PROGRAM")
    {
        glGetProgramiv(ComputeShader, GL_LINK_STATUS, &success);
        if (!success)
        {
            glGetProgramInfoLog(ComputeShader, log_length, nullptr, info_log);
            std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << info_log << "\n ---- " << std::endl;
        }
    }
 // Here the return is implicitly void, but from C++ not OpenGL!
}

I realize here that GLvoid is typedef'd to void but I am wondering if there is any case where using the GL types could cause issues when it it is not explictly clear that the values are coming from OpenGL.

Another example would be writing an image to a file (from glReadPixels). If I am setting fields in the header which normally takes things in the form unsigned char should I change that to a GLuchar?

$\endgroup$
4
$\begingroup$

Yes, there's a time not to use GL types when interacting with OpenGL: GLvoid. There is absolutely no reason to use this type.

With everything else (assuming you're using a "standard" OpenGL loader), you should use OpenGL's types when talking to OpenGL. That is, the values you pass to OpenGL functions should be in OpenGL's types. This may mean that a function that talks to OpenGL may need an OpenGL data type in its function parameter list. This should be avoided where possible, to prevent you from creating dependencies between OpenGL code and non-OpenGL code.

However, if you don't mind having large portions of your application have dependencies on OpenGL, you may use OpenGL's data types throughout your code.

OpenGL's data types are specified to have a particular bitdepth. As such, they are (conceptually, if not strictly C++-legally) pointer-interconvertible to certain types defined in <stdint.h>/<cstdint>. Indeed, many OpenGL headers will check for the existence of this header and use it wherever it is available to define OpenGL's data types. As such, if you want a fixed bitdepth integer, you have a choice besides using OpenGL's data types.

I am wondering if there is any case where using the GL types could cause issues when it it is not explictly clear that the values are coming from OpenGL.

OpenGL is C, not magic. A function in C cannot have any control over the return value of the function that calls it. Even a C++ function cannot; at best, it can throw an exception, but this still doesn't have anything to do with its caller's return value.

$\endgroup$
  • $\begingroup$ So to sum up never (even when talking to OpenGL) use GLvoid and only use GLtypes when talking to OpenGL. If you need fixed bitdepth integers in your code that does not talk to OpenGL use cstdint? $\endgroup$ – Startec Nov 12 '17 at 2:32
  • $\begingroup$ And why never use GLvoid? $\endgroup$ – Startec Nov 12 '17 at 2:37
  • $\begingroup$ GLuint has a meaning that is distinct from the fundamental type unsigned int. GLvoid is no different from void. $\endgroup$ – Nicol Bolas Nov 12 '17 at 2:47
  • 1
    $\begingroup$ @Startec: Headers will redefine GLuint based on the platform(s) they work on. GLvoid will always be defined as void. $\endgroup$ – Nicol Bolas Nov 13 '17 at 20:18
  • 3
    $\begingroup$ @Startec You can as well look at it with the logic you use in your question. GLuint makes sense, because you communicate that value to the GL, you either put it into a GL function or it's returned from a GL function. But that GLvoid function is your function, a C++ function that doesn't return anything anyway, let alone a GL value, you don't go return glWhatever(...);, since you don't return anything. void is just not a meaningful data type, whose representation would have any relevance, because it has none. $\endgroup$ – Christian Rau Nov 15 '17 at 10:58
2
$\begingroup$

GL's types aren't true types but typedefs for platform types. So when you think about GLuint vs. unsigned int, you should consider that in the same way you consider unsigned int vs. uint32_t. If you are only writing for a single platform, you should read your system's GL/gl.h and pay attention to the section that looks like this:

typedef unsigned int    GLenum;
typedef unsigned char   GLboolean;
typedef unsigned int    GLbitfield;
typedef void        GLvoid;
typedef signed char GLbyte;     /* 1-byte signed */
typedef short       GLshort;    /* 2-byte signed */
typedef int     GLint;      /* 4-byte signed */
typedef unsigned char   GLubyte;    /* 1-byte unsigned */
typedef unsigned short  GLushort;   /* 2-byte unsigned */
typedef unsigned int    GLuint;     /* 4-byte unsigned */
typedef int     GLsizei;    /* 4-byte signed */
typedef float       GLfloat;    /* single precision float */
typedef float       GLclampf;   /* single precision float in [0,1] */
typedef double      GLdouble;   /* double precision float */
typedef double      GLclampd;   /* double precision float in [0,1] */

If your coding standard says you should always use the old C types instead of the guaranteed-width types like uint32_t, and you should avoid unnecessary casts, maybe it makes sense to just use the appropriate native type instead of the GL names. As Nicol Bolas says, it avoids having to include GL/gl.h. If your coding standard prefers using the guaranteed-width types, maybe it makes sense to keep using those in your non-GL code, and to think more carefully about when you pass those to functions taking GL type names.

If you avoid explicit casts wherever possible and you compile with warnings enabled, it'll be much easier to switch to a new platform where the typedefs are different, because the compiler will warn you about numeric conversions that might lose information. If you explicitly cast from (say) GLint to int, but then move to a platform where int is 16-bit and GLint is a typedef for uint32_t, then the explicit cast will stop the compiler warning you about the narrowing conversion.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.