Skip to content

Shader validation #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 10, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.idea/
cmake-build-debug/
/build
5 changes: 5 additions & 0 deletions include/gl_layer/private/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,18 @@ class Context {
void glGetProgramiv(unsigned int handle, GLenum param, int* params);
void glLinkProgram(GLuint program);
void glUseProgram(unsigned int handle);
void glDeleteProgram(GLuint program);

void validate_program_bound(std::string_view func_name);
bool validate_program_status(GLuint program);

private:
Version gl_version;

GLLayerOutputFun output_fun = nullptr;
void* output_user_data = nullptr;
ContextGLFunctions gl;
GLuint bound_program = 0;

std::unordered_map<unsigned int, Shader> shaders{};
std::unordered_map<unsigned int, Program> programs{};
Expand Down
2 changes: 2 additions & 0 deletions include/gl_layer/private/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ using GLuint = std::uint32_t;
using GLint = std::int32_t;
using GLsizei = std::int32_t;
using GLchar = char;
using GLfloat = float;
using GLboolean = bool;

enum GLShaderInfoParam {
GL_SHADER_TYPE = 0x8B4F,
Expand Down
10 changes: 9 additions & 1 deletion src/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,14 @@ Context* g_context = nullptr;

} // namespace gl_layer

static bool is_func(const char* name, std::string_view func) {
static bool is_func(std::string_view name, std::string_view func) {
return func == name;
}

static bool func_has(std::string_view name, std::string_view substr) {
return name.find(substr) != std::string_view::npos;
}

int gl_layer_init(unsigned int gl_version_major, unsigned int gl_version_minor, const ContextGLFunctions* gl_functions) {
gl_layer::g_context = new gl_layer::Context(gl_layer::Version{ gl_version_major, gl_version_minor }, gl_functions);
if (gl_layer::g_context) return 0;
Expand All @@ -64,6 +68,10 @@ void gl_layer_callback(const char* name, void* func_ptr, int num_args, ...) {
return;
}

using namespace gl_layer; // GL types

std::string_view name = name_c;

va_list args;
va_start(args, num_args);

Expand Down
61 changes: 53 additions & 8 deletions src/shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@ void Context::glLinkProgram(GLuint program)
return;
}

auto& programr = program_it->second;
auto& programInfo = program_it->second;

// Store all active uniforms in the program (location, array size, and type)
GLint uniform_count{};
gl.GetProgramiv(program, GL_ACTIVE_UNIFORMS, &uniform_count);
if (uniform_count > 0)
Expand All @@ -105,26 +106,70 @@ void Context::glLinkProgram(GLuint program)

auto loc = gl.GetUniformLocation(program, uniform_name.get());

programr.uniforms.emplace(loc, uniform_info);
programInfo.uniforms.emplace(loc, uniform_info);
}
}
}

void Context::glUseProgram(unsigned int handle) {
auto it = programs.find(handle);
if (handle == 0) {
bound_program = 0;
return;
}

if (!validate_program_status(handle)) {
return;
}

// TODO: add optional performance warning for rebinding the same program
//if (handle == bound_program) {
// output_fmt("glUseProgram(program = %u): Program is already bound.", handle);
//}

bound_program = handle;
}

void Context::glDeleteProgram(GLuint program)
{
auto it = programs.find(program);
if (it == programs.end()) {
output_fmt("glUseProgram(program = %u): Invalid program handle.", handle);
output_fmt("glUseProgram(program = %u): Invalid program handle.", program);
return;
}

if (it->second.link_status == LinkStatus::UNCHECKED) {
output_fmt("glUseProgram(program = %u): Always check program link status before trying to use the object.", handle);
// note: this does not change which program is bound, even if it becomes invalid here

programs.erase(it);
}

void Context::validate_program_bound(std::string_view func_name)
{
if (bound_program == 0) {
output_fmt("%s: No program bound.", func_name.data());
return;
}
}

bool Context::validate_program_status(GLuint program)
{
auto it = programs.find(program);
if (it == programs.end()) {
output_fmt("glUseProgram(program = %u): Invalid program handle.", program);
return false;
}

if (it->second.link_status == LinkStatus::UNCHECKED) {
output_fmt("glUseProgram(program = %u): Always check program link status before trying to use the object.", program);
return false;
}

if (it->second.link_status == LinkStatus::FAILED) {
output_fmt("glUseProgram(program = %u): Program has a linker error.", handle);
return;
output_fmt("glUseProgram(program = %u): Program has a linker error.", program);
return false;
}

return true;
}
}
}

Expand Down