Route shader creation through renderer GL

This commit is contained in:
2026-06-03 07:03:50 +02:00
parent acdaf3bb8e
commit 1ae79ab3c1
6 changed files with 1123 additions and 67 deletions

View File

@@ -1,4 +1,5 @@
#include "renderer_gl/opengl_capabilities.h"
#include "renderer_gl/shader_bindings.h"
#include <array>
#include <limits>
@@ -1030,6 +1031,190 @@ pp::foundation::Result<std::int32_t> get_opengl_attribute_location(
dispatch.get_attrib_location(program_id, attribute_name));
}
pp::foundation::Result<OpenGlShaderCompileInfo> compile_opengl_shader_source(
std::uint32_t stage,
const char* source,
char* info_log,
std::int32_t info_log_capacity,
OpenGlShaderCompileDispatch dispatch) noexcept
{
if (dispatch.create_shader == nullptr
|| dispatch.shader_source == nullptr
|| dispatch.compile_shader == nullptr
|| dispatch.get_shader_integer == nullptr
|| dispatch.get_shader_info_log == nullptr) {
return pp::foundation::Result<OpenGlShaderCompileInfo>::failure(
pp::foundation::Status::invalid_argument("OpenGL shader compile dispatch callbacks must not be null"));
}
if (stage == 0U || source == nullptr || source[0] == '\0' || info_log == nullptr || info_log_capacity <= 0) {
return pp::foundation::Result<OpenGlShaderCompileInfo>::failure(
pp::foundation::Status::invalid_argument("OpenGL shader compile parameters are invalid"));
}
const auto shader_id = dispatch.create_shader(stage);
if (shader_id == 0U) {
return pp::foundation::Result<OpenGlShaderCompileInfo>::failure(
pp::foundation::Status::out_of_range("OpenGL shader allocation returned id 0"));
}
const char* const sources[] { source };
dispatch.shader_source(shader_id, 1, sources);
dispatch.compile_shader(shader_id);
OpenGlShaderCompileInfo info {
.shader_id = shader_id,
};
dispatch.get_shader_integer(shader_id, shader_compile_status_query(), &info.compile_status);
dispatch.get_shader_info_log(shader_id, info_log_capacity, &info.info_log_length, info_log);
return pp::foundation::Result<OpenGlShaderCompileInfo>::success(info);
}
pp::foundation::Status delete_opengl_shader(
std::uint32_t shader_id,
OpenGlShaderDeleteDispatch dispatch) noexcept
{
if (dispatch.delete_shader == nullptr) {
return pp::foundation::Status::invalid_argument("OpenGL shader delete dispatch callback must not be null");
}
if (shader_id == 0U) {
return pp::foundation::Status::success();
}
dispatch.delete_shader(shader_id);
return pp::foundation::Status::success();
}
pp::foundation::Result<OpenGlProgramLinkInfo> link_opengl_shader_program(
std::uint32_t vertex_shader_id,
std::uint32_t fragment_shader_id,
std::span<const OpenGlAttributeBinding> attribute_bindings,
char* info_log,
std::int32_t info_log_capacity,
OpenGlProgramLinkDispatch dispatch) noexcept
{
if (dispatch.create_program == nullptr
|| dispatch.attach_shader == nullptr
|| dispatch.delete_shader == nullptr
|| dispatch.link_program == nullptr
|| dispatch.get_attrib_location == nullptr
|| dispatch.bind_attrib_location == nullptr
|| dispatch.get_program_integer == nullptr
|| dispatch.get_program_info_log == nullptr) {
return pp::foundation::Result<OpenGlProgramLinkInfo>::failure(
pp::foundation::Status::invalid_argument("OpenGL program link dispatch callbacks must not be null"));
}
if (vertex_shader_id == 0U
|| fragment_shader_id == 0U
|| attribute_bindings.empty()
|| info_log == nullptr
|| info_log_capacity <= 0) {
return pp::foundation::Result<OpenGlProgramLinkInfo>::failure(
pp::foundation::Status::invalid_argument("OpenGL program link parameters are invalid"));
}
const auto program_id = dispatch.create_program();
if (program_id == 0U) {
return pp::foundation::Result<OpenGlProgramLinkInfo>::failure(
pp::foundation::Status::out_of_range("OpenGL program allocation returned id 0"));
}
dispatch.attach_shader(program_id, vertex_shader_id);
dispatch.attach_shader(program_id, fragment_shader_id);
dispatch.delete_shader(vertex_shader_id);
dispatch.delete_shader(fragment_shader_id);
dispatch.link_program(program_id);
for (const auto& binding : attribute_bindings) {
if (binding.name != nullptr && dispatch.get_attrib_location(program_id, binding.name) != -1) {
dispatch.bind_attrib_location(program_id, binding.location, binding.name);
}
}
OpenGlProgramLinkInfo info {
.program_id = program_id,
};
dispatch.link_program(program_id);
dispatch.get_program_integer(program_id, program_link_status_query(), &info.link_status);
dispatch.get_program_info_log(program_id, info_log_capacity, &info.info_log_length, info_log);
return pp::foundation::Result<OpenGlProgramLinkInfo>::success(info);
}
pp::foundation::Result<std::int32_t> query_opengl_program_integer(
std::uint32_t program_id,
std::uint32_t query,
OpenGlProgramIntegerDispatch dispatch) noexcept
{
if (dispatch.get_program_integer == nullptr) {
return pp::foundation::Result<std::int32_t>::failure(
pp::foundation::Status::invalid_argument("OpenGL program integer dispatch callback must not be null"));
}
if (program_id == 0U || query == 0U) {
return pp::foundation::Result<std::int32_t>::failure(
pp::foundation::Status::invalid_argument("OpenGL program integer parameters are invalid"));
}
std::int32_t value = 0;
dispatch.get_program_integer(program_id, query, &value);
return pp::foundation::Result<std::int32_t>::success(value);
}
pp::foundation::Result<OpenGlActiveUniformInfo> get_opengl_active_uniform(
std::uint32_t program_id,
std::uint32_t index,
char* name,
std::int32_t name_capacity,
OpenGlActiveUniformDispatch dispatch) noexcept
{
if (dispatch.get_active_uniform == nullptr) {
return pp::foundation::Result<OpenGlActiveUniformInfo>::failure(
pp::foundation::Status::invalid_argument("OpenGL active uniform dispatch callback must not be null"));
}
if (program_id == 0U || name == nullptr || name_capacity <= 0) {
return pp::foundation::Result<OpenGlActiveUniformInfo>::failure(
pp::foundation::Status::invalid_argument("OpenGL active uniform parameters are invalid"));
}
OpenGlActiveUniformInfo info {};
dispatch.get_active_uniform(
program_id,
index,
name_capacity,
&info.length,
&info.size,
&info.type,
name);
if (info.length >= 0 && info.length < name_capacity) {
name[info.length] = '\0';
} else {
name[name_capacity - 1] = '\0';
}
return pp::foundation::Result<OpenGlActiveUniformInfo>::success(info);
}
pp::foundation::Result<std::int32_t> get_opengl_uniform_location(
std::uint32_t program_id,
const char* uniform_name,
OpenGlUniformLocationDispatch dispatch) noexcept
{
if (dispatch.get_uniform_location == nullptr) {
return pp::foundation::Result<std::int32_t>::failure(
pp::foundation::Status::invalid_argument("OpenGL uniform-location dispatch callback must not be null"));
}
if (program_id == 0U || uniform_name == nullptr || uniform_name[0] == '\0') {
return pp::foundation::Result<std::int32_t>::failure(
pp::foundation::Status::invalid_argument("OpenGL uniform-location parameters are invalid"));
}
return pp::foundation::Result<std::int32_t>::success(
dispatch.get_uniform_location(program_id, uniform_name));
}
std::uint32_t extension_count_query() noexcept
{
return gl_num_extensions;

View File

@@ -9,6 +9,8 @@
namespace pp::renderer::gl {
struct OpenGlAttributeBinding;
struct OpenGlRuntime {
bool desktop_gl = false;
bool gles = false;
@@ -148,6 +150,24 @@ struct OpenGlTexture2DReadbackResult {
bool pixels_read = false;
};
struct OpenGlShaderCompileInfo {
std::uint32_t shader_id = 0;
std::int32_t compile_status = 0;
std::int32_t info_log_length = 0;
};
struct OpenGlProgramLinkInfo {
std::uint32_t program_id = 0;
std::int32_t link_status = 0;
std::int32_t info_log_length = 0;
};
struct OpenGlActiveUniformInfo {
std::int32_t length = 0;
std::int32_t size = 0;
std::uint32_t type = 0;
};
struct OpenGlFramebufferRect {
std::int32_t x0 = 0;
std::int32_t y0 = 0;
@@ -232,6 +252,47 @@ using OpenGlUniformMatrix4fvFn = void (*)(
using OpenGlUniform1iFn = void (*)(std::int32_t location, std::int32_t value) noexcept;
using OpenGlUniform1fFn = void (*)(std::int32_t location, float value) noexcept;
using OpenGlGetAttribLocationFn = std::int32_t (*)(std::uint32_t program, const char* name) noexcept;
using OpenGlCreateShaderFn = std::uint32_t (*)(std::uint32_t stage) noexcept;
using OpenGlShaderSourceFn = void (*)(
std::uint32_t shader,
std::int32_t count,
const char* const* sources) noexcept;
using OpenGlCompileShaderFn = void (*)(std::uint32_t shader) noexcept;
using OpenGlGetShaderIntegerFn = void (*)(
std::uint32_t shader,
std::uint32_t query,
std::int32_t* value) noexcept;
using OpenGlGetShaderInfoLogFn = void (*)(
std::uint32_t shader,
std::int32_t capacity,
std::int32_t* length,
char* info_log) noexcept;
using OpenGlDeleteShaderFn = void (*)(std::uint32_t shader) noexcept;
using OpenGlCreateProgramFn = std::uint32_t (*)() noexcept;
using OpenGlAttachShaderFn = void (*)(std::uint32_t program, std::uint32_t shader) noexcept;
using OpenGlLinkProgramFn = void (*)(std::uint32_t program) noexcept;
using OpenGlBindAttribLocationFn = void (*)(
std::uint32_t program,
std::uint32_t location,
const char* name) noexcept;
using OpenGlGetProgramIntegerFn = void (*)(
std::uint32_t program,
std::uint32_t query,
std::int32_t* value) noexcept;
using OpenGlGetProgramInfoLogFn = void (*)(
std::uint32_t program,
std::int32_t capacity,
std::int32_t* length,
char* info_log) noexcept;
using OpenGlGetActiveUniformFn = void (*)(
std::uint32_t program,
std::uint32_t index,
std::int32_t capacity,
std::int32_t* length,
std::int32_t* size,
std::uint32_t* type,
char* name) noexcept;
using OpenGlGetUniformLocationFn = std::int32_t (*)(std::uint32_t program, const char* name) noexcept;
using OpenGlBindFramebufferFn = void (*)(std::uint32_t target, std::uint32_t framebuffer) noexcept;
using OpenGlBindTextureFn = void (*)(std::uint32_t target, std::uint32_t texture) noexcept;
using OpenGlBindSamplerFn = void (*)(std::uint32_t unit, std::uint32_t sampler) noexcept;
@@ -482,6 +543,41 @@ struct OpenGlAttributeLocationDispatch {
OpenGlGetAttribLocationFn get_attrib_location = nullptr;
};
struct OpenGlShaderCompileDispatch {
OpenGlCreateShaderFn create_shader = nullptr;
OpenGlShaderSourceFn shader_source = nullptr;
OpenGlCompileShaderFn compile_shader = nullptr;
OpenGlGetShaderIntegerFn get_shader_integer = nullptr;
OpenGlGetShaderInfoLogFn get_shader_info_log = nullptr;
};
struct OpenGlShaderDeleteDispatch {
OpenGlDeleteShaderFn delete_shader = nullptr;
};
struct OpenGlProgramLinkDispatch {
OpenGlCreateProgramFn create_program = nullptr;
OpenGlAttachShaderFn attach_shader = nullptr;
OpenGlDeleteShaderFn delete_shader = nullptr;
OpenGlLinkProgramFn link_program = nullptr;
OpenGlGetAttribLocationFn get_attrib_location = nullptr;
OpenGlBindAttribLocationFn bind_attrib_location = nullptr;
OpenGlGetProgramIntegerFn get_program_integer = nullptr;
OpenGlGetProgramInfoLogFn get_program_info_log = nullptr;
};
struct OpenGlProgramIntegerDispatch {
OpenGlGetProgramIntegerFn get_program_integer = nullptr;
};
struct OpenGlActiveUniformDispatch {
OpenGlGetActiveUniformFn get_active_uniform = nullptr;
};
struct OpenGlUniformLocationDispatch {
OpenGlGetUniformLocationFn get_uniform_location = nullptr;
};
[[nodiscard]] OpenGlCapabilities detect_opengl_capabilities(
std::span<const std::string_view> extensions,
OpenGlRuntime runtime) noexcept;
@@ -603,6 +699,36 @@ struct OpenGlAttributeLocationDispatch {
std::uint32_t program_id,
const char* attribute_name,
OpenGlAttributeLocationDispatch dispatch) noexcept;
[[nodiscard]] pp::foundation::Result<OpenGlShaderCompileInfo> compile_opengl_shader_source(
std::uint32_t stage,
const char* source,
char* info_log,
std::int32_t info_log_capacity,
OpenGlShaderCompileDispatch dispatch) noexcept;
[[nodiscard]] pp::foundation::Status delete_opengl_shader(
std::uint32_t shader_id,
OpenGlShaderDeleteDispatch dispatch) noexcept;
[[nodiscard]] pp::foundation::Result<OpenGlProgramLinkInfo> link_opengl_shader_program(
std::uint32_t vertex_shader_id,
std::uint32_t fragment_shader_id,
std::span<const OpenGlAttributeBinding> attribute_bindings,
char* info_log,
std::int32_t info_log_capacity,
OpenGlProgramLinkDispatch dispatch) noexcept;
[[nodiscard]] pp::foundation::Result<std::int32_t> query_opengl_program_integer(
std::uint32_t program_id,
std::uint32_t query,
OpenGlProgramIntegerDispatch dispatch) noexcept;
[[nodiscard]] pp::foundation::Result<OpenGlActiveUniformInfo> get_opengl_active_uniform(
std::uint32_t program_id,
std::uint32_t index,
char* name,
std::int32_t name_capacity,
OpenGlActiveUniformDispatch dispatch) noexcept;
[[nodiscard]] pp::foundation::Result<std::int32_t> get_opengl_uniform_location(
std::uint32_t program_id,
const char* uniform_name,
OpenGlUniformLocationDispatch dispatch) noexcept;
[[nodiscard]] std::uint32_t extension_count_query() noexcept;
[[nodiscard]] std::uint32_t extension_string_name() noexcept;

View File

@@ -88,6 +88,125 @@ std::int32_t get_opengl_attrib_location(std::uint32_t program, const char* name)
return static_cast<std::int32_t>(glGetAttribLocation(static_cast<GLuint>(program), name));
}
std::uint32_t create_opengl_shader(std::uint32_t stage) noexcept
{
return static_cast<std::uint32_t>(glCreateShader(static_cast<GLenum>(stage)));
}
void set_opengl_shader_source(
std::uint32_t shader,
std::int32_t count,
const char* const* sources) noexcept
{
glShaderSource(
static_cast<GLuint>(shader),
static_cast<GLsizei>(count),
reinterpret_cast<const GLchar* const*>(sources),
nullptr);
}
void compile_opengl_shader(std::uint32_t shader) noexcept
{
glCompileShader(static_cast<GLuint>(shader));
}
void query_opengl_shader_integer(
std::uint32_t shader,
std::uint32_t query,
std::int32_t* value) noexcept
{
glGetShaderiv(
static_cast<GLuint>(shader),
static_cast<GLenum>(query),
reinterpret_cast<GLint*>(value));
}
void get_opengl_shader_info_log(
std::uint32_t shader,
std::int32_t capacity,
std::int32_t* length,
char* info_log) noexcept
{
glGetShaderInfoLog(
static_cast<GLuint>(shader),
static_cast<GLsizei>(capacity),
reinterpret_cast<GLsizei*>(length),
reinterpret_cast<GLchar*>(info_log));
}
void delete_opengl_shader(std::uint32_t shader) noexcept
{
glDeleteShader(static_cast<GLuint>(shader));
}
std::uint32_t create_opengl_program() noexcept
{
return static_cast<std::uint32_t>(glCreateProgram());
}
void attach_opengl_shader(std::uint32_t program, std::uint32_t shader) noexcept
{
glAttachShader(static_cast<GLuint>(program), static_cast<GLuint>(shader));
}
void link_opengl_program(std::uint32_t program) noexcept
{
glLinkProgram(static_cast<GLuint>(program));
}
void bind_opengl_attrib_location(std::uint32_t program, std::uint32_t location, const char* name) noexcept
{
glBindAttribLocation(static_cast<GLuint>(program), static_cast<GLuint>(location), name);
}
void query_opengl_program_integer(
std::uint32_t program,
std::uint32_t query,
std::int32_t* value) noexcept
{
glGetProgramiv(
static_cast<GLuint>(program),
static_cast<GLenum>(query),
reinterpret_cast<GLint*>(value));
}
void get_opengl_program_info_log(
std::uint32_t program,
std::int32_t capacity,
std::int32_t* length,
char* info_log) noexcept
{
glGetProgramInfoLog(
static_cast<GLuint>(program),
static_cast<GLsizei>(capacity),
reinterpret_cast<GLsizei*>(length),
reinterpret_cast<GLchar*>(info_log));
}
void get_opengl_active_uniform(
std::uint32_t program,
std::uint32_t index,
std::int32_t capacity,
std::int32_t* length,
std::int32_t* size,
std::uint32_t* type,
char* name) noexcept
{
glGetActiveUniform(
static_cast<GLuint>(program),
static_cast<GLuint>(index),
static_cast<GLsizei>(capacity),
reinterpret_cast<GLsizei*>(length),
reinterpret_cast<GLint*>(size),
reinterpret_cast<GLenum*>(type),
reinterpret_cast<GLchar*>(name));
}
std::int32_t get_opengl_uniform_location(std::uint32_t program, const char* name) noexcept
{
return static_cast<std::int32_t>(glGetUniformLocation(static_cast<GLuint>(program), name));
}
}
std::map<kShader, Shader> ShaderManager::m_shaders;
@@ -247,113 +366,212 @@ bool Shader::create(const std::string& vertex, const std::string& fragment)
bool ret = true;
App::I->render_task([this, &ret, vertex, fragment]
{
GLint status;
static char infolog[4096];
int infolen;
const GLchar* source;
auto vs = glCreateShader(vertex_shader_stage());
if (!vs)
const auto vertex_shader = pp::renderer::gl::compile_opengl_shader_source(
pp::renderer::gl::vertex_shader_stage(),
vertex.c_str(),
infolog,
static_cast<std::int32_t>(sizeof(infolog)),
pp::renderer::gl::OpenGlShaderCompileDispatch {
.create_shader = create_opengl_shader,
.shader_source = set_opengl_shader_source,
.compile_shader = compile_opengl_shader,
.get_shader_integer = query_opengl_shader_integer,
.get_shader_info_log = get_opengl_shader_info_log,
});
if (!vertex_shader.ok())
{
ret = false;
LOG("Shader::create() vertex compile failed because: %s", vertex_shader.status().message);
return;
}
source = vertex.c_str();
glShaderSource(vs, 1, &source, nullptr);
glCompileShader(vs);
glGetShaderiv(vs, shader_compile_status_query(), &status);
glGetShaderInfoLog(vs, sizeof(infolog), &infolen, infolog);
if (infolen > 0)
if (vertex_shader.value().info_log_length > 0)
{
LOG("\nVERTEX SHADER: %s", m_path.c_str());
parse_error(infolog, vertex);
}
if (status == 0)
if (vertex_shader.value().compile_status == 0)
{
glDeleteShader(vs);
const auto status = pp::renderer::gl::delete_opengl_shader(
vertex_shader.value().shader_id,
pp::renderer::gl::OpenGlShaderDeleteDispatch {
.delete_shader = delete_opengl_shader,
});
if (!status.ok())
LOG("Shader::create() vertex shader cleanup failed because: %s", status.message);
ret = false;
return;
}
auto fs = glCreateShader(fragment_shader_stage());
if (!fs)
const auto fragment_shader = pp::renderer::gl::compile_opengl_shader_source(
pp::renderer::gl::fragment_shader_stage(),
fragment.c_str(),
infolog,
static_cast<std::int32_t>(sizeof(infolog)),
pp::renderer::gl::OpenGlShaderCompileDispatch {
.create_shader = create_opengl_shader,
.shader_source = set_opengl_shader_source,
.compile_shader = compile_opengl_shader,
.get_shader_integer = query_opengl_shader_integer,
.get_shader_info_log = get_opengl_shader_info_log,
});
if (!fragment_shader.ok())
{
glDeleteShader(vs);
const auto status = pp::renderer::gl::delete_opengl_shader(
vertex_shader.value().shader_id,
pp::renderer::gl::OpenGlShaderDeleteDispatch {
.delete_shader = delete_opengl_shader,
});
if (!status.ok())
LOG("Shader::create() vertex shader cleanup failed because: %s", status.message);
ret = false;
LOG("Shader::create() fragment compile failed because: %s", fragment_shader.status().message);
return;
}
source = fragment.c_str();
glShaderSource(fs, 1, &source, nullptr);
glCompileShader(fs);
glGetShaderiv(fs, shader_compile_status_query(), &status);
glGetShaderInfoLog(fs, sizeof(infolog), &infolen, infolog);
if (infolen > 0)
if (fragment_shader.value().info_log_length > 0)
{
LOG("\nFRAGMENT SHADER: %s", m_path.c_str());
parse_error(infolog, fragment);
}
if (status == 0)
if (fragment_shader.value().compile_status == 0)
{
glDeleteShader(vs);
glDeleteShader(fs);
const auto vertex_cleanup = pp::renderer::gl::delete_opengl_shader(
vertex_shader.value().shader_id,
pp::renderer::gl::OpenGlShaderDeleteDispatch {
.delete_shader = delete_opengl_shader,
});
const auto fragment_cleanup = pp::renderer::gl::delete_opengl_shader(
fragment_shader.value().shader_id,
pp::renderer::gl::OpenGlShaderDeleteDispatch {
.delete_shader = delete_opengl_shader,
});
if (!vertex_cleanup.ok())
LOG("Shader::create() vertex shader cleanup failed because: %s", vertex_cleanup.message);
if (!fragment_cleanup.ok())
LOG("Shader::create() fragment shader cleanup failed because: %s", fragment_cleanup.message);
ret = false;
return;
}
auto ps = glCreateProgram();
if (!ps)
const auto program = pp::renderer::gl::link_opengl_shader_program(
vertex_shader.value().shader_id,
fragment_shader.value().shader_id,
pp::renderer::gl::panopainter_shader_attribute_bindings(),
infolog,
static_cast<std::int32_t>(sizeof(infolog)),
pp::renderer::gl::OpenGlProgramLinkDispatch {
.create_program = create_opengl_program,
.attach_shader = attach_opengl_shader,
.delete_shader = delete_opengl_shader,
.link_program = link_opengl_program,
.get_attrib_location = get_opengl_attrib_location,
.bind_attrib_location = bind_opengl_attrib_location,
.get_program_integer = query_opengl_program_integer,
.get_program_info_log = get_opengl_program_info_log,
});
if (!program.ok())
{
glDeleteShader(vs);
glDeleteShader(fs);
const auto vertex_cleanup = pp::renderer::gl::delete_opengl_shader(
vertex_shader.value().shader_id,
pp::renderer::gl::OpenGlShaderDeleteDispatch {
.delete_shader = delete_opengl_shader,
});
const auto fragment_cleanup = pp::renderer::gl::delete_opengl_shader(
fragment_shader.value().shader_id,
pp::renderer::gl::OpenGlShaderDeleteDispatch {
.delete_shader = delete_opengl_shader,
});
if (!vertex_cleanup.ok())
LOG("Shader::create() vertex shader cleanup failed because: %s", vertex_cleanup.message);
if (!fragment_cleanup.ok())
LOG("Shader::create() fragment shader cleanup failed because: %s", fragment_cleanup.message);
ret = false;
LOG("Shader::create() program link failed because: %s", program.status().message);
return;
}
glAttachShader(ps, vs);
glAttachShader(ps, fs);
glDeleteShader(vs);
glDeleteShader(fs);
glLinkProgram(ps);
for (const auto& binding : pp::renderer::gl::panopainter_shader_attribute_bindings())
{
if (glGetAttribLocation(ps, binding.name) != -1)
glBindAttribLocation(ps, static_cast<GLuint>(binding.location), binding.name);
}
glLinkProgram(ps);
glGetProgramiv(ps, program_link_status_query(), &status);
glGetProgramInfoLog(ps, sizeof(infolog), &infolen, infolog);
if (infolen > 0)
if (program.value().info_log_length > 0)
LOG("LINK SHADER: %s\n%s", m_path.c_str(), infolog);
if (status == 0)
if (program.value().link_status == 0)
{
glDeleteProgram(ps);
const auto status = pp::renderer::gl::delete_opengl_program(
program.value().program_id,
pp::renderer::gl::OpenGlProgramDeleteDispatch {
.use_program = use_opengl_program,
.delete_program = delete_opengl_program,
});
if (!status.ok())
LOG("Shader::create() program cleanup failed because: %s", status.message);
ret = false;
return;
}
const auto cleanup_program = [](std::uint32_t program_id) noexcept {
const auto status = pp::renderer::gl::delete_opengl_program(
program_id,
pp::renderer::gl::OpenGlProgramDeleteDispatch {
.use_program = use_opengl_program,
.delete_program = delete_opengl_program,
});
if (!status.ok())
LOG("Shader::create() program cleanup failed because: %s", status.message);
};
// Parse shader uniforms
{
GLint count;
GLint size; // size of the variable
GLenum type; // type of the variable (float, vec3 or mat4, etc)
const GLsizei bufSize = 64; // maximum name length
GLchar name[bufSize]; // variable name in GLSL
GLsizei length; // name length
glGetProgramiv(ps, active_uniform_count_query(), &count);
const auto uniform_count = pp::renderer::gl::query_opengl_program_integer(
program.value().program_id,
pp::renderer::gl::active_uniform_count_query(),
pp::renderer::gl::OpenGlProgramIntegerDispatch {
.get_program_integer = query_opengl_program_integer,
});
if (!uniform_count.ok())
{
LOG("Shader::create() uniform discovery failed because: %s", uniform_count.status().message);
cleanup_program(program.value().program_id);
ret = false;
return;
}
constexpr std::int32_t bufSize = 64; // maximum name length
char uniform_name[bufSize]; // variable name in GLSL
const auto count = uniform_count.value();
for (int i = 0; i < count; i++)
{
glGetActiveUniform(ps, (GLuint)i, bufSize, &length, &size, &type, name);
name[length] = 0;
kShaderUniform id = static_cast<kShaderUniform>(pp::renderer::gl::shader_uniform_id(name));
const auto uniform = pp::renderer::gl::get_opengl_active_uniform(
program.value().program_id,
static_cast<std::uint32_t>(i),
uniform_name,
bufSize,
pp::renderer::gl::OpenGlActiveUniformDispatch {
.get_active_uniform = get_opengl_active_uniform,
});
if (!uniform.ok())
{
LOG("Shader::create() active uniform discovery failed because: %s", uniform.status().message);
cleanup_program(program.value().program_id);
ret = false;
return;
}
kShaderUniform id = static_cast<kShaderUniform>(pp::renderer::gl::shader_uniform_id(uniform_name));
if (m_umap.find(id) != m_umap.end())
LOG("UNIFORM ALREADY DEFINED: %s", name);
m_umap[id] = glGetUniformLocation(ps, name);
//printf("Uniform #%d Type: %u Name: %s Loc: %d\n", i, type, name, glGetUniformLocation(ps, name));
LOG("UNIFORM ALREADY DEFINED: %s", uniform_name);
const auto location = pp::renderer::gl::get_opengl_uniform_location(
program.value().program_id,
uniform_name,
pp::renderer::gl::OpenGlUniformLocationDispatch {
.get_uniform_location = get_opengl_uniform_location,
});
if (!location.ok())
{
LOG("Shader::create() uniform location failed because: %s", location.status().message);
cleanup_program(program.value().program_id);
ret = false;
return;
}
m_umap[id] = location.value();
}
}
prog = ps;
prog = program.value().program_id;
});
return ret;