158 lines
4.0 KiB
C++
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_program_variable> 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_program_variable> 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;
|
|
}
|
|
}
|