#include "opengl/handles/shader_program_handle.hpp" #include // TODO remove #include "opengl/error.hpp" #include "util/logger.hpp" namespace zgl { shader_program_handle::attribute_support_type shader_program_handle::check_attribute_support( const std::span attributes ) const { auto attribute_candidates = attribute_support_type{}; auto error = std::error_code{}; auto check_error = [&error, ec = static_cast(GL_NO_ERROR)]() mutable -> std::error_code& { ec = glGetError(); if (ec != GL_NO_ERROR) { error = make_error_code(ec); } return error; }; auto curr_attribute_flag = attribute_support_type{ 1 }; for (const auto& attribute : attributes) { const auto location = glGetAttribLocation(program_id, attribute.name); if (location == attribute.info.location) { attribute_candidates |= curr_attribute_flag; } curr_attribute_flag <<= 1; } auto supported_attributes = attribute_support_type{}; GLint count; glGetProgramiv(program_id, GL_ACTIVE_ATTRIBUTES, &count); if (check_error()) ztu::logger::error("GL_err: %", error.message()); for (GLint i{}; i != count and attribute_candidates; ++i) { GLenum type; GLint size; GLsizei name_length; auto name = std::array{}; glGetActiveAttrib( program_id, i, name.size(), &name_length, &size, &type, name.data() ); if (check_error()) ztu::logger::error("GL_err: %", error.message()); const auto name_view = std::string_view(name.data(), name_length); auto attribute_index = attribute_support_type{}; for (auto candidates = attribute_candidates; candidates; candidates >>= 1) { if (candidates & 1) { const auto& attribute = attributes[attribute_index]; if (type == attribute.info.type and name_view == attribute.name) { const auto new_uniform_flag = attribute_support_type{ 1 } << attribute_index; supported_attributes |= new_uniform_flag; attribute_candidates ^= new_uniform_flag; } } ++attribute_index; } } return supported_attributes; } shader_program_handle::uniform_support_type shader_program_handle::check_uniform_support( const std::span uniforms ) const { auto uniform_candidates = uniform_support_type{}; auto error = std::error_code{}; auto check_error = [&error, ec = static_cast(GL_NO_ERROR)]() mutable -> std::error_code& { ec = glGetError(); if (ec != GL_NO_ERROR) { error = make_error_code(ec); } return error; }; auto curr_uniform_flag = uniform_support_type{ 1 }; for (const auto& uniform : uniforms) { const auto location = glGetUniformLocation(program_id, uniform.name); if (location == uniform.info.location) { uniform_candidates |= curr_uniform_flag; ztu::logger::debug("[%] '%': %.", program_id, uniform.name, location); } else { ztu::logger::debug("Expected '%' at % but was %.", uniform.name, uniform.info.location, location); } curr_uniform_flag <<= 1; } auto supported_uniforms = uniform_support_type{}; GLint count; glGetProgramiv(program_id, GL_ACTIVE_UNIFORMS, &count); if (check_error()) ztu::logger::error("GL_err: %", error.message()); for (GLint i{}; i != count and uniform_candidates; ++i) { GLenum type; GLint size; GLsizei name_length; auto name = std::array{}; glGetActiveUniform( program_id, i, name.size(), &name_length, &size, &type, name.data() ); if (check_error()) ztu::logger::error("GL_err: %", error.message()); const auto name_view = std::string_view(name.data(), name_length); auto uniform_index = uniform_support_type{}; for (auto candidates = uniform_candidates; candidates; candidates >>= 1) { if (candidates & 1) { const auto& uniform = uniforms[uniform_index]; if (type == uniform.info.type and name_view == uniform.name) { const auto new_uniform_flag = uniform_support_type{ 1 } << uniform_index; supported_uniforms |= new_uniform_flag; uniform_candidates ^= new_uniform_flag; } } ++uniform_index; } } return supported_uniforms; } }