From 184588122ad52ea7013fa2c1d2f5324ddf33dc39 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sun, 1 Feb 2026 01:23:52 +0100 Subject: [PATCH 01/15] Start transitioning to OpenGL 4.6 --- include/ghoul/opengl/ghoul_gl.h | 20 +- src/opengl/programobject.cpp | 1353 +++++++------------------------ src/opengl/shaderobject.cpp | 28 +- 3 files changed, 311 insertions(+), 1090 deletions(-) diff --git a/include/ghoul/opengl/ghoul_gl.h b/include/ghoul/opengl/ghoul_gl.h index 97b3a7a4..d15a4fed 100644 --- a/include/ghoul/opengl/ghoul_gl.h +++ b/include/ghoul/opengl/ghoul_gl.h @@ -43,7 +43,7 @@ #pragma GCC diagnostic ignored "-Wuseless-cast" #endif -#include +#include #include #define __GL_H__ @@ -69,20 +69,16 @@ namespace ghoul { struct GLDebugGroup { explicit GLDebugGroup(std::string_view name) { - if (glbinding::Binding::PushDebugGroup.isResolved()) { - glPushDebugGroup( - GL_DEBUG_SOURCE_APPLICATION, - 0, - static_cast(name.length()), - name.data() - ); - } + glPushDebugGroup( + GL_DEBUG_SOURCE_APPLICATION, + 0, + static_cast(name.length()), + name.data() + ); } ~GLDebugGroup() { - if (glbinding::Binding::PopDebugGroup.isResolved()) { - glPopDebugGroup(); - } + glPopDebugGroup(); } }; diff --git a/src/opengl/programobject.cpp b/src/opengl/programobject.cpp index 28885b6d..4a64589d 100755 --- a/src/opengl/programobject.cpp +++ b/src/opengl/programobject.cpp @@ -64,14 +64,12 @@ ProgramObject::ProgramObject(std::string name) if (_id == 0) { throw ProgramObjectError("glCreateProgram returned 0"); } - if (glbinding::Binding::ObjectLabel.isResolved()) { - glObjectLabel( - GL_PROGRAM, - _id, - static_cast(_programName.length() + 1), - _programName.c_str() - ); - } + glObjectLabel( + GL_PROGRAM, + _id, + static_cast(_programName.length() + 1), + _programName.c_str() + ); } ProgramObject::ProgramObject(const ProgramObject& cpy) @@ -87,14 +85,12 @@ ProgramObject::ProgramObject(const ProgramObject& cpy) throw ProgramObjectError("glCreateProgram returned 0"); } - if (glbinding::Binding::ObjectLabel.isResolved()) { - glObjectLabel( - GL_PROGRAM, - _id, - static_cast(_programName.length() + 1), - _programName.c_str() - ); - } + glObjectLabel( + GL_PROGRAM, + _id, + static_cast(_programName.length() + 1), + _programName.c_str() + ); for (const std::shared_ptr& obj : cpy._shaderObjects) { auto shaderCopy = std::make_shared(*obj); @@ -115,14 +111,12 @@ ProgramObject& ProgramObject::operator=(const ProgramObject& rhs) { if (this != &rhs) { _programName = rhs._programName; - if (glbinding::Binding::ObjectLabel.isResolved()) { - glObjectLabel( - GL_PROGRAM, - _id, - static_cast(rhs._programName.length() + 1), - rhs._programName.c_str() - ); - } + glObjectLabel( + GL_PROGRAM, + _id, + static_cast(rhs._programName.length() + 1), + rhs._programName.c_str() + ); _loggerCat = rhs._loggerCat; _ignoreUniformLocationError = rhs._ignoreUniformLocationError; _ignoreAttributeLocationError = rhs._ignoreAttributeLocationError; @@ -136,14 +130,12 @@ ProgramObject& ProgramObject::operator=(const ProgramObject& rhs) { if (_id == 0) { throw ProgramObjectError("glCreateProgram returned 0"); } - if (glbinding::Binding::ObjectLabel.isResolved()) { - glObjectLabel( - GL_PROGRAM, - _id, - static_cast(_programName.length() + 1), - _programName.c_str() - ); - } + glObjectLabel( + GL_PROGRAM, + _id, + static_cast(_programName.length() + 1), + _programName.c_str() + ); for (const std::shared_ptr& obj : rhs._shaderObjects) { auto shaderCopy = std::make_shared(*obj); @@ -161,14 +153,12 @@ ProgramObject& ProgramObject::operator=(ProgramObject&& rhs) noexcept { rhs._id = 0; _programName = std::move(rhs._programName); - if (glbinding::Binding::ObjectLabel.isResolved()) { - glObjectLabel( - GL_PROGRAM, - _id, - static_cast(_programName.length() + 1), - _programName.c_str() - ); - } + glObjectLabel( + GL_PROGRAM, + _id, + static_cast(_programName.length() + 1), + _programName.c_str() + ); _loggerCat = std::move(rhs._loggerCat); _ignoreUniformLocationError = rhs._ignoreUniformLocationError; _ignoreAttributeLocationError = rhs._ignoreAttributeLocationError; @@ -185,14 +175,12 @@ ProgramObject& ProgramObject::operator=(ProgramObject&& rhs) noexcept { void ProgramObject::setName(std::string name) { _programName = std::move(name); _loggerCat = std::format("ProgramObject['{}']", _programName); - if (glbinding::Binding::ObjectLabel.isResolved()) { - glObjectLabel( - GL_PROGRAM, - _id, - static_cast(_programName.length() + 1), - _programName.c_str() - ); - } + glObjectLabel( + GL_PROGRAM, + _id, + static_cast(_programName.length() + 1), + _programName.c_str() + ); } const std::string& ProgramObject::name() const{ @@ -1251,850 +1239,347 @@ bool ProgramObject::setUniform(const std::string& name, const glm::dmat4x4& valu void ProgramObject::setUniform(GLint location, GLuint value) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform1ui.isResolved()) { - glProgramUniform1ui(_id, location, value); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform1ui(location, value); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform1ui(_id, location, value); } void ProgramObject::setUniform(GLint location, GLuint v1, GLuint v2) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform2ui.isResolved()) { - glProgramUniform2ui(_id, location, v1, v2); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform2ui(location, v1, v2); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform2ui(_id, location, v1, v2); } void ProgramObject::setUniform(GLint location, GLuint v1, GLuint v2, GLuint v3) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform3ui.isResolved()) { - glProgramUniform3ui(_id, location, v1, v2, v3); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform3ui(location, v1, v2, v3); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform3ui(_id, location, v1, v2, v3); } -void ProgramObject::setUniform(GLint location, - GLuint v1, GLuint v2, GLuint v3, GLuint v4) const +void ProgramObject::setUniform(GLint location, GLuint v1, GLuint v2, GLuint v3, + GLuint v4) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform4ui.isResolved()) { - glProgramUniform4ui(_id, location, v1, v2, v3, v4); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform4ui(location, v1, v2, v3, v4); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform4ui(_id, location, v1, v2, v3, v4); } void ProgramObject::setUniform(GLint location, const glm::uvec2& value) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform2uiv.isResolved()) { - glProgramUniform2uiv(_id, location, 1, glm::value_ptr(value)); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform2uiv(location, 1, glm::value_ptr(value)); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform2uiv(_id, location, 1, glm::value_ptr(value)); } void ProgramObject::setUniform(GLint location, const glm::uvec3& value) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform3uiv.isResolved()) { - glProgramUniform3uiv(_id, location, 1, glm::value_ptr(value)); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform3uiv(location, 1, glm::value_ptr(value)); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform3uiv(_id, location, 1, glm::value_ptr(value)); } void ProgramObject::setUniform(GLint location, const glm::uvec4& value) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform4uiv.isResolved()) { - glProgramUniform4uiv(_id, location, 1, glm::value_ptr(value)); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform4uiv(location, 1, glm::value_ptr(value)); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform4uiv(_id, location, 1, glm::value_ptr(value)); } void ProgramObject::setUniform(GLint location, const std::vector& values) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform1uiv.isResolved()) { - glProgramUniform1uiv( - _id, - location, - static_cast(values.size()), - values.data() - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform1uiv(location, static_cast(values.size()), values.data()); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform1uiv( + _id, + location, + static_cast(values.size()), + values.data() + ); } void ProgramObject::setUniform(GLint location, const std::vector& values) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform2uiv.isResolved()) { - glProgramUniform2uiv( - _id, - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform2uiv( - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform2uiv( + _id, + location, + static_cast(values.size()), + reinterpret_cast(values.data()) + ); } void ProgramObject::setUniform(GLint location, const std::vector& values) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform3uiv.isResolved()) { - glProgramUniform3uiv( - _id, - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform3uiv( - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform3uiv( + _id, + location, + static_cast(values.size()), + reinterpret_cast(values.data()) + ); } void ProgramObject::setUniform(GLint location, const std::vector& values) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform4uiv.isResolved()) { - glProgramUniform4uiv( - _id, - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform4uiv( - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform4uiv( + _id, + location, + static_cast(values.size()), + reinterpret_cast(values.data()) + ); } void ProgramObject::setUniform(GLint location, GLint value) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform1i.isResolved()) { - glProgramUniform1i(_id, location, value); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform1i(location, value); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform1i(_id, location, value); } void ProgramObject::setUniform(GLint location, GLint v1, GLint v2) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform2i.isResolved()) { - glProgramUniform2i(_id, location, v1, v2); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform2i(location, v1, v2); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform2i(_id, location, v1, v2); } void ProgramObject::setUniform(GLint location, GLint v1, GLint v2, GLint v3) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform3i.isResolved()) { - glProgramUniform3i(_id, location, v1, v2, v3); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform3i(location, v1, v2, v3); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform3i(_id, location, v1, v2, v3); } void ProgramObject::setUniform(GLint location, GLint v1, GLint v2, GLint v3, GLint v4) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform4i.isResolved()) { - glProgramUniform4i(_id, location, v1, v2, v3, v4); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform4i(location, v1, v2, v3, v4); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform4i(_id, location, v1, v2, v3, v4); } void ProgramObject::setUniform(GLint location, const glm::ivec2& value) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform2iv.isResolved()) { - glProgramUniform2iv(_id, location, 1, glm::value_ptr(value)); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform2iv(location, 1, glm::value_ptr(value)); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform2iv(_id, location, 1, glm::value_ptr(value)); } void ProgramObject::setUniform(GLint location, const glm::ivec3& value) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform3iv.isResolved()) { - glProgramUniform3iv(_id, location, 1, glm::value_ptr(value)); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform3iv(location, 1, glm::value_ptr(value)); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform3iv(_id, location, 1, glm::value_ptr(value)); } void ProgramObject::setUniform(GLint location, const glm::ivec4& value) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform4iv.isResolved()) { - glProgramUniform4iv(_id, location, 1, glm::value_ptr(value)); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform4iv(location, 1, glm::value_ptr(value)); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform4iv(_id, location, 1, glm::value_ptr(value)); } void ProgramObject::setUniform(GLint location, const std::vector& values) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform1iv.isResolved()) { - glProgramUniform1iv( - _id, - location, - static_cast(values.size()), - values.data() - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform1iv(location, static_cast(values.size()), values.data()); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform1iv( + _id, + location, + static_cast(values.size()), + values.data() + ); } void ProgramObject::setUniform(GLint location, const std::vector& values) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform2iv.isResolved()) { - glProgramUniform2iv( - _id, - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform2iv( - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform2iv( + _id, + location, + static_cast(values.size()), + reinterpret_cast(values.data()) + ); } void ProgramObject::setUniform(GLint location, const std::vector& values) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform3iv.isResolved()) { - glProgramUniform3iv( - _id, - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform3iv( - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform3iv( + _id, + location, + static_cast(values.size()), + reinterpret_cast(values.data()) + ); } void ProgramObject::setUniform(GLint location, const std::vector& values) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform4iv.isResolved()) { - glProgramUniform4iv( - _id, - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform4iv( - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform4iv( + _id, + location, + static_cast(values.size()), + reinterpret_cast(values.data()) + ); } void ProgramObject::setUniform(GLint location, GLfloat value) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform1f.isResolved()) { - glProgramUniform1f(_id, location, value); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform1f(location, value); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform1f(_id, location, value); } void ProgramObject::setUniform(GLint location, GLfloat v1, GLfloat v2) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform2f.isResolved()) { - glProgramUniform2f(_id, location, v1, v2); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform2f(location, v1, v2); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform2f(_id, location, v1, v2); } void ProgramObject::setUniform(GLint location, GLfloat v1, GLfloat v2, GLfloat v3) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform3f.isResolved()) { - glProgramUniform3f(_id, location, v1, v2, v3); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform3f(location, v1, v2, v3); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform3f(_id, location, v1, v2, v3); } -void ProgramObject::setUniform(GLint location, - GLfloat v1, GLfloat v2, GLfloat v3, GLfloat v4) const +void ProgramObject::setUniform(GLint location, GLfloat v1, GLfloat v2, GLfloat v3, + GLfloat v4) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform4f.isResolved()) { - glProgramUniform4f(_id, location, v1, v2, v3, v4); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform4f(location, v1, v2, v3, v4); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform4f(_id, location, v1, v2, v3, v4); } void ProgramObject::setUniform(GLint location, const glm::vec2& value) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform2fv.isResolved()) { - glProgramUniform2fv(_id, location, 1, glm::value_ptr(value)); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform2fv(location, 1, glm::value_ptr(value)); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform2fv(_id, location, 1, glm::value_ptr(value)); } void ProgramObject::setUniform(GLint location, const glm::vec3& value) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform3fv.isResolved()) { - glProgramUniform3fv(_id, location, 1, glm::value_ptr(value)); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform3fv(location, 1, glm::value_ptr(value)); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform3fv(_id, location, 1, glm::value_ptr(value)); } void ProgramObject::setUniform(GLint location, const glm::vec4& value) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform4fv.isResolved()) { - glProgramUniform4fv(_id, location, 1, glm::value_ptr(value)); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform4fv(location, 1, glm::value_ptr(value)); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform4fv(_id, location, 1, glm::value_ptr(value)); } void ProgramObject::setUniform(GLint location, const std::vector& values) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform1fv.isResolved()) { - glProgramUniform1fv( - _id, - location, - static_cast(values.size()), - values.data() - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform1fv(location, static_cast(values.size()), values.data()); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform1fv( + _id, + location, + static_cast(values.size()), + values.data() + ); } void ProgramObject::setUniform(GLint location, const std::vector& values) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform2fv.isResolved()) { - glProgramUniform2fv( - _id, - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform2fv( - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform2fv( + _id, + location, + static_cast(values.size()), + reinterpret_cast(values.data()) + ); } void ProgramObject::setUniform(GLint location, const std::vector& values) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform3fv.isResolved()) { - glProgramUniform3fv( - _id, - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform3fv( - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform3fv( + _id, + location, + static_cast(values.size()), + reinterpret_cast(values.data()) + ); } void ProgramObject::setUniform(GLint location, const std::vector& values) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform4fv.isResolved()) { - glProgramUniform4fv( - _id, - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform4fv( - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform4fv( + _id, + location, + static_cast(values.size()), + reinterpret_cast(values.data()) + ); } void ProgramObject::setUniform(GLint location, GLdouble value) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform1d.isResolved()) { - glProgramUniform1d(_id, location, value); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform1d(location, value); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform1d(_id, location, value); } void ProgramObject::setUniform(GLint location, GLdouble v1, GLdouble v2) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform2d.isResolved()) { - glProgramUniform2d(_id, location, v1, v2); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform2d(location, v1, v2); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform2d(_id, location, v1, v2); } void ProgramObject::setUniform(GLint location, GLdouble v1, GLdouble v2, GLdouble v3) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform3d.isResolved()) { - glProgramUniform3d(_id, location, v1, v2, v3); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform3d(location, v1, v2, v3); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform3d(_id, location, v1, v2, v3); } void ProgramObject::setUniform(GLint location, GLdouble v1, GLdouble v2, GLdouble v3, GLdouble v4) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform4d.isResolved()) { - glProgramUniform4d(_id, location, v1, v2, v3, v4); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform4d(location, v1, v2, v3, v4); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform4d(_id, location, v1, v2, v3, v4); } void ProgramObject::setUniform(GLint location, const glm::dvec2& value) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform2dv.isResolved()) { - glProgramUniform2dv(_id, location, 1, glm::value_ptr(value)); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform2dv(location, 1, glm::value_ptr(value)); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform2dv(_id, location, 1, glm::value_ptr(value)); } void ProgramObject::setUniform(GLint location, const glm::dvec3& value) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform3dv.isResolved()) { - glProgramUniform3dv(_id, location, 1, glm::value_ptr(value)); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform3dv(location, 1, glm::value_ptr(value)); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform3dv(_id, location, 1, glm::value_ptr(value)); } void ProgramObject::setUniform(GLint location, const glm::dvec4& value) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform4dv.isResolved()) { - glProgramUniform4dv(_id, location, 1, glm::value_ptr(value)); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform4dv(location, 1, glm::value_ptr(value)); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform4dv(_id, location, 1, glm::value_ptr(value)); } void ProgramObject::setUniform(GLint location, const std::vector& values) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform1dv.isResolved()) { - glProgramUniform1dv( - _id, - location, - static_cast(values.size()), - values.data() - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform1dv(location, static_cast(values.size()), values.data()); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform1dv( + _id, + location, + static_cast(values.size()), + values.data() + ); } void ProgramObject::setUniform(GLint location, const std::vector& values) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform2dv.isResolved()) { - glProgramUniform2dv( - _id, - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform2dv( - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform2dv( + _id, + location, + static_cast(values.size()), + reinterpret_cast(values.data()) + ); } void ProgramObject::setUniform(GLint location, const std::vector& values) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform3dv.isResolved()) { - glProgramUniform3dv( - _id, - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform3dv( - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform3dv( + _id, + location, + static_cast(values.size()), + reinterpret_cast(values.data()) + ); } void ProgramObject::setUniform(GLint location, const std::vector& values) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniform4dv.isResolved()) { - glProgramUniform4dv( - _id, - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniform4dv( - location, - static_cast(values.size()), - reinterpret_cast(values.data()) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniform4dv( + _id, + location, + static_cast(values.size()), + reinterpret_cast(values.data()) + ); } void ProgramObject::setUniform(GLint location, const glm::mat2x2& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix2fv.isResolved()) { - glProgramUniformMatrix2fv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix2fv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix2fv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::mat2x3& value, @@ -2102,476 +1587,226 @@ void ProgramObject::setUniform(GLint location, const glm::mat2x3& value, { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix2x3fv.isResolved()) { - glProgramUniformMatrix2x3fv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix2x3fv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix2x3fv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::mat2x4& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix2x4fv.isResolved()) { - glProgramUniformMatrix2x4fv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix2x4fv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix2x4fv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::mat3x2& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix3x2fv.isResolved()) { - glProgramUniformMatrix3x2fv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix3x2fv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix3x2fv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::mat3x3& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix3fv.isResolved()) { - glProgramUniformMatrix3fv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix3fv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix3fv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::mat3x4& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix3x4fv.isResolved()) { - glProgramUniformMatrix3x4fv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix3x4fv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix3x4fv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::mat4x2& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix4x2fv.isResolved()) { - glProgramUniformMatrix4x2fv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix4x2fv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix4x2fv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::mat4x3& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix4x3fv.isResolved()) { - glProgramUniformMatrix4x3fv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix4x3fv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix4x3fv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::mat4x4& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix4fv.isResolved()) { - glProgramUniformMatrix4fv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix4fv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix4fv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::dmat2x2& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix2dv.isResolved()) { - glProgramUniformMatrix2dv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix2dv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix2dv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::dmat2x3& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix2x3dv.isResolved()) { - glProgramUniformMatrix2x3dv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix2x3dv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix2x3dv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::dmat2x4& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix2x4dv.isResolved()) { - glProgramUniformMatrix2x4dv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix2x4dv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix2x4dv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::dmat3x2& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix3x2dv.isResolved()) { - glProgramUniformMatrix3x2dv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix3x2dv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix3x2dv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::dmat3x3& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix3dv.isResolved()) { - glProgramUniformMatrix3dv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix3dv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix3dv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::dmat3x4& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix3x4dv.isResolved()) { - glProgramUniformMatrix3x4dv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix3x4dv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix3x4dv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::dmat4x2& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix4x2dv.isResolved()) { - glProgramUniformMatrix4x2dv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix4x2dv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix4x2dv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::dmat4x3& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); - - if (glbinding::Binding::ProgramUniformMatrix4x3dv.isResolved()) { - glProgramUniformMatrix4x3dv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix4x3dv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } + glProgramUniformMatrix4x3dv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); } void ProgramObject::setUniform(GLint location, const glm::dmat4x4& value, Transpose transpose) const { ghoul_assert(location != -1, "Location must not be -1"); + glProgramUniformMatrix4dv( + _id, + location, + 1, + transpose ? GL_TRUE : GL_FALSE, + value_ptr(value) + ); +} - if (glbinding::Binding::ProgramUniformMatrix4dv.isResolved()) { - glProgramUniformMatrix4dv( - _id, - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - } - else { - GLint oldProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgram); - glUseProgram(_id); - glUniformMatrix4dv( - location, - 1, - transpose ? GL_TRUE : GL_FALSE, - value_ptr(value) - ); - glUseProgram(static_cast(oldProgram)); - } +void ProgramObject::setUniform(GLint location, const NewTexture& value) const { + ghoul_assert(location != -1, "Location must not be -1"); + glProgramUniformHandleui64ARB(_id, location, value); } bool ProgramObject::setSsboBinding(std::string_view name, GLuint binding) const { diff --git a/src/opengl/shaderobject.cpp b/src/opengl/shaderobject.cpp index 363b8232..37d27388 100755 --- a/src/opengl/shaderobject.cpp +++ b/src/opengl/shaderobject.cpp @@ -67,8 +67,7 @@ ShaderObject::ShaderObject(ShaderType shaderType, const std::filesystem::path& f throw ShaderObjectError("glCreateShader returned 0"); } -#ifdef GL_VERSION_4_3 - if (glbinding::Binding::ObjectLabel.isResolved() && !_shaderName.empty()) { + if (!_shaderName.empty()) { glObjectLabel( GL_SHADER, _id, @@ -76,7 +75,6 @@ ShaderObject::ShaderObject(ShaderType shaderType, const std::filesystem::path& f _shaderName.c_str() ); } -#endif // GL_VERSION_4_3 if (hasFilename) { rebuildFromFile(); @@ -94,8 +92,7 @@ ShaderObject::ShaderObject(const ShaderObject& cpy) if (_id == 0) { throw ShaderObjectError("glCreateShader returned 0"); } -#ifdef GL_VERSION_4_3 - if (glbinding::Binding::ObjectLabel.isResolved()) { + if (!_shaderName.empty()) { glObjectLabel( GL_SHADER, _id, @@ -103,7 +100,6 @@ ShaderObject::ShaderObject(const ShaderObject& cpy) _shaderName.c_str() ); } -#endif setShaderObjectCallback(_onChangeCallback); rebuildFromFile(); } @@ -142,8 +138,7 @@ ShaderObject& ShaderObject::operator=(const ShaderObject& rhs) { if (_id == 0) { throw ShaderObjectError("glCreateShader returned 0"); } -#ifdef GL_VERSION_4_3 - if (glbinding::Binding::ObjectLabel.isResolved()) { + if (!_shaderName.empty()) { glObjectLabel( GL_SHADER, _id, @@ -151,7 +146,6 @@ ShaderObject& ShaderObject::operator=(const ShaderObject& rhs) { _shaderName.c_str() ); } -#endif rebuildFromFile(); } return *this; @@ -175,16 +169,12 @@ ShaderObject& ShaderObject::operator=(ShaderObject&& rhs) noexcept { void ShaderObject::setName(std::string name) { _shaderName = std::move(name); _loggerCat = std::format("ShaderObject['{}']", _shaderName); -#ifdef GL_VERSION_4_3 - if (glbinding::Binding::ObjectLabel.isResolved()) { - glObjectLabel( - GL_SHADER, - _id, - GLsizei(_shaderName.length() + 1), - _shaderName.c_str() - ); - } -#endif + glObjectLabel( + GL_SHADER, + _id, + GLsizei(_shaderName.length() + 1), + _shaderName.c_str() + ); } const std::string& ShaderObject::name() const { From 63c1def71830f5c96f6bcc56634d80bcf46dc61c Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sun, 1 Feb 2026 01:25:58 +0100 Subject: [PATCH 02/15] Add new Direct-State-Access based Texture class --- include/ghoul/opengl/programobject.h | 27 ++ include/ghoul/opengl/texture.h | 286 ++++++++++++++++++++ src/opengl/programobject.cpp | 12 + src/opengl/texture.cpp | 376 +++++++++++++++++++++++++++ 4 files changed, 701 insertions(+) diff --git a/include/ghoul/opengl/programobject.h b/include/ghoul/opengl/programobject.h index 3a057747..4528217a 100755 --- a/include/ghoul/opengl/programobject.h +++ b/include/ghoul/opengl/programobject.h @@ -41,6 +41,8 @@ namespace ghoul::opengl { +class NewTexture; + /** * This class is a wrapper for an OpenGL program object storing an array of OpenGL * shaders. The usual restrictions for shader objects as described in the OpenGL and GLSL @@ -1286,6 +1288,19 @@ class ProgramObject { bool setUniform(const std::string& name, const glm::dmat4x4& value, Transpose transpose = Transpose::No) const; + /** + * Locates and sets the uniform(s) \p name with the passed value \p value. Returns + * `true` if the initial uniform could be found; `false` otherwise. Will call the + * OpenGL function `glProgramUniformHandleui64ARB`. + * + * \param name The name of the uniform in the ShaderObject%s + * \param value The value the uniform should be set to + * \return `true` if the initial uniform was successfully located, `false` otherwise + * + * \pre \p name must not be empty + */ + bool setUniform(const std::string& name, const NewTexture& value) const; + /** * Sets the uniform located at \p location with the passed \p value. Will call the * OpenGL function `glProgramUniform1ui`. @@ -2076,6 +2091,18 @@ class ProgramObject { void setUniform(GLint location, const glm::dmat4x4& value, Transpose transpose = Transpose::No) const; + /** + * Sets the uniform(s) located at \p location with the passed value \p value. Returns + * `true` if the initial uniform could be found; `false` otherwise. Will call the + * OpenGL function `glProgramUniformHandleui64ARB`. + * + * \param location The location of the uniform retrieved from #uniformLocation + * \param value The value the uniform should be set to + * + * \pre \p location must not be `-1` + */ + void setUniform(GLint location, const NewTexture& value) const; + ////////////////////////////////////////////////////////////////////////////////////// ////// SSBO Bindings diff --git a/include/ghoul/opengl/texture.h b/include/ghoul/opengl/texture.h index 87ca4d9b..782b9cb8 100755 --- a/include/ghoul/opengl/texture.h +++ b/include/ghoul/opengl/texture.h @@ -467,6 +467,7 @@ class Texture { * \param mipMapLevel The MipMap level that should be used in this texture. */ void setMipMapLevel(int mipMapLevel); + int mipMapLevel() const; /** * Sets the maximum anisotropy level that should be used. This is only valid when the @@ -834,6 +835,9 @@ class Texture { */ glm::vec4 texelAsFloat(const glm::uvec3& pos) const; + void setBorderColor(glm::vec4 borderColor); + glm::vec4 borderColor() const; + protected: /** * Initializes the Texture by determining the Texture type, the bytes per pixel, @@ -915,12 +919,294 @@ class Texture { void* _pixels = nullptr; int _pixelAlignment = 1; + glm::vec4 _borderColor; + #ifdef Debugging_Ghoul_Textures_Indices int index = 0; static int nextIndex; #endif // Debugging_Ghoul_Textures_Indices }; +class NewTexture { +public: + /** + * This enum specifies the allowed formats for the Texture%s. These are directly + * mapped to the appropriate OpenGL constants. + * + * \see http://www.opengl.org/sdk/docs/man/xhtml/glTexImage1D.xml + */ + enum class Format : std::underlying_type_t { + Red = static_cast>(GL_RED), + RG = static_cast>(GL_RG), + RGB = static_cast>(GL_RGB), + BGR = static_cast>(GL_BGR), + RGBA = static_cast>(GL_RGBA), + BGRA = static_cast>(GL_BGRA), + DepthComponent = static_cast>(GL_DEPTH_COMPONENT) + }; + + /** + * This enum specifies the filtering method this texture will use to interpolate + * between two texel. The values for this enum correspond directly to OpenGL settings. + * See the OpenGL specification for details. + */ + enum class FilterMode { + Nearest, ///< GL_NEAREST + Linear, ///< GL_LINEAR + LinearMipMap, ///< GL_LINEAR_MIPMAP_LINEAR + AnisotropicMipMap + }; + + /** + * This enum specifies the wrapping mode this texture will use at the edges of the + * texture. The values for this enum correspond directly to OpenGL settings. See the + * OpenGL specification for details. + */ + enum class WrappingMode : std::underlying_type_t { + Repeat = static_cast>(GL_REPEAT), + Clamp = static_cast>(GL_CLAMP), + ClampToEdge = static_cast>(GL_CLAMP_TO_EDGE), + ClampToBorder = static_cast>(GL_CLAMP_TO_BORDER), + MirroredRepeat = static_cast>(GL_MIRRORED_REPEAT) + }; + + /** + * Encapsulating the wrapping mode state for 1D, 2D, and 3D textures. 1D textures + * only use `s`, 2D textures use `s` and `t`, where as 3D textures use all three + * specified wrapping modes. + */ + struct WrappingModes { + WrappingMode s; + WrappingMode t = s; + WrappingMode r = t; + }; + + static int numberOfChannels(Format format); + + /** + * This constructor will create storage internally to fit the amount of data that is + * necessary for the \p dimensions `* bytesPerPixel` (which is in turn + * dependent on the \p dataType). The Texture can be 1D, 2D, or 3D depending on how + * many components are equal to `1`. + * + * \param dimensions The dimensions of the texture. A 3D texture will be created + * if all components are bigger than `1`, a 2D texture will be created if the + * `z` component is equal to `1`, while a 1D texture is created if the `y` and + * `z` component is equal to `1` + * \param type The type of the texture. Must be one of GL_TEXTURE_1D, GL_TEXTURE_2D, + * or GL_TEXTURE_3D + * \param format Specifies the format of the data + * \param internalFormat The internal format for the texture. See + * http://www.opengl.org/sdk/docs/man/xhtml/glTexImage1D.xml Tables 1, 2, and 3 + * for concrete values. In addition, the S3TC_DXT formats can be used to + * support hardware compression. See + * http://www.opengl.org/wiki/Image_Format#S3TC.2FDXT for more information + * \param dataType The data type of the pixel data. See + * http://www.opengl.org/sdk/docs/man/xhtml/glTexImage1D.xml for a list of + * possible values + * \param filter The Texture::FilterMode that will be used to interpolate between + * texels + * \param wrapping The Texture::WrappingMode that will be used to generate values on + * the border of the texture + * + * \pre Element of \p dimensions must be bigger or equal `1` + */ + NewTexture(glm::uvec3 dimensions, GLenum type, Format format = Format::RGBA, + GLenum internalFormat = GL_RGBA, GLenum dataType = GL_UNSIGNED_BYTE, + FilterMode filter = FilterMode::Linear, + WrappingModes wrapping = { WrappingMode::Repeat }, + std::array swizzleMask = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }, + int mipMapLevel = 8, glm::vec4 borderColor = glm::vec4(0.f, 0.f, 0.f, 1.f)); + + /** + * This constructor will generate a Texture out of the passed data. The data should + * contain enough bytes to fill `dimensions * bytesPerPixel` (which is in + * turn dependent on the dataType) pixel. The Texture can be 1D, 2D, or 3D depending + * on how many components are equal to `1`. + * + * \param data The data from which to generate the Texture. The data must be in a + * linear format and (in 2D and 3D cases) aligned so that it can be accessed + * using the following equations: `(y * dimensions.x) + x` in the 2D case and + * `(z * dimensions.x * dimensions.y) + (y * dimensions.x) + x` in the 3D case. + * \param dimensions The dimensions of the texture. A 3D texture will be created if + * all components are bigger than `1`, a 2D texture will be created if the `z` + * component is equal to `1`, while a 1D texture is created if the `y` and `z` + * component is equal to `1` + * \param type The type of the texture. Must be one of GL_TEXTURE_1D, GL_TEXTURE_2D, + * or GL_TEXTURE_3D + * \param format Specifies the format of the data + * \param internalFormat The internal format for the texture. See + * http://www.opengl.org/sdk/docs/man/xhtml/glTexImage1D.xml Tables 1,2, and 3 + * for concrete values. In addition, the S3TC_DXT formats can be used to + * support hardware compression. + * See http://www.opengl.org/wiki/Image_Format#S3TC.2FDXT for more information + * \param dataType The data type of the pixel data. See + * http://www.opengl.org/sdk/docs/man/xhtml/glTexImage1D.xml for a list of + * possible values + * \param filter The Texture::FilterMode that will be used to interpolate between + * texels + * \param wrapping The Texture::WrappingMode that will be used to generate values on + * the border of the texture + * \param pixelAlignment The byte-alignment for each of the pixels in the provided + * \p data array + */ + NewTexture(const void* data, glm::uvec3 dimensions, GLenum type, Format format = Format::RGBA, + GLenum internalFormat = GL_RGBA, GLenum dataType = GL_UNSIGNED_BYTE, + FilterMode filter = FilterMode::Linear, + WrappingModes wrapping = { WrappingMode::Repeat }, int pixelAlignment = 1, + std::array swizzleMask = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }, + int mipMapLevel = 8, glm::vec4 borderColor = glm::vec4(0.f, 0.f, 0.f, 1.f)); + + explicit NewTexture(const Texture& texture); + + /** + * Unloads the Texture from GPU memory and destroys the id. The destructor will also + * remove the data associated with this texture. + */ + ~NewTexture(); + + /** + * Resizes the textures to the new size. If the new size is different from the + * previous size, the contents of the texture are erased and if the Texture class + * owned the RAM pixel data, it is erased. + * + * \param dimensions The new size of the texture + */ + //void resize(glm::uvec3 dimensions); + + void makeResident(); + void makeUnresident(); + + /** + * Returns `true` if the OpenGL texture is resident in the GPU memory. + * + * \return `true` if the OpenGL texture is resident + */ + bool isResident() const; + + /** + * Returns the OpenGL handle of this texture. + */ + operator GLuint64() const; + + /** + * Returns the OpenGL name of this texture. + */ + operator GLuint() const; + + /** + * Returns the type for this texture. + * + * \return The type for this texture. This value can either be `GL_TEXTURE_1D`, + * `GL_TEXTURE_2D` or `GL_TEXTURE_3D` depending on the dimension of the stored + * texture. + */ + GLenum type() const; + + /** + * Returns the dimensions of this texture. If the texture is a 2D texture, the `z` + * component will be equal to `1` and if the texture is a 1D texture, the `y` and `z` + * components will be equal to `1`. + * + * \return The dimensions of this texture + */ + const glm::uvec3& dimensions() const; + + /** + * Returns the format for this texture. + * + * \return The format for this texture + */ + Format format() const; + + /** + * Returns the internal format for this texture. See + * http://www.opengl.org/sdk/docs/man/xhtml/glTexImage1D.xml for more information and + * the possible return values. + */ + GLenum internalFormat() const; + + /** + * Returns the Texture::FilterMode used by this texture. + * + * \return The Texture::FilterMode used by this texture + */ + FilterMode filter() const; + + /** + * Returns the currently used swizzle mask for this Texture. + * + * \return The currently used swizzle mask for this Texture + */ + std::array swizzleMask() const; + + /** + * Returns the storage data type for this Texture. For a complete list of available + * return values see http://www.opengl.org/sdk/docs/man/xhtml/glTexImage1D.xml for + * more information. + * + * \return The storage data type + */ + GLenum dataType() const; + + /** + * Returns the number of channels that are stored in this texture. If the format of + * the Texture is not in the list of formats found at + * http://www.opengl.org/sdk/docs/man/xhtml/glTexImage1D.xml, an assertion will be + * triggered. + * + * \return The number of channels that are stored in this texture + */ + int numberOfChannels() const; + + /* + * Returns the number of bytes each pixel stores. + * + * \return The number of bytes each pixel stores + */ + GLubyte bytesPerPixel() const; + + /** + * Returns the currently used Texture::WrappingMode for this texture. + * + * \return The currently used Texture::WrappingMode for this texture + */ + WrappingModes wrapping() const; + + /** + * Sets new data for the texture to use. If the dimensions are not updated and the new + * data has a different size, undefined behavior will occur. This Texture will take + * ownership of the data array. + * + * \param pixels The pointer to the new data array that should be used. + * \param takeOwnership Should this Texture take ownership of the data and delete it? + * \param pixelAlignment The byte-alignment for each of the pixels in the provided + * \p pixels array + */ + void uploadDataToTexture(const void* pixelData, int pixelAlignment = 1) const; + +private: + GLuint _id = 0; + GLuint64 _handle = 0; + glm::uvec3 _dimensions = glm::uvec3(0); + Format _format; + GLenum _internalFormat; + std::array _swizzleMask; + GLenum _dataType; + FilterMode _filter; + WrappingModes _wrapping; + GLenum _type; + int _mipMapLevel = 8; + float _anisotropyLevel = -1.f; + +#ifdef Debugging_Ghoul_Textures_Indices + int index = 0; + static int nextIndex; +#endif // Debugging_Ghoul_Textures_Indices +}; + + + } // namespace ghoul::opengl #include "texture.inl" diff --git a/src/opengl/programobject.cpp b/src/opengl/programobject.cpp index 4a64589d..32c26ae9 100755 --- a/src/opengl/programobject.cpp +++ b/src/opengl/programobject.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include #include @@ -1237,6 +1238,17 @@ bool ProgramObject::setUniform(const std::string& name, const glm::dmat4x4& valu return true; } +bool ProgramObject::setUniform(const std::string& name, const NewTexture& value) const { + ghoul_assert(!name.empty(), "Name must not be empty"); + + const GLint location = uniformLocation(name); + if (location == -1) { + return false; + } + setUniform(location, value); + return true; +} + void ProgramObject::setUniform(GLint location, GLuint value) const { ghoul_assert(location != -1, "Location must not be -1"); glProgramUniform1ui(_id, location, value); diff --git a/src/opengl/texture.cpp b/src/opengl/texture.cpp index 01d0e309..7cdecb32 100755 --- a/src/opengl/texture.cpp +++ b/src/opengl/texture.cpp @@ -367,6 +367,10 @@ void Texture::setMipMapLevel(int mipMapLevel) { applyFilter(); } +int Texture::mipMapLevel() const { + return _mipMapLevel; +} + void Texture::applyWrapping() const { ZoneScoped; @@ -1372,6 +1376,18 @@ glm::vec4 Texture::texelAsFloat(const glm::uvec3& pos) const { return texelAsFloat(pos.x, pos.y, pos.z); } + +void Texture::setBorderColor(glm::vec4 borderColor) { + _borderColor = std::move(borderColor); + + bind(); + glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, glm::value_ptr(_borderColor)); +} + +glm::vec4 Texture::borderColor() const { + return _borderColor; +} + void Texture::calculateBytesPerPixel() { const size_t numChannels = numberOfChannels(); int szType = 0; @@ -1408,4 +1424,364 @@ void Texture::calculateBytesPerPixel() { _bpp = static_cast(szType * numChannels); } + +#ifdef Debugging_Ghoul_Textures_Indices +int NewTexture::nextIndex = 0; +#endif // Debugging_Ghoul_Textures_Indices + +int NewTexture::numberOfChannels(Format format) { + switch (format) { + case Format::Red: + case Format::DepthComponent: + return 1; + case Format::RG: + return 2; + case Format::RGB: + case Format::BGR: + return 3; + case Format::RGBA: + case Format::BGRA: + return 4; + } + return 0; +} + +NewTexture::NewTexture(glm::uvec3 dimensions, GLenum type, Format format, GLenum internalFormat, + GLenum dataType, FilterMode filter, WrappingModes wrapping, + std::array swizzleMask, int mipMapLevel, glm::vec4 borderColor) + : _dimensions(std::move(dimensions)) + , _format(format) + , _internalFormat(internalFormat) + , _swizzleMask(std::move(swizzleMask)) + , _dataType(dataType) + , _filter(filter) + , _wrapping(wrapping) + , _type(type) + , _mipMapLevel(mipMapLevel) +{ +#ifdef Debugging_Ghoul_Textures_Indices + index = nextIndex++; +#endif // Debugging_Ghoul_Textures_Indices + + ghoul_assert(_dimensions.x >= 1, "Element of dimensions must be bigger or equal 1"); + ghoul_assert(_dimensions.y >= 1, "Element of dimensions must be bigger or equal 1"); + ghoul_assert(_dimensions.z >= 1, "Element of dimensions must be bigger or equal 1"); + ghoul_assert( + _type == GL_TEXTURE_1D || _type == GL_TEXTURE_2D || _type == GL_TEXTURE_3D, + "Type must be one of GL_TEXTURE_1D, GL_TEXTURE_2D, or GL_TEXTURE_3D" + ); + + glCreateTextures(_type, 1, &_id); + + // Apply filter + switch (_filter) { + case FilterMode::Nearest: + glTextureParameteri(_id, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTextureParameteri(_id, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + break; + case FilterMode::Linear: + glTextureParameteri(_id, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTextureParameteri(_id, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + break; + case FilterMode::LinearMipMap: + glGenerateTextureMipmap(_id); + glTextureParameteri(_id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTextureParameteri(_id, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTextureParameteri(_id, GL_TEXTURE_MAX_LEVEL, _mipMapLevel - 1); + break; + case FilterMode::AnisotropicMipMap: + glGenerateTextureMipmap(_id); + glTextureParameteri(_id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTextureParameteri(_id, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTextureParameteri(_id, GL_TEXTURE_MAX_LEVEL, _mipMapLevel - 1); + if (std::equal_to<>()(_anisotropyLevel, -1.f)) { + GLfloat maxTextureAnisotropy = 1.0; + glGetFloatv( + GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, + &maxTextureAnisotropy + ); + _anisotropyLevel = maxTextureAnisotropy; + } + glTextureParameterf(_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, _anisotropyLevel); + glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, 0); + break; + } + + // Apply wrap + switch (_type) { + case GL_TEXTURE_3D: + glTextureParameteri(_id, GL_TEXTURE_WRAP_R, static_cast(_wrapping.r)); + [[fallthrough]]; + case GL_TEXTURE_2D: + glTextureParameteri(_id, GL_TEXTURE_WRAP_T, static_cast(_wrapping.t)); + [[fallthrough]]; + case GL_TEXTURE_1D: + glTextureParameteri(_id, GL_TEXTURE_WRAP_S, static_cast(_wrapping.s)); + break; + default: + throw MissingCaseException(); + } + + // Apply swizzle + glTextureParameteriv(_id, GL_TEXTURE_SWIZZLE_RGBA, _swizzleMask.data()); + + // Apply border color + // @TODO Check since DSA textures have limitations on which are allowed + glTextureParameterfv(_id, GL_TEXTURE_BORDER_COLOR, glm::value_ptr(borderColor)); + + switch (_type) { + case GL_TEXTURE_1D: + glTextureStorage1D(_id, 1, _internalFormat, _dimensions.x); + break; + case GL_TEXTURE_2D: + glTextureStorage2D(_id, 1, _internalFormat, _dimensions.x, _dimensions.y); + break; + case GL_TEXTURE_3D: + glTextureStorage3D(_id, 1, _internalFormat, _dimensions.x, _dimensions.y, _dimensions.z); + break; + default: + throw MissingCaseException(); + } + + _handle = glGetTextureHandleARB(_id); +} + +NewTexture::NewTexture(const void* data, glm::uvec3 dimensions, GLenum type, Format format, GLenum internalFormat, + GLenum dataType, FilterMode filter, WrappingModes wrapping, int pixelAlignment, + std::array swizzleMask, int mipMapLevel, glm::vec4 borderColor) + : NewTexture(dimensions, type, format, internalFormat, dataType, filter, wrapping, swizzleMask, mipMapLevel, borderColor) +{ + uploadDataToTexture(data, pixelAlignment); +} + +static GLenum internalFormatToSized(GLenum internalFormat, GLenum dataType) { + switch (internalFormat) { + case GL_RED: + switch (dataType) { + case GL_UNSIGNED_BYTE: + return GL_R8; + case GL_BYTE: + return GL_R8; + case GL_UNSIGNED_SHORT: + return GL_R16UI; + case GL_SHORT: + return GL_R16I; + case GL_UNSIGNED_INT: + return GL_R16UI; + case GL_INT: + return GL_R16I; + case GL_FLOAT: + return GL_R32F; + default: + throw MissingCaseException(); + } + case GL_RG: + switch (dataType) { + case GL_UNSIGNED_BYTE: + return GL_RG8; + case GL_BYTE: + return GL_RG8; + case GL_UNSIGNED_SHORT: + return GL_RG16UI; + case GL_SHORT: + return GL_RG16I; + case GL_UNSIGNED_INT: + return GL_RG16UI; + case GL_INT: + return GL_RG16I; + case GL_FLOAT: + return GL_RG32F; + default: + throw MissingCaseException(); + } + case GL_RGB: + switch (dataType) { + case GL_UNSIGNED_BYTE: + return GL_RGB8; + case GL_BYTE: + return GL_RGB8; + case GL_UNSIGNED_BYTE_3_3_2: + return GL_R3_G3_B2; + case GL_UNSIGNED_SHORT: + return GL_RGB16UI; + case GL_SHORT: + return GL_RGB16I; + case GL_UNSIGNED_INT: + return GL_RGB16UI; + case GL_INT: + return GL_RGB16I; + case GL_FLOAT: + return GL_RGB32F; + default: + throw MissingCaseException(); + } + case GL_RGBA: + switch (dataType) { + case GL_UNSIGNED_BYTE: + return GL_RGBA8; + case GL_BYTE: + return GL_RGBA8; + case GL_UNSIGNED_SHORT: + return GL_RGBA16UI; + case GL_SHORT: + return GL_RGBA16I; + case GL_UNSIGNED_INT: + return GL_RGBA16UI; + case GL_INT: + return GL_RGBA16I; + case GL_FLOAT: + return GL_RGBA32F; + default: + throw MissingCaseException(); + } + default: + throw MissingCaseException(); + } +} + +NewTexture::NewTexture(const Texture& texture) + : NewTexture( + texture.pixelData(), + texture.dimensions(), + texture.type(), + Format(texture.format()), + internalFormatToSized(texture.internalFormat(), texture.dataType()), + texture.dataType(), + FilterMode(texture.filter()), + { + WrappingMode(texture.wrapping().s), + WrappingMode(texture.wrapping().t), + WrappingMode(texture.wrapping().r) + + }, + 1, + texture.swizzleMask(), + texture.mipMapLevel(), + texture.borderColor() + ) +{} + +NewTexture::~NewTexture() { + makeUnresident(); + glDeleteTextures(1, &_id); +} + +//void NewTexture::resize(glm::uvec3 dimensions) { +// if (dimensions == _dimensions) { +// return; +// } +// +// +//} + +void NewTexture::makeResident() { + glMakeTextureHandleResidentARB(_handle); +} + +void NewTexture::makeUnresident() { + glMakeTextureHandleNonResidentARB(_handle); +} + +bool NewTexture::isResident() const { + return glIsTextureHandleResidentARB(_handle) == GL_TRUE; +} + +NewTexture::operator GLuint64() const { + return _handle; +} + +NewTexture::operator GLuint() const { + return _id; +} + +GLenum NewTexture::type() const { + return _type; +} + +const glm::uvec3& NewTexture::dimensions() const { + return _dimensions; +} + +NewTexture::Format NewTexture::format() const { + return _format; +} + +GLenum NewTexture::internalFormat() const { + return _internalFormat; +} + +NewTexture::FilterMode NewTexture::filter() const { + return _filter; +} + +std::array NewTexture::swizzleMask() const { + return _swizzleMask; +} + +GLenum NewTexture::dataType() const { + return _dataType; +} + +int NewTexture::numberOfChannels() const { + return numberOfChannels(_format); +} + +GLubyte NewTexture::bytesPerPixel() const { + const size_t numChannels = numberOfChannels(); + int szType = 0; + switch (_dataType) { + case GL_UNSIGNED_BYTE: + case GL_BYTE: + case GL_UNSIGNED_BYTE_3_3_2: + case GL_UNSIGNED_BYTE_2_3_3_REV: + szType = 1; + break; + case GL_UNSIGNED_SHORT: + case GL_SHORT: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_4_4_4_4_REV: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + szType = 2; + break; + case GL_UNSIGNED_INT: + case GL_INT: + case GL_FLOAT: + case GL_UNSIGNED_INT_8_8_8_8: + case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_10_10_10_2: + case GL_UNSIGNED_INT_2_10_10_10_REV: + szType = 4; + break; + default: + throw MissingCaseException(); + } + + return static_cast(szType * numChannels); +} + +NewTexture::WrappingModes NewTexture::wrapping() const { + return _wrapping; +} + +void NewTexture::uploadDataToTexture(const void* pixelData, int pixelAlignment) const { + glPixelStorei(GL_UNPACK_ALIGNMENT, pixelAlignment); + + switch (_type) { + case GL_TEXTURE_1D: + glTextureSubImage1D(_id, 0, 0, _dimensions.x, GLenum(_format), _dataType, pixelData); + break; + case GL_TEXTURE_2D: + glTextureSubImage2D(_id, 0, 0, 0, _dimensions.x, _dimensions.y, GLenum(_format), _dataType, pixelData); + break; + case GL_TEXTURE_3D: + glTextureSubImage3D(_id, 0, 0, 0, 0, _dimensions.x, _dimensions.y, _dimensions.z, GLenum(_format), _dataType, pixelData); + break; + default: + throw MissingCaseException(); + } +} + } // namespace ghoul::opengl From 886f2f07306a5ba195640a2cd2b61336f54c3ed0 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sun, 1 Feb 2026 20:12:00 +0100 Subject: [PATCH 03/15] Use DSA functions for Framebuffers --- src/opengl/framebufferobject.cpp | 37 +++++--------------------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/src/opengl/framebufferobject.cpp b/src/opengl/framebufferobject.cpp index 00635928..510fe2df 100755 --- a/src/opengl/framebufferobject.cpp +++ b/src/opengl/framebufferobject.cpp @@ -92,42 +92,15 @@ void FramebufferObject::attachTexture(Texture* texture, GLenum attachment, int m { switch (texture->type()) { case GL_TEXTURE_1D: - glFramebufferTexture1D( - GL_FRAMEBUFFER, - attachment, - GL_TEXTURE_1D, - *texture, - mipLevel - ); - break; case GL_TEXTURE_2D: case GL_TEXTURE_RECTANGLE: - glFramebufferTexture2D( - GL_FRAMEBUFFER, - attachment, - texture->type(), - *texture, - mipLevel - ); + glNamedFramebufferTexture(_id, attachment, *texture, mipLevel); break; case GL_TEXTURE_3D: - glFramebufferTexture3D( - GL_FRAMEBUFFER, - attachment, - GL_TEXTURE_3D, - *texture, - mipLevel, - zSlice - ); + glNamedFramebufferTextureLayer(_id, attachment, *texture, mipLevel, zSlice); break; case GL_TEXTURE_2D_ARRAY: - glFramebufferTextureLayer( - GL_FRAMEBUFFER, - attachment, - *texture, - mipLevel, - zSlice - ); + glNamedFramebufferTextureLayer(_id, attachment, *texture, mipLevel, zSlice); break; default: LERROR("Unknown texture type"); @@ -145,7 +118,7 @@ void FramebufferObject::detachTexture(GLenum attachment) { LWARNING("Trying to detach unknown texture"); } - glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, 0, 0); + glNamedFramebufferTexture(_id, attachment, 0, 0); } void FramebufferObject::detachAll() { @@ -166,7 +139,7 @@ GLuint FramebufferObject::getActiveObject() { } GLuint FramebufferObject::generateId() { - glGenFramebuffers(1, &_id); + glCreateFramebuffers(1, &_id); return _id; } From 89224970241b09c427e508f19a9e6f6991936fc0 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 2 Feb 2026 00:30:03 +0100 Subject: [PATCH 04/15] Use DSA function for glBufferData and glGenX -> glCreateX --- include/ghoul/opengl/vertexbufferobject.h | 6 --- include/ghoul/opengl/vertexbufferobject.inl | 12 +++--- src/font/fontrenderer.cpp | 43 +++++++++------------ src/io/model/modelmesh.cpp | 17 ++++---- src/opengl/texture.cpp | 2 +- src/opengl/vertexbufferobject.cpp | 21 ++++------ 6 files changed, 44 insertions(+), 57 deletions(-) diff --git a/include/ghoul/opengl/vertexbufferobject.h b/include/ghoul/opengl/vertexbufferobject.h index 9b3ed471..de01fd85 100644 --- a/include/ghoul/opengl/vertexbufferobject.h +++ b/include/ghoul/opengl/vertexbufferobject.h @@ -140,12 +140,6 @@ class VertexBufferObject { void render() const; private: - /** - * Constructs the internal GL objects by calling `glGenVertexArrays` and - * `glGenBuffers`. - */ - void generateGLObjects(); - /// The vertex array object that stores the created VertexBufferObject GLuint _vaoID = 0; diff --git a/include/ghoul/opengl/vertexbufferobject.inl b/include/ghoul/opengl/vertexbufferobject.inl index 1029341e..892c5c0e 100644 --- a/include/ghoul/opengl/vertexbufferobject.inl +++ b/include/ghoul/opengl/vertexbufferobject.inl @@ -38,23 +38,25 @@ void VertexBufferObject::initialize(const std::vector& vertexArray, ghoul_assert(!vertexArray.empty(), "Vertex array must not be empty"); ghoul_assert(!indexArray.empty(), "Index array must not be empty"); - generateGLObjects(); _iSize = static_cast(indexArray.size()); + glCreateVertexArrays(1, &_vaoID); glBindVertexArray(_vaoID); + glCreateBuffers(1, &_vBufferID); glBindBuffer(GL_ARRAY_BUFFER, _vBufferID); - glBufferData( - GL_ARRAY_BUFFER, + glNamedBufferData( + _vBufferID, vertexArray.size() * sizeof(T), vertexArray.data(), GL_STATIC_DRAW ); + glCreateBuffers(1, &_iBufferID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID); - glBufferData( - GL_ELEMENT_ARRAY_BUFFER, + glNamedBufferData( + _iBufferID, indexArray.size() * sizeof(GLint), indexArray.data(), GL_STATIC_DRAW diff --git a/src/font/fontrenderer.cpp b/src/font/fontrenderer.cpp index c65f1ebc..40387909 100644 --- a/src/font/fontrenderer.cpp +++ b/src/font/fontrenderer.cpp @@ -206,12 +206,12 @@ FontRenderer::FontRenderer(std::unique_ptr program, { ghoul_assert(_program, "No program provided"); - // + // // Configure the OpenGL objects for the orthogonal font rendering - glGenVertexArrays(1, &_orthogonal.vao); + glCreateVertexArrays(1, &_orthogonal.vao); glBindVertexArray(_orthogonal.vao); - glGenBuffers(1, &_orthogonal.vbo); + glCreateBuffers(1, &_orthogonal.vbo); glBindBuffer(GL_ARRAY_BUFFER, _orthogonal.vbo); struct OrthogonalVertex { @@ -246,16 +246,16 @@ FontRenderer::FontRenderer(std::unique_ptr program, reinterpret_cast(offsetof(OrthogonalVertex, outlineS)) ); - glGenBuffers(1, &_orthogonal.ibo); + glCreateBuffers(1, &_orthogonal.ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _orthogonal.ibo); // // Configure the OpenGL objects for the projective font rendering - glGenVertexArrays(1, &_perspective.vao); + glCreateVertexArrays(1, &_perspective.vao); glBindVertexArray(_perspective.vao); - glGenBuffers(1, &_perspective.vbo); + glCreateBuffers(1, &_perspective.vbo); glBindBuffer(GL_ARRAY_BUFFER, _perspective.vbo); struct PerspectiveVertex { @@ -291,7 +291,7 @@ FontRenderer::FontRenderer(std::unique_ptr program, reinterpret_cast(offsetof(PerspectiveVertex, outlineS)) ); - glGenBuffers(1, &_perspective.ibo); + glCreateBuffers(1, &_perspective.ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _perspective.ibo); glBindVertexArray(0); @@ -524,32 +524,29 @@ FontRenderer::BoundingBoxInformation FontRenderer::render(Font& font, glm::ortho(0.f, _framebufferSize.x, 0.f, _framebufferSize.y) ); - glBindVertexArray(_orthogonal.vao); - - glBindBuffer(GL_ARRAY_BUFFER, _orthogonal.vbo); - glBufferData( - GL_ARRAY_BUFFER, + glNamedBufferData( + _orthogonal.vbo, _vertexBuffer.size() * sizeof(float), _vertexBuffer.data(), GL_DYNAMIC_DRAW ); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _orthogonal.ibo); - glBufferData( - GL_ELEMENT_ARRAY_BUFFER, + glNamedBufferData( + _orthogonal.ibo, _indexBuffer.size() * sizeof(GLushort), _indexBuffer.data(), GL_DYNAMIC_DRAW ); + glBindVertexArray(_orthogonal.vao); glDrawElements( GL_TRIANGLES, static_cast(_indexBuffer.size()), GL_UNSIGNED_SHORT, nullptr ); - glBindVertexArray(0); + glEnable(GL_DEPTH_TEST); return { size, static_cast(lines) }; @@ -744,32 +741,30 @@ FontRenderer::BoundingBoxInformation FontRenderer::render(Font& font, labelInfo.disableTransmittance ); - glBindVertexArray(_perspective.vao); - glBindBuffer(GL_ARRAY_BUFFER, _perspective.vbo); - glBufferData( - GL_ARRAY_BUFFER, + glNamedBufferData( + _perspective.vbo, _vertexBuffer.size() * sizeof(float), _vertexBuffer.data(), GL_DYNAMIC_DRAW ); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _perspective.ibo); - glBufferData( - GL_ELEMENT_ARRAY_BUFFER, + glNamedBufferData( + _perspective.ibo, _indexBuffer.size() * sizeof(GLushort), _indexBuffer.data(), GL_DYNAMIC_DRAW ); + glBindVertexArray(_perspective.vao); glDrawElements( GL_TRIANGLES, static_cast(_indexBuffer.size()), GL_UNSIGNED_SHORT, nullptr ); - glBindVertexArray(0); + if (!labelInfo.enableDepth) { glEnable(GL_DEPTH_TEST); } diff --git a/src/io/model/modelmesh.cpp b/src/io/model/modelmesh.cpp index 653beff3..212ce439 100644 --- a/src/io/model/modelmesh.cpp +++ b/src/io/model/modelmesh.cpp @@ -258,27 +258,28 @@ void ModelMesh::initialize() { return; } - glGenVertexArrays(1, &_vaoID); - glGenBuffers(1, &_vbo); - glGenBuffers(1, &_ibo); - + glCreateVertexArrays(1, &_vaoID); glBindVertexArray(_vaoID); + + glCreateBuffers(1, &_vbo); glBindBuffer(GL_ARRAY_BUFFER, _vbo); - glBufferData( - GL_ARRAY_BUFFER, + glNamedBufferData( + _vbo, _vertices.size() * sizeof(Vertex), _vertices.data(), GL_STATIC_DRAW ); + glCreateBuffers(1, &_ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo); - glBufferData( - GL_ELEMENT_ARRAY_BUFFER, + glNamedBufferData( + _ibo, _indices.size() * sizeof(unsigned int), _indices.data(), GL_STATIC_DRAW ); + // Set vertex attributes pointers // Vertex position glEnableVertexAttribArray(0); diff --git a/src/opengl/texture.cpp b/src/opengl/texture.cpp index 7cdecb32..6a1d9cdb 100755 --- a/src/opengl/texture.cpp +++ b/src/opengl/texture.cpp @@ -141,7 +141,7 @@ void Texture::generateId() { ZoneScoped; _id = 0; - glGenTextures(1, &_id); + glCreateTextures(_type, 1, &_id); } void Texture::enable() const { diff --git a/src/opengl/vertexbufferobject.cpp b/src/opengl/vertexbufferobject.cpp index 050597ee..b51e95a7 100644 --- a/src/opengl/vertexbufferobject.cpp +++ b/src/opengl/vertexbufferobject.cpp @@ -72,23 +72,24 @@ void VertexBufferObject::initialize(const std::vector& vertexArray, ghoul_assert(!vertexArray.empty(), "Vertex array must not be empty"); ghoul_assert(!indexArray.empty(), "Index array must not be empty"); - generateGLObjects(); + glCreateVertexArrays(1, &_vaoID); + glBindVertexArray(_vaoID); _iSize = static_cast(indexArray.size()); - glBindVertexArray(_vaoID); - + glCreateBuffers(1, &_vBufferID); glBindBuffer(GL_ARRAY_BUFFER, _vBufferID); - glBufferData( - GL_ARRAY_BUFFER, + glNamedBufferData( + _vBufferID, vertexArray.size() * sizeof(GLfloat), vertexArray.data(), GL_STATIC_DRAW ); + glCreateBuffers(1, &_iBufferID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID); - glBufferData( - GL_ELEMENT_ARRAY_BUFFER, + glNamedBufferData( + _iBufferID, indexArray.size() * sizeof(GLint), indexArray.data(), GL_STATIC_DRAW @@ -134,10 +135,4 @@ void VertexBufferObject::render() const { glBindVertexArray(0); } -void VertexBufferObject::generateGLObjects() { - glGenVertexArrays(1, &_vaoID); - glGenBuffers(1, &_vBufferID); - glGenBuffers(1, &_iBufferID); -} - } // namespace ghoul::opengl From 61b510a5e1b6c51bb3b28f05cc8c02e477c720ac Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 2 Feb 2026 01:05:55 +0100 Subject: [PATCH 05/15] Move old texture class to DSA functions --- src/opengl/texture.cpp | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/src/opengl/texture.cpp b/src/opengl/texture.cpp index 6a1d9cdb..98d60729 100755 --- a/src/opengl/texture.cpp +++ b/src/opengl/texture.cpp @@ -236,28 +236,26 @@ std::array Texture::swizzleMask() const { void Texture::applyFilter() { ZoneScoped; - bind(); - switch (_filter) { case FilterMode::Nearest: - glTexParameteri(_type, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(_type, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTextureParameteri(_id, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTextureParameteri(_id, GL_TEXTURE_MAG_FILTER, GL_NEAREST); break; case FilterMode::Linear: - glTexParameteri(_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTextureParameteri(_id, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTextureParameteri(_id, GL_TEXTURE_MAG_FILTER, GL_LINEAR); break; case FilterMode::LinearMipMap: - glGenerateMipmap(_type); - glTexParameteri(_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(_type, GL_TEXTURE_MAX_LEVEL, _mipMapLevel - 1); + glGenerateTextureMipmap(_id); + glTextureParameteri(_id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTextureParameteri(_id, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTextureParameteri(_id, GL_TEXTURE_MAX_LEVEL, _mipMapLevel - 1); break; case FilterMode::AnisotropicMipMap: - glGenerateMipmap(_type); - glTexParameteri(_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(_type, GL_TEXTURE_MAX_LEVEL, _mipMapLevel - 1); + glGenerateTextureMipmap(_id); + glTextureParameteri(_id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTextureParameteri(_id, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTextureParameteri(_id, GL_TEXTURE_MAX_LEVEL, _mipMapLevel - 1); if (std::equal_to<>()(_anisotropyLevel, -1.f)) { GLfloat maxTextureAnisotropy = 1.0; glGetFloatv( @@ -266,8 +264,8 @@ void Texture::applyFilter() { ); _anisotropyLevel = maxTextureAnisotropy; } - glTexParameterf(_type, GL_TEXTURE_MAX_ANISOTROPY_EXT, _anisotropyLevel); - glTexParameteri(_type, GL_TEXTURE_BASE_LEVEL, 0); + glTextureParameterf(_id, GL_TEXTURE_MAX_ANISOTROPY_EXT, _anisotropyLevel); + glTextureParameteri(_id, GL_TEXTURE_BASE_LEVEL, 0); break; } } @@ -374,17 +372,15 @@ int Texture::mipMapLevel() const { void Texture::applyWrapping() const { ZoneScoped; - bind(); - switch (_type) { case GL_TEXTURE_3D: - glTexParameteri(_type, GL_TEXTURE_WRAP_R, static_cast(_wrapping.r)); + glTextureParameteri(_id, GL_TEXTURE_WRAP_R, static_cast(_wrapping.r)); [[fallthrough]]; case GL_TEXTURE_2D: - glTexParameteri(_type, GL_TEXTURE_WRAP_T, static_cast(_wrapping.t)); + glTextureParameteri(_id, GL_TEXTURE_WRAP_T, static_cast(_wrapping.t)); [[fallthrough]]; case GL_TEXTURE_1D: - glTexParameteri(_type, GL_TEXTURE_WRAP_S, static_cast(_wrapping.s)); + glTextureParameteri(_id, GL_TEXTURE_WRAP_S, static_cast(_wrapping.s)); break; default: throw MissingCaseException(); @@ -393,8 +389,7 @@ void Texture::applyWrapping() const { void Texture::applySwizzleMask() { if (_swizzleMaskChanged) { - bind(); - glTexParameteriv(_type, GL_TEXTURE_SWIZZLE_RGBA, _swizzleMask.data()); + glTextureParameteriv(_id, GL_TEXTURE_SWIZZLE_RGBA, _swizzleMask.data()); } } From 6fbda63cfa1fae54c9a82f79c64b006529aed36b Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Mon, 2 Feb 2026 17:57:21 +0100 Subject: [PATCH 06/15] glEnableVertexAttribArray -> glEnableVertexArrayAttrib --- src/font/fontrenderer.cpp | 12 ++++++------ src/io/model/modelmesh.cpp | 10 +++++----- src/opengl/vertexbufferobject.cpp | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/font/fontrenderer.cpp b/src/font/fontrenderer.cpp index 40387909..90dafe0e 100644 --- a/src/font/fontrenderer.cpp +++ b/src/font/fontrenderer.cpp @@ -223,10 +223,10 @@ FontRenderer::FontRenderer(std::unique_ptr program, float outlineT; }; - glEnableVertexAttribArray(0); + glEnableVertexArrayAttrib(_orthogonal.vao, 0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(OrthogonalVertex), nullptr); - glEnableVertexAttribArray(1); + glEnableVertexArrayAttrib(_orthogonal.vao, 1); glVertexAttribPointer( 1, 2, @@ -236,7 +236,7 @@ FontRenderer::FontRenderer(std::unique_ptr program, reinterpret_cast(offsetof(OrthogonalVertex, s)) ); - glEnableVertexAttribArray(2); + glEnableVertexArrayAttrib(_orthogonal.vao, 2); glVertexAttribPointer( 2, 2, @@ -268,10 +268,10 @@ FontRenderer::FontRenderer(std::unique_ptr program, float outlineT; }; - glEnableVertexAttribArray(0); + glEnableVertexArrayAttrib(_perspective.vao, 0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(PerspectiveVertex), nullptr); - glEnableVertexAttribArray(1); + glEnableVertexArrayAttrib(_perspective.vao, 1); glVertexAttribPointer( 1, 2, @@ -281,7 +281,7 @@ FontRenderer::FontRenderer(std::unique_ptr program, reinterpret_cast(offsetof(PerspectiveVertex, s)) ); - glEnableVertexAttribArray(2); + glEnableVertexArrayAttrib(_perspective.vao, 2); glVertexAttribPointer( 2, 2, diff --git a/src/io/model/modelmesh.cpp b/src/io/model/modelmesh.cpp index 212ce439..f67c7b8e 100644 --- a/src/io/model/modelmesh.cpp +++ b/src/io/model/modelmesh.cpp @@ -282,11 +282,11 @@ void ModelMesh::initialize() { // Set vertex attributes pointers // Vertex position - glEnableVertexAttribArray(0); + glEnableVertexArrayAttrib(_vaoID, 0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr); // Vertex texture coordinates - glEnableVertexAttribArray(1); + glEnableVertexArrayAttrib(_vaoID, 1); glVertexAttribPointer( 1, 2, @@ -297,7 +297,7 @@ void ModelMesh::initialize() { ); // Vertex normals - glEnableVertexAttribArray(2); + glEnableVertexArrayAttrib(_vaoID, 2); glVertexAttribPointer( 2, 3, @@ -308,7 +308,7 @@ void ModelMesh::initialize() { ); // Vertex tangent (for normal mapping) - glEnableVertexAttribArray(3); + glEnableVertexArrayAttrib(_vaoID, 3); glVertexAttribPointer( 3, 3, @@ -319,7 +319,7 @@ void ModelMesh::initialize() { ); // Vertex color - glEnableVertexAttribArray(4); + glEnableVertexArrayAttrib(_vaoID, 4); glVertexAttribPointer( 4, 3, diff --git a/src/opengl/vertexbufferobject.cpp b/src/opengl/vertexbufferobject.cpp index b51e95a7..7aa7c49d 100644 --- a/src/opengl/vertexbufferobject.cpp +++ b/src/opengl/vertexbufferobject.cpp @@ -108,7 +108,7 @@ void VertexBufferObject::vertexAttribPointer(GLuint index, GLint size, GLenum ty { uint64_t o = offset; glBindVertexArray(_vaoID); - glEnableVertexAttribArray(index); + glEnableVertexArrayAttrib(_vaoID, index); glVertexAttribPointer( index, size, From 6b696942e7fdbb796b36638b72889f19bee6a2f8 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Tue, 3 Feb 2026 00:56:23 +0100 Subject: [PATCH 07/15] Use DSA functions for vertex arrays and buffer objects 1/n --- src/font/fontrenderer.cpp | 78 ++++++++++++++++++++++---------------- src/io/model/modelmesh.cpp | 59 +++++++--------------------- 2 files changed, 58 insertions(+), 79 deletions(-) diff --git a/src/font/fontrenderer.cpp b/src/font/fontrenderer.cpp index 90dafe0e..55953da2 100644 --- a/src/font/fontrenderer.cpp +++ b/src/font/fontrenderer.cpp @@ -208,12 +208,6 @@ FontRenderer::FontRenderer(std::unique_ptr program, // // Configure the OpenGL objects for the orthogonal font rendering - glCreateVertexArrays(1, &_orthogonal.vao); - glBindVertexArray(_orthogonal.vao); - - glCreateBuffers(1, &_orthogonal.vbo); - glBindBuffer(GL_ARRAY_BUFFER, _orthogonal.vbo); - struct OrthogonalVertex { float x; float y; @@ -223,41 +217,48 @@ FontRenderer::FontRenderer(std::unique_ptr program, float outlineT; }; + glCreateBuffers(1, &_orthogonal.vbo); + glCreateBuffers(1, &_orthogonal.ibo); + + glCreateVertexArrays(1, &_orthogonal.vao); + glVertexArrayVertexBuffer( + _orthogonal.vao, + 0, + _orthogonal.vbo, + 0, + sizeof(OrthogonalVertex) + ); + glVertexArrayElementBuffer(_orthogonal.vao, _orthogonal.ibo); + glEnableVertexArrayAttrib(_orthogonal.vao, 0); - glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(OrthogonalVertex), nullptr); + glVertexArrayAttribFormat(_orthogonal.vao, 0, 2, GL_FLOAT, GL_FALSE, 0); + glVertexArrayAttribBinding(_orthogonal.vao, 0, 0); glEnableVertexArrayAttrib(_orthogonal.vao, 1); - glVertexAttribPointer( + glVertexArrayAttribFormat( + _orthogonal.vao, 1, 2, GL_FLOAT, GL_FALSE, - sizeof(OrthogonalVertex), - reinterpret_cast(offsetof(OrthogonalVertex, s)) + offsetof(OrthogonalVertex, s) ); + glVertexArrayAttribBinding(_orthogonal.vao, 1, 0); glEnableVertexArrayAttrib(_orthogonal.vao, 2); - glVertexAttribPointer( + glVertexArrayAttribFormat( + _orthogonal.vao, 2, 2, GL_FLOAT, GL_FALSE, - sizeof(OrthogonalVertex), - reinterpret_cast(offsetof(OrthogonalVertex, outlineS)) + offsetof(OrthogonalVertex, outlineS) ); - - glCreateBuffers(1, &_orthogonal.ibo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _orthogonal.ibo); + glVertexArrayAttribBinding(_orthogonal.vao, 2, 0); // // Configure the OpenGL objects for the projective font rendering - glCreateVertexArrays(1, &_perspective.vao); - glBindVertexArray(_perspective.vao); - - glCreateBuffers(1, &_perspective.vbo); - glBindBuffer(GL_ARRAY_BUFFER, _perspective.vbo); - struct PerspectiveVertex { float x; float y; @@ -268,32 +269,43 @@ FontRenderer::FontRenderer(std::unique_ptr program, float outlineT; }; + glCreateBuffers(1, &_perspective.vbo); + glCreateBuffers(1, &_perspective.ibo); + glCreateVertexArrays(1, &_perspective.vao); + glVertexArrayVertexBuffer( + _perspective.vao, + 0, + _perspective.vbo, + 0, + sizeof(PerspectiveVertex) + ); + glVertexArrayElementBuffer(_perspective.vao, _perspective.ibo); + glEnableVertexArrayAttrib(_perspective.vao, 0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(PerspectiveVertex), nullptr); + glVertexArrayAttribFormat(_perspective.vao, 0, 3, GL_FLOAT, GL_FALSE, 0); + glVertexArrayAttribBinding(_perspective.vao, 0, 0); glEnableVertexArrayAttrib(_perspective.vao, 1); - glVertexAttribPointer( + glVertexArrayAttribFormat( + _perspective.vao, 1, 2, GL_FLOAT, GL_FALSE, - 7 * sizeof(float), - reinterpret_cast(offsetof(PerspectiveVertex, s)) + offsetof(PerspectiveVertex, s) ); + glVertexArrayAttribBinding(_perspective.vao, 1, 0); glEnableVertexArrayAttrib(_perspective.vao, 2); - glVertexAttribPointer( + glVertexArrayAttribFormat( + _perspective.vao, 2, 2, GL_FLOAT, GL_FALSE, - 7 * sizeof(float), - reinterpret_cast(offsetof(PerspectiveVertex, outlineS)) + offsetof(PerspectiveVertex, outlineS) ); - - glCreateBuffers(1, &_perspective.ibo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _perspective.ibo); - glBindVertexArray(0); + glVertexArrayAttribBinding(_perspective.vao, 2, 0); _vertexBuffer.reserve(128 * 10); _indexBuffer.reserve(128 * 10); diff --git a/src/io/model/modelmesh.cpp b/src/io/model/modelmesh.cpp index f67c7b8e..b4cd302e 100644 --- a/src/io/model/modelmesh.cpp +++ b/src/io/model/modelmesh.cpp @@ -258,11 +258,7 @@ void ModelMesh::initialize() { return; } - glCreateVertexArrays(1, &_vaoID); - glBindVertexArray(_vaoID); - glCreateBuffers(1, &_vbo); - glBindBuffer(GL_ARRAY_BUFFER, _vbo); glNamedBufferData( _vbo, _vertices.size() * sizeof(Vertex), @@ -271,7 +267,6 @@ void ModelMesh::initialize() { ); glCreateBuffers(1, &_ibo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo); glNamedBufferData( _ibo, _indices.size() * sizeof(unsigned int), @@ -279,57 +274,29 @@ void ModelMesh::initialize() { GL_STATIC_DRAW ); + glCreateVertexArrays(1, &_vaoID); + glVertexArrayVertexBuffer(_vaoID, 0, _vbo, 0, sizeof(Vertex)); + glVertexArrayElementBuffer(_vaoID, _ibo); - // Set vertex attributes pointers - // Vertex position glEnableVertexArrayAttrib(_vaoID, 0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr); + glVertexArrayAttribFormat(_vaoID, 0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex)); + glVertexArrayAttribBinding(_vaoID, 0, 0); - // Vertex texture coordinates glEnableVertexArrayAttrib(_vaoID, 1); - glVertexAttribPointer( - 1, - 2, - GL_FLOAT, - GL_FALSE, - sizeof(Vertex), - reinterpret_cast(offsetof(Vertex, tex)) - ); + glVertexArrayAttribFormat(_vaoID, 1, 2, GL_FLOAT, GL_FALSE, offsetof(Vertex, tex)); + glVertexArrayAttribBinding(_vaoID, 1, 0); - // Vertex normals glEnableVertexArrayAttrib(_vaoID, 2); - glVertexAttribPointer( - 2, - 3, - GL_FLOAT, - GL_FALSE, - sizeof(Vertex), - reinterpret_cast(offsetof(Vertex, normal)) - ); + glVertexArrayAttribFormat(_vaoID, 2, 3, GL_FLOAT, GL_FALSE, offsetof(Vertex, normal)); + glVertexArrayAttribBinding(_vaoID, 2, 0); - // Vertex tangent (for normal mapping) glEnableVertexArrayAttrib(_vaoID, 3); - glVertexAttribPointer( - 3, - 3, - GL_FLOAT, - GL_FALSE, - sizeof(Vertex), - reinterpret_cast(offsetof(Vertex, tangent)) - ); + glVertexArrayAttribFormat(_vaoID, 3, 3, GL_FLOAT, GL_FALSE, offsetof(Vertex, tangent)); + glVertexArrayAttribBinding(_vaoID, 3, 0); - // Vertex color glEnableVertexArrayAttrib(_vaoID, 4); - glVertexAttribPointer( - 4, - 3, - GL_FLOAT, - GL_FALSE, - sizeof(Vertex), - reinterpret_cast(offsetof(Vertex, color)) - ); - - glBindVertexArray(0); + glVertexArrayAttribFormat(_vaoID, 4, 3, GL_FLOAT, GL_FALSE, offsetof(Vertex, color)); + glVertexArrayAttribBinding(_vaoID, 4, 0); // initialize textures // Also chack if there are several textures/colors of the same type for this mesh From db71c6ca1aa67c0045622fc1334ba5d35939476c Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Tue, 3 Feb 2026 15:42:59 +0100 Subject: [PATCH 08/15] glNamedBufferData -> glNamedBufferStorage --- include/ghoul/opengl/vertexbufferobject.inl | 17 +++++++---------- src/io/model/modelmesh.cpp | 8 ++++---- src/opengl/vertexbufferobject.cpp | 8 ++++---- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/include/ghoul/opengl/vertexbufferobject.inl b/include/ghoul/opengl/vertexbufferobject.inl index 892c5c0e..7086c360 100644 --- a/include/ghoul/opengl/vertexbufferobject.inl +++ b/include/ghoul/opengl/vertexbufferobject.inl @@ -41,28 +41,25 @@ void VertexBufferObject::initialize(const std::vector& vertexArray, _iSize = static_cast(indexArray.size()); - glCreateVertexArrays(1, &_vaoID); - glBindVertexArray(_vaoID); - glCreateBuffers(1, &_vBufferID); - glBindBuffer(GL_ARRAY_BUFFER, _vBufferID); - glNamedBufferData( + glNamedBufferStorage( _vBufferID, vertexArray.size() * sizeof(T), vertexArray.data(), - GL_STATIC_DRAW + GL_NONE_BIT ); glCreateBuffers(1, &_iBufferID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID); - glNamedBufferData( + glNamedBufferStorage( _iBufferID, indexArray.size() * sizeof(GLint), indexArray.data(), - GL_STATIC_DRAW + GL_NONE_BIT ); - glBindVertexArray(0); + glCreateVertexArrays(1, &_vaoID); + glVertexArrayVertexBuffer(_vaoId, 0, _vBufferID, 0, 3 * sizeof(float)); + glVertexArrayElementBuffer(_vaoId, _iBufferID); } } // namespace ghoul::opengl diff --git a/src/io/model/modelmesh.cpp b/src/io/model/modelmesh.cpp index b4cd302e..e4854f6d 100644 --- a/src/io/model/modelmesh.cpp +++ b/src/io/model/modelmesh.cpp @@ -259,19 +259,19 @@ void ModelMesh::initialize() { } glCreateBuffers(1, &_vbo); - glNamedBufferData( + glNamedBufferStorage( _vbo, _vertices.size() * sizeof(Vertex), _vertices.data(), - GL_STATIC_DRAW + GL_NONE_BIT ); glCreateBuffers(1, &_ibo); - glNamedBufferData( + glNamedBufferStorage( _ibo, _indices.size() * sizeof(unsigned int), _indices.data(), - GL_STATIC_DRAW + GL_NONE_BIT ); glCreateVertexArrays(1, &_vaoID); diff --git a/src/opengl/vertexbufferobject.cpp b/src/opengl/vertexbufferobject.cpp index 7aa7c49d..b0c2c7f3 100644 --- a/src/opengl/vertexbufferobject.cpp +++ b/src/opengl/vertexbufferobject.cpp @@ -79,20 +79,20 @@ void VertexBufferObject::initialize(const std::vector& vertexArray, glCreateBuffers(1, &_vBufferID); glBindBuffer(GL_ARRAY_BUFFER, _vBufferID); - glNamedBufferData( + glNamedBufferStorage( _vBufferID, vertexArray.size() * sizeof(GLfloat), vertexArray.data(), - GL_STATIC_DRAW + GL_NONE_BIT ); glCreateBuffers(1, &_iBufferID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID); - glNamedBufferData( + glNamedBufferStorage( _iBufferID, indexArray.size() * sizeof(GLint), indexArray.data(), - GL_STATIC_DRAW + GL_NONE_BIT ); glBindVertexArray(0); From 59f56eb289dd79b972bf3973fef3b25400716c44 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 4 Feb 2026 15:35:20 +0100 Subject: [PATCH 09/15] More DSA calls for textures --- src/opengl/texture.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/opengl/texture.cpp b/src/opengl/texture.cpp index 98d60729..f2d91252 100755 --- a/src/opengl/texture.cpp +++ b/src/opengl/texture.cpp @@ -444,12 +444,10 @@ void Texture::uploadDataToTexture(void* pixelData) const { } void Texture::reUploadDataToTexture(void* pixelData) const { - bind(); - switch (_type) { case GL_TEXTURE_1D: - glTexSubImage1D( - _type, + glTextureSubImage1D( + _id, 0, 0, GLsizei(_dimensions.x), @@ -459,8 +457,8 @@ void Texture::reUploadDataToTexture(void* pixelData) const { ); break; case GL_TEXTURE_2D: - glTexSubImage2D( - _type, + glTextureSubImage2D( + _id, 0, 0, 0, @@ -472,8 +470,8 @@ void Texture::reUploadDataToTexture(void* pixelData) const { ); break; case GL_TEXTURE_3D: - glTexSubImage3D( - _type, + glTextureSubImage3D( + _id, 0, 0, 0, @@ -1374,9 +1372,7 @@ glm::vec4 Texture::texelAsFloat(const glm::uvec3& pos) const { void Texture::setBorderColor(glm::vec4 borderColor) { _borderColor = std::move(borderColor); - - bind(); - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, glm::value_ptr(_borderColor)); + glTextureParameterfv(_id, GL_TEXTURE_BORDER_COLOR, glm::value_ptr(_borderColor)); } glm::vec4 Texture::borderColor() const { From 966916f03489d7ddb900b13c36315ce1724fe86b Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 4 Feb 2026 15:35:30 +0100 Subject: [PATCH 10/15] Add new function to perform program validation --- include/ghoul/opengl/programobject.h | 11 ++++++++++ src/opengl/programobject.cpp | 30 ++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/include/ghoul/opengl/programobject.h b/include/ghoul/opengl/programobject.h index 4528217a..bee42284 100755 --- a/include/ghoul/opengl/programobject.h +++ b/include/ghoul/opengl/programobject.h @@ -241,6 +241,17 @@ class ProgramObject { */ void rebuildFromFile(); + /** + * Calls the OpenGL driver to validate the program object. This should only be done + * close to the actual draw call usage and with the same state. Any messages reported + * by the driver will be printed as informational messages. If the validation fails + * an error message will be raised. + * + * Note: This function should only be called when full performance is not needed, for + * example in Debug environments or during shaderd development + */ + void validate() const; + /** * Returns whether this ProgramObject is dirty and needs to be recompiled and rebuilt * due to a change in the underlying file. A ProgramObject is automatically set to be diff --git a/src/opengl/programobject.cpp b/src/opengl/programobject.cpp index 32c26ae9..993b199a 100755 --- a/src/opengl/programobject.cpp +++ b/src/opengl/programobject.cpp @@ -283,6 +283,36 @@ void ProgramObject::rebuildFromFile() { *this = std::move(p); } +void ProgramObject::validate() const { + glValidateProgram(_id); + + GLint success = 0; + glGetProgramiv(_id, GL_VALIDATE_STATUS, &success); + + GLint logLength = 0; + glGetProgramiv(_id, GL_INFO_LOG_LENGTH, &logLength); + + if (success == GL_TRUE) { + if (logLength > 0) { + std::vector rawLog(logLength); + glGetProgramInfoLog(_id, logLength, nullptr, rawLog.data()); + const std::string log = std::string(rawLog.data()); + LINFO(log); + } + } + else { + if (logLength > 0) { + std::vector rawLog(logLength); + glGetProgramInfoLog(_id, logLength, nullptr, rawLog.data()); + const std::string log = std::string(rawLog.data()); + LERROR(log); + } + else { + LERROR("Unknown error validating program"); + } + } +} + bool ProgramObject::isDirty() const { return _programIsDirty; } From ba01087376a3f457a5d88065deeece0518d060a7 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 5 Feb 2026 12:13:12 +0100 Subject: [PATCH 11/15] Compile fix --- include/ghoul/opengl/vertexbufferobject.inl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/ghoul/opengl/vertexbufferobject.inl b/include/ghoul/opengl/vertexbufferobject.inl index 7086c360..83c94521 100644 --- a/include/ghoul/opengl/vertexbufferobject.inl +++ b/include/ghoul/opengl/vertexbufferobject.inl @@ -58,8 +58,8 @@ void VertexBufferObject::initialize(const std::vector& vertexArray, ); glCreateVertexArrays(1, &_vaoID); - glVertexArrayVertexBuffer(_vaoId, 0, _vBufferID, 0, 3 * sizeof(float)); - glVertexArrayElementBuffer(_vaoId, _iBufferID); + glVertexArrayVertexBuffer(_vaoID, 0, _vBufferID, 0, 3 * sizeof(float)); + glVertexArrayElementBuffer(_vaoID, _iBufferID); } } // namespace ghoul::opengl From 5236cc767016a9a04a20a9f6fce5adacecb8ad35 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 5 Feb 2026 12:13:44 +0100 Subject: [PATCH 12/15] Apply DSA to TextureUnits --- include/ghoul/opengl/textureunit.h | 49 ++---------------------------- src/font/fontrenderer.cpp | 6 ++-- src/io/model/modelmesh.cpp | 12 ++------ src/opengl/textureunit.cpp | 34 ++++++--------------- 4 files changed, 17 insertions(+), 84 deletions(-) diff --git a/include/ghoul/opengl/textureunit.h b/include/ghoul/opengl/textureunit.h index 1d26b349..da618443 100644 --- a/include/ghoul/opengl/textureunit.h +++ b/include/ghoul/opengl/textureunit.h @@ -61,45 +61,18 @@ class TextureUnit { */ ~TextureUnit(); - TextureUnit(const TextureUnit&) = default; TextureUnit(TextureUnit&&) noexcept = default; /** - * This method will activate the enum assigned to this TextureUnit. If this is the - * first call to either activate, #glEnum, or #unitNumber, a free unit number will be - * assigned to this object. This will call the OpenGL function - * `glActiveTexture` with the enum as a parameter. - * - * \throw TextureUnitError If the new unit number could not be assigned + * Activates and binds the provided texture to the TextureUnit. */ - void activate(); + void bind(GLuint texture); /** * This method will deactivate the enum assigned to this TextureUnit and mark it as * free again. */ - void deactivate(); - - /** - * This method returns the texture unit enum that was assigned to this TextureUnit. If - * this is the first call to either #activate, glEnum, or #unitNumber, a free unit - * enum will be assigned to this object. The returned enum is equivalent to - * `GL_TEXTURE0 + unitNumber()`. - * - * \return The unit enum that was assigned to this TextureUnit - */ - GLenum glEnum(); - - /** - * This method returns the texture unit number that was assigned to this TextureUnit. - * If this is the first call to either #activate, #glEnum, or unitNumber, a free unit - * number will be assigned to this object. - * - * \return The texture unit number that was assigned to this TextureUnit - * - * \throw TextureUnitError If the new unit number could not be assigned - */ - GLint unitNumber(); + void unassign(); /** * This operator returns the texture unit number that was assigned to this @@ -113,22 +86,6 @@ class TextureUnit { */ operator GLint(); - /** - * Sets the zero unit as the active texture unit. This call is equivalent to calling - * the OpenGL function `glActiveTexture(GL_TEXTURE0)`. - */ - static void setZeroUnit(); - - /** - * This method returns the number texture units that have been marked as used by - * calling one of the methods #activate, #glEnum, or #unitNumber. The maximum number - * of supported texture units can be queried from the - * #ghoul::systemcapabilities::SystemCapabilities. - * - * \return The number of texture units in use - */ - static int numberActiveUnits(); - private: /** * This method is called the first time either #activate, #glEnum, or #unitNumber is diff --git a/src/font/fontrenderer.cpp b/src/font/fontrenderer.cpp index 55953da2..dd4a93ef 100644 --- a/src/font/fontrenderer.cpp +++ b/src/font/fontrenderer.cpp @@ -524,8 +524,7 @@ FontRenderer::BoundingBoxInformation FontRenderer::render(Font& font, size.y = lines * font.height(); opengl::TextureUnit atlasUnit; - atlasUnit.activate(); - font.atlasTexture().bind(); + atlasUnit.bind(font.atlasTexture()); _program->setUniform(_uniformCache.baseColor, color); _program->setUniform(_uniformCache.outlineColor, outlineColor); @@ -732,8 +731,7 @@ FontRenderer::BoundingBoxInformation FontRenderer::render(Font& font, _program->activate(); opengl::TextureUnit atlasUnit; - atlasUnit.activate(); - font.atlasTexture().bind(); + atlasUnit.bind(font.atlasTexture()); _program->setUniform(_uniformCacheProjection.baseColor, color); _program->setUniform(_uniformCacheProjection.outlineColor, outlineColor); diff --git a/src/io/model/modelmesh.cpp b/src/io/model/modelmesh.cpp index e4854f6d..feeb08e0 100644 --- a/src/io/model/modelmesh.cpp +++ b/src/io/model/modelmesh.cpp @@ -109,7 +109,7 @@ void ModelMesh::render(opengl::ProgramObject& program, const glm::mat4& meshTran // Use texture or color if (texture.hasTexture) { // Activate proper texture unit before binding - textureUnits[textureUnitIndex].activate(); + textureUnits[textureUnitIndex].bind(*texture.texture); // Specular special case if (texture.type == TextureType::TextureSpecular) { @@ -120,9 +120,6 @@ void ModelMesh::render(opengl::ProgramObject& program, const glm::mat4& meshTran program.setUniform("has_" + name, true); program.setUniform(name, textureUnits[textureUnitIndex]); - // And finally bind the texture - texture.texture->bind(); - // Advance the texture unit index textureUnitIndex++; } @@ -153,15 +150,12 @@ void ModelMesh::render(opengl::ProgramObject& program, const glm::mat4& meshTran // Use texture or color if (texture.hasTexture) { // Activate proper texture unit before binding - textureUnits[textureUnitIndex].activate(); + textureUnits[textureUnitIndex].bind(*texture.texture); // Tell shader to use textures and set texture unit program.setUniform("has_texture_diffuse", true); program.setUniform("baseTexture", textureUnits[textureUnitIndex]); - // And finally bind the texture - texture.texture->bind(); - // Advance the texture unit index textureUnitIndex++; break; @@ -279,7 +273,7 @@ void ModelMesh::initialize() { glVertexArrayElementBuffer(_vaoID, _ibo); glEnableVertexArrayAttrib(_vaoID, 0); - glVertexArrayAttribFormat(_vaoID, 0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex)); + glVertexArrayAttribFormat(_vaoID, 0, 3, GL_FLOAT, GL_FALSE, 0); glVertexArrayAttribBinding(_vaoID, 0, 0); glEnableVertexArrayAttrib(_vaoID, 1); diff --git a/src/opengl/textureunit.cpp b/src/opengl/textureunit.cpp index 4fcc1216..dc6d75a6 100644 --- a/src/opengl/textureunit.cpp +++ b/src/opengl/textureunit.cpp @@ -25,6 +25,7 @@ #include +#include #include #include #include @@ -47,17 +48,18 @@ TextureUnit::TextureUnit() { } TextureUnit::~TextureUnit() { - deactivate(); + unassign(); } -void TextureUnit::activate() { +void TextureUnit::bind(GLuint texture) { if (!_assigned) { assignUnit(); } - glActiveTexture(_glEnum); + + glBindTextureUnit(_number, texture); } -void TextureUnit::deactivate() { +void TextureUnit::unassign() { if (_assigned) { _assigned = false; _busyUnits.at(_number) = false; @@ -67,32 +69,13 @@ void TextureUnit::deactivate() { } } -GLenum TextureUnit::glEnum() { - if (!_assigned) { - assignUnit(); - } - return _glEnum; -} - -GLint TextureUnit::unitNumber() { +TextureUnit::operator GLint() { if (!_assigned) { assignUnit(); } return _number; } -TextureUnit::operator GLint() { - return unitNumber(); -} - -void TextureUnit::setZeroUnit() { - glActiveTexture(GL_TEXTURE0); -} - -int TextureUnit::numberActiveUnits() { - return _totalActive; -} - void TextureUnit::assignUnit() { if (_totalActive >= _maxTexUnits) { throw TextureUnitError("No more texture units available"); @@ -116,7 +99,8 @@ void TextureUnit::initialize() { _maxTexUnits = OpenGLCap.maxTextureUnits(); } else { - _maxTexUnits = 8; // Reasonable default setting for OpenGL + // OpenGL requires at least 16 texture units to exist + _maxTexUnits = 16; } _busyUnits = std::vector(_maxTexUnits, false); _isInitialized = true; From 489ea53f17f1911622070547555c936833c1112c Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 5 Feb 2026 12:30:36 +0100 Subject: [PATCH 13/15] Compile fixes --- src/opengl/programobject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opengl/programobject.cpp b/src/opengl/programobject.cpp index 993b199a..aee3a7ce 100755 --- a/src/opengl/programobject.cpp +++ b/src/opengl/programobject.cpp @@ -292,7 +292,7 @@ void ProgramObject::validate() const { GLint logLength = 0; glGetProgramiv(_id, GL_INFO_LOG_LENGTH, &logLength); - if (success == GL_TRUE) { + if (success) { if (logLength > 0) { std::vector rawLog(logLength); glGetProgramInfoLog(_id, logLength, nullptr, rawLog.data()); From 762874ee6a3f2113485ec882218e82628623fbe5 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 5 Feb 2026 12:45:30 +0100 Subject: [PATCH 14/15] Remove binding of textures --- include/ghoul/opengl/texture.h | 5 ----- src/opengl/texture.cpp | 11 +++-------- src/opengl/textureatlas.cpp | 1 - 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/include/ghoul/opengl/texture.h b/include/ghoul/opengl/texture.h index 782b9cb8..4981a394 100755 --- a/include/ghoul/opengl/texture.h +++ b/include/ghoul/opengl/texture.h @@ -210,11 +210,6 @@ class Texture { */ void disable() const; - /** - * Binds this texture to the texture type by calling `glBindTexture`. - */ - void bind() const; - /** * Returns the OpenGL name of this texture. */ diff --git a/src/opengl/texture.cpp b/src/opengl/texture.cpp index f2d91252..f098ffb9 100755 --- a/src/opengl/texture.cpp +++ b/src/opengl/texture.cpp @@ -152,10 +152,6 @@ void Texture::disable() const { glDisable(_type); } -void Texture::bind() const { - glBindTexture(_type, _id); -} - Texture::operator GLuint() const { return _id; } @@ -394,8 +390,7 @@ void Texture::applySwizzleMask() { } void Texture::uploadDataToTexture(void* pixelData) const { - bind(); - + glBindTexture(_type, _id); glPixelStorei(GL_UNPACK_ALIGNMENT, _pixelAlignment); switch (_type) { @@ -516,11 +511,11 @@ void Texture::purgeFromRAM() { } void Texture::downloadTexture() { - bind(); if (!_pixels) { allocateMemory(); } - glGetTexImage(_type, 0, GLenum(_format), _dataType, _pixels); + const unsigned int arraySize = compMul(_dimensions) * _bpp; + glGetTextureImage(_id, 0, GLenum(_format), _dataType, arraySize, _pixels); } glm::vec4 Texture::texelAsFloat(unsigned int x) const { diff --git a/src/opengl/textureatlas.cpp b/src/opengl/textureatlas.cpp index 35c38ebd..1fc78c81 100644 --- a/src/opengl/textureatlas.cpp +++ b/src/opengl/textureatlas.cpp @@ -119,7 +119,6 @@ int TextureAtlas::spaceUsed() const { void TextureAtlas::upload() { _texture->setPixelData(_data.data(), Texture::TakeOwnership::No); - _texture->bind(); _texture->uploadTexture(); } From edcb8e8b1b70fcdbbee9e22be66fd3660ebc50f4 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Thu, 5 Feb 2026 14:54:03 +0100 Subject: [PATCH 15/15] Fewer bind calls --- src/font/fontrenderer.cpp | 31 ++++++++++++++++++------------- src/opengl/vertexbufferobject.cpp | 1 - 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/font/fontrenderer.cpp b/src/font/fontrenderer.cpp index dd4a93ef..8408cb4c 100644 --- a/src/font/fontrenderer.cpp +++ b/src/font/fontrenderer.cpp @@ -507,12 +507,15 @@ FontRenderer::BoundingBoxInformation FontRenderer::render(Font& font, const GLushort idx3 = vertexIndex + 3; _indexBuffer.insert(_indexBuffer.end(), { idx, idx1, idx2, idx, idx2, idx3 }); vertexIndex += 4; - _vertexBuffer.insert(_vertexBuffer.end(), { - x0, y0, s0, t0, outlineS0, outlineT0, - x0, y1, s0, t1, outlineS0, outlineT1, - x1, y1, s1, t1, outlineS1, outlineT1, - x1, y0, s1, t0, outlineS1, outlineT0 - }); + _vertexBuffer.insert( + _vertexBuffer.end(), + { + x0, y0, s0, t0, outlineS0, outlineT0, + x0, y1, s0, t1, outlineS0, outlineT1, + x1, y1, s1, t1, outlineS1, outlineT1, + x1, y0, s1, t0, outlineS1, outlineT0 + } + ); movingPos.x += glyph->horizontalAdvance; width += glyph->horizontalAdvance; @@ -697,12 +700,15 @@ FontRenderer::BoundingBoxInformation FontRenderer::render(Font& font, } } - _vertexBuffer.insert(_vertexBuffer.end(), { - p0.x, p0.y, p0.z, s0, t0, outlineS0, outlineT0, - p1.x, p1.y, p1.z, s0, t1, outlineS0, outlineT1, - p2.x, p2.y, p2.z, s1, t1, outlineS1, outlineT1, - p3.x, p3.y, p3.z, s1, t0, outlineS1, outlineT0 - }); + _vertexBuffer.insert( + _vertexBuffer.end(), + { + p0.x, p0.y, p0.z, s0, t0, outlineS0, outlineT0, + p1.x, p1.y, p1.z, s0, t1, outlineS0, outlineT1, + p2.x, p2.y, p2.z, s1, t1, outlineS1, outlineT1, + p3.x, p3.y, p3.z, s1, t0, outlineS1, outlineT0 + } + ); const unsigned short vi = vertexIndex; const unsigned short vi1 = vertexIndex + 1; @@ -751,7 +757,6 @@ FontRenderer::BoundingBoxInformation FontRenderer::render(Font& font, labelInfo.disableTransmittance ); - glNamedBufferData( _perspective.vbo, _vertexBuffer.size() * sizeof(float), diff --git a/src/opengl/vertexbufferobject.cpp b/src/opengl/vertexbufferobject.cpp index b0c2c7f3..21c88bfc 100644 --- a/src/opengl/vertexbufferobject.cpp +++ b/src/opengl/vertexbufferobject.cpp @@ -130,7 +130,6 @@ void VertexBufferObject::unbind() const { void VertexBufferObject::render() const { glBindVertexArray(_vaoID); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _iBufferID); glDrawElements(_mode, _iSize, GL_UNSIGNED_INT, nullptr); glBindVertexArray(0); }