diff --git a/libs/gfx/include/psemek/gfx/program.hpp b/libs/gfx/include/psemek/gfx/program.hpp index 41af9fea..4fe49dd2 100644 --- a/libs/gfx/include/psemek/gfx/program.hpp +++ b/libs/gfx/include/psemek/gfx/program.hpp @@ -18,6 +18,8 @@ namespace psemek::gfx program(std::string_view vertex_source, std::string_view fragment_source); program(std::string_view vertex_source, std::string_view geometry_source, std::string_view fragment_source); + ~program(); + GLuint id() const; void bind() const; diff --git a/libs/gfx/source/gfx/program.cpp b/libs/gfx/source/gfx/program.cpp index 7c8a344f..94821053 100644 --- a/libs/gfx/source/gfx/program.cpp +++ b/libs/gfx/source/gfx/program.cpp @@ -1,6 +1,7 @@ #include #include +#include #include @@ -245,6 +246,12 @@ namespace psemek::gfx static GLuint create_program(std::vector> const & sources) { std::vector shaders; + + [[maybe_unused]] util::at_scope_exit delete_shaders([&shaders]{ + for (auto s : shaders) + gl::DeleteShader(s); + }); + for (auto const & p : sources) { GLuint sh = gl::CreateShader(p.first); @@ -252,10 +259,16 @@ namespace psemek::gfx } GLuint program = gl::CreateProgram(); - load_program(program, shaders); - for (auto s : shaders) - gl::DeleteShader(s); + try + { + load_program(program, shaders); + } + catch (...) + { + gl::DeleteProgram(program); + throw; + } return program; } @@ -270,6 +283,11 @@ namespace psemek::gfx program_ = create_program({{gl::VERTEX_SHADER, vertex_source}, {gl::GEOMETRY_SHADER, geometry_source}, {gl::FRAGMENT_SHADER, fragment_source}}); } + program::~program() + { + gl::DeleteProgram(program_); + } + GLuint program::id() const { return program_; diff --git a/todo.md b/todo.md index ae2d8f74..79b94898 100644 --- a/todo.md +++ b/todo.md @@ -1,4 +1,3 @@ -* Make sure program & shaders are deleted properly if program creation fails * Remove gfx::vertex, setup mesh using attributes directly * Design affine transforms in geom & use them instead of matrices when appropriate * Create an 'app' module that simplifies application creation