Files
Z3D/source/opengl/handles/shader_program_handle.cpp
2025-03-27 19:47:32 +01:00

158 lines
4.0 KiB
C++

#include "opengl/handles/shader_program_handle.hpp"
#include <string_view>
// 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<const shader_uniform> attributes
) const {
auto attribute_candidates = attribute_support_type{};
auto error = std::error_code{};
auto check_error = [&error, ec = static_cast<GLenum>(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(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(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<char, 256>{};
glGetActiveAttrib(
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<const shader_uniform> uniforms
) const {
auto uniform_candidates = uniform_support_type{};
auto error = std::error_code{};
auto check_error = [&error, ec = static_cast<GLenum>(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(id, uniform.name);
if (location == uniform.info.location)
{
uniform_candidates |= curr_uniform_flag;
ztu::logger::debug("[%] '%': %.", 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(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<char, 256>{};
glGetActiveUniform(
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;
}
bool shader_program_handle::valid() const
{
return id != 0;
}
}