...
This commit is contained in:
@@ -11,13 +11,13 @@
|
||||
namespace zgl
|
||||
{
|
||||
inline shader_program_data::shader_program_data(GLuint program_id)
|
||||
: m_handle{ program_id } {}
|
||||
: handle{ program_id } {}
|
||||
|
||||
|
||||
inline shader_program_data::shader_program_data(shader_program_data&& other) noexcept
|
||||
{
|
||||
m_handle = other.m_handle;
|
||||
other.m_handle.program_id = 0;
|
||||
handle = other.handle;
|
||||
other.handle.id = 0;
|
||||
}
|
||||
|
||||
inline shader_program_data& shader_program_data::operator=(shader_program_data&& other) noexcept
|
||||
@@ -25,21 +25,16 @@ inline shader_program_data& shader_program_data::operator=(shader_program_data&&
|
||||
if (&other != this)
|
||||
{
|
||||
this->~shader_program_data();
|
||||
m_handle = other.m_handle;
|
||||
other.m_handle.program_id = 0;
|
||||
handle = other.handle;
|
||||
other.handle.id = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline shader_program_data::~shader_program_data()
|
||||
{
|
||||
if (m_handle.program_id) {
|
||||
glDeleteProgram(m_handle.program_id);
|
||||
if (handle.id) {
|
||||
glDeleteProgram(handle.id);
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] inline shader_program_handle shader_program_data::handle() const
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,10 @@
|
||||
|
||||
namespace zgl
|
||||
{
|
||||
inline texture_data::texture_data(const GLuint texture_id)
|
||||
: m_handle{ texture_id } {}
|
||||
|
||||
inline texture_data::texture_data(texture_data&& other) noexcept
|
||||
: m_handle{ other.m_handle }
|
||||
: handle{ other.handle }
|
||||
{
|
||||
other.m_handle.texture_id = 0;
|
||||
other.handle.id = 0;
|
||||
}
|
||||
|
||||
inline texture_data& texture_data::operator=(texture_data&& other) noexcept
|
||||
@@ -19,61 +16,24 @@ inline texture_data& texture_data::operator=(texture_data&& other) noexcept
|
||||
{
|
||||
this->~texture_data();
|
||||
|
||||
m_handle = other.m_handle;
|
||||
handle = other.handle;
|
||||
|
||||
other.m_handle.texture_id = 0;
|
||||
other.handle.id = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::error_code texture_data::build_from(
|
||||
std::span<const T> buffer,
|
||||
const GLenum format,
|
||||
const GLenum type,
|
||||
const GLsizei width,
|
||||
const GLsizei height,
|
||||
texture_data& data
|
||||
) {
|
||||
GLuint texture_id;
|
||||
|
||||
glGenTextures(1, &texture_id);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D, 0,
|
||||
GL_RGBA8,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
format, type,
|
||||
buffer.data()
|
||||
);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
data = texture_data(texture_id);
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
inline texture_data::~texture_data()
|
||||
{
|
||||
if (m_handle.texture_id)
|
||||
if (handle.id)
|
||||
{
|
||||
glDeleteTextures(1, &m_handle.texture_id);
|
||||
glDeleteTextures(1, &handle.id);
|
||||
}
|
||||
}
|
||||
|
||||
inline texture_handle texture_data::handle() const
|
||||
{
|
||||
return { m_handle.texture_id };
|
||||
return { handle.id };
|
||||
}
|
||||
}
|
||||
|
||||
133
source/opengl/data_managers/mesh_vertex_buffer_manager.cpp
Normal file
133
source/opengl/data_managers/mesh_vertex_buffer_manager.cpp
Normal file
@@ -0,0 +1,133 @@
|
||||
#include "opengl/data_managers/mesh_vertex_buffer_manager.hpp"
|
||||
|
||||
void zgl::mesh_vertex_buffer_manager::process(store_type& store)
|
||||
{
|
||||
for (const auto& [ id, mesh ] : store)
|
||||
{
|
||||
// The ireator must reutrn a pair containing the components and a tuple of spans
|
||||
}
|
||||
}
|
||||
|
||||
template<typename C, typename... Ts>
|
||||
void dynamic_vertex_buffer<C, Ts...>::build_vertex_buffer(
|
||||
std::vector<ztu::u8>& vertex_buffer,
|
||||
std::size_t& component_count,
|
||||
std::array<GLenum, sizeof...(Ts)>& component_types,
|
||||
std::array<GLint, sizeof...(Ts)>& component_lengths,
|
||||
GLsizei& stride
|
||||
) const {
|
||||
const auto for_all_components = [&]<typename T>(auto&& f, const T default_value)
|
||||
{
|
||||
return std::apply(
|
||||
[&](const auto&... component_buffer)
|
||||
{
|
||||
std::array<T, sizeof...(component_buffer)> results{};
|
||||
auto i = std::size_t{};
|
||||
(
|
||||
(
|
||||
results[i] = [&](const auto& buffer, const auto index) -> T
|
||||
{
|
||||
if ((m_components & C{ 1 << index }) != C{})
|
||||
{
|
||||
return f(buffer, index);
|
||||
}
|
||||
return default_value;
|
||||
}(component_buffer, i),
|
||||
++i
|
||||
),
|
||||
...
|
||||
);
|
||||
return results;
|
||||
},
|
||||
m_component_buffers
|
||||
);
|
||||
};
|
||||
|
||||
component_count = 0;
|
||||
component_types = for_all_components(
|
||||
ztu::specialised_lambda
|
||||
{
|
||||
[&component_count]<numeric_type Component, std::size_t Count>(const std::vector<std::array<Component, Count>>&, std::size_t)
|
||||
{
|
||||
++component_count;
|
||||
return zgl::type_utils::to_gl_type<Component>();
|
||||
},
|
||||
[&component_count]<numeric_type Component>(const std::vector<Component>&, std::size_t)
|
||||
{
|
||||
++component_count;
|
||||
return zgl::type_utils::to_gl_type<Component>();
|
||||
}
|
||||
},
|
||||
GLenum{ GL_INVALID_VALUE }
|
||||
);
|
||||
|
||||
const auto element_counts = for_all_components(
|
||||
[]<class Component>(const std::vector<Component>& buffer, std::size_t)
|
||||
{
|
||||
return buffer.size();
|
||||
},
|
||||
std::numeric_limits<std::size_t>::max()
|
||||
);
|
||||
|
||||
const auto minimum_element_count = std::ranges::min(element_counts);
|
||||
|
||||
component_lengths = for_all_components(
|
||||
ztu::specialised_lambda
|
||||
{
|
||||
[]<class Component>(const std::vector<Component>&, std::size_t)
|
||||
{
|
||||
return 1;
|
||||
},
|
||||
[]<class Component, std::size_t Count>(const std::vector<std::array<Component, Count>>&, std::size_t)
|
||||
{
|
||||
return Count;
|
||||
}
|
||||
},
|
||||
GLsizei{ 0 }
|
||||
);
|
||||
|
||||
auto component_sizes = std::array<GLsizei, sizeof...(Ts)>{};
|
||||
for (std::size_t i{}; i != component_sizes.size(); ++i)
|
||||
{
|
||||
component_sizes[i] = component_lengths[i] * zgl::type_utils::size_of(component_types[i]);
|
||||
}
|
||||
|
||||
const auto total_size = minimum_element_count * std::accumulate(
|
||||
component_sizes.begin(),
|
||||
component_sizes.end(),
|
||||
GLsizei{ 0 }
|
||||
);
|
||||
|
||||
vertex_buffer.resize(total_size);
|
||||
|
||||
// Calculate offsets and stride
|
||||
auto component_offsets = component_sizes;
|
||||
stride = 0;
|
||||
for (std::size_t i{}; i != component_offsets.size(); ++i) {
|
||||
component_offsets[i] = stride;
|
||||
stride += component_sizes[i];
|
||||
}
|
||||
|
||||
// Copy all the components over one by one
|
||||
for_all_components(
|
||||
[&]<class Component>(const std::vector<Component>& buffer, std::size_t index)
|
||||
{
|
||||
std::size_t pos = component_offsets[index];
|
||||
for (std::size_t i{}; i != minimum_element_count; ++i)
|
||||
{
|
||||
std::memcpy(
|
||||
&vertex_buffer[pos],
|
||||
buffer[i].data(),
|
||||
component_sizes[index]
|
||||
);
|
||||
pos += stride;
|
||||
}
|
||||
return 0;
|
||||
},
|
||||
0
|
||||
);
|
||||
|
||||
// remove values of unused components
|
||||
std::ignore = std::ranges::remove(component_lengths, 0);
|
||||
std::ignore = std::ranges::remove(component_types, GL_INVALID_VALUE);
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
#include "opengl/data_uploaders/shader_compiler.hpp"
|
||||
#include "opengl/data_managers/shader_manager.hpp"
|
||||
|
||||
#include <numeric>
|
||||
#include <bits/ranges_algobase.h>
|
||||
|
||||
#include "opengl/error.hpp"
|
||||
#include "util/logger.hpp"
|
||||
|
||||
|
||||
@@ -33,13 +35,17 @@ struct prioritized_metadata_comparator
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr auto gl_shader_types = std::array<GLenum, zgl::shading::stage::count>{
|
||||
GL_VERTEX_SHADER,
|
||||
GL_TESS_CONTROL_SHADER,
|
||||
GL_TESS_EVALUATION_SHADER,
|
||||
GL_GEOMETRY_SHADER,
|
||||
GL_FRAGMENT_SHADER
|
||||
};
|
||||
|
||||
zgl::shader_handle zgl::shader_program_compiler::find_shader(
|
||||
std::optional<std::pair<zgl::shader_metadata, zgl::shader_handle>> zgl::shader_manager::find_shader(
|
||||
const shading::shader_requirements& requirements
|
||||
) {
|
||||
|
||||
auto handle = shader_handle{};
|
||||
|
||||
auto shader_it = std::ranges::lower_bound(
|
||||
m_shader_lookup,
|
||||
std::pair{ requirements.geometry, requirements.stage },
|
||||
@@ -51,9 +57,6 @@ zgl::shader_handle zgl::shader_program_compiler::find_shader(
|
||||
}
|
||||
);
|
||||
|
||||
dynamic_shader_source_store::id_type source_id{};
|
||||
shading::features::generic::type to_be_enabled{};
|
||||
|
||||
while (
|
||||
shader_it != m_shader_lookup.end() and
|
||||
shader_it->first.geometry == requirements.geometry and
|
||||
@@ -67,36 +70,16 @@ zgl::shader_handle zgl::shader_program_compiler::find_shader(
|
||||
|
||||
if (unwanted_static_features == 0 and missing_dynamic_features == 0)
|
||||
{
|
||||
to_be_enabled = req.features & static_enable;
|
||||
source_id = id;
|
||||
|
||||
res.static_enabled = features & ~dynamic_enable & ~unwanted_features;
|
||||
res.dynamic_enable = dynamic_enable;
|
||||
|
||||
break;
|
||||
return std::pair{ meta, data.handle };
|
||||
}
|
||||
|
||||
++shader_it;
|
||||
}
|
||||
|
||||
if (source_id)
|
||||
{
|
||||
const auto [ shader_source_it, source_found ] = shader_sources.find(source_id);
|
||||
if (source_found)
|
||||
{
|
||||
get_define_strings(
|
||||
req.geometry,
|
||||
to_be_enabled,
|
||||
res.string_count,
|
||||
shader_strings
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return handle;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void zgl::shader_program_compiler::compile_shaders(
|
||||
void zgl::shader_manager::get_handles(
|
||||
const dynamic_shader_source_store& shader_sources,
|
||||
std::span<const shading::shader_set_requirements> requirements,
|
||||
std::span<shader_set_metadata> metadata,
|
||||
@@ -119,8 +102,15 @@ void zgl::shader_program_compiler::compile_shaders(
|
||||
for (auto [ stage_index, handle ] : std::ranges::views::enumerate(shader_set.stages))
|
||||
{
|
||||
shader_req.stage = static_cast<shading::stage::types>(stage_index);
|
||||
handle = find_shader(shader_req);
|
||||
if (not handle.valid())
|
||||
|
||||
if (auto shader_match = find_shader(shader_req))
|
||||
{
|
||||
const auto& [ shader_meta, shader_handle ] = *shader_match;
|
||||
shader_set_meta.static_enabled |= shader_meta.static_enabled;
|
||||
shader_set_meta.dynamic_enable |= shader_meta.dynamic_enable;
|
||||
handle = shader_handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_source_requirement_buffer.push_back(shader_req);
|
||||
}
|
||||
@@ -132,7 +122,7 @@ void zgl::shader_program_compiler::compile_shaders(
|
||||
m_preprocessed_shader_source_metadata_buffer.resize(m_source_requirement_buffer.size());
|
||||
m_source_strings_buffer.clear();
|
||||
|
||||
m_preprocessor.fetch_shader_sources(
|
||||
m_preprocessor.get_shader_sources(
|
||||
shader_sources,
|
||||
m_source_requirement_buffer,
|
||||
m_preprocessed_shader_source_metadata_buffer,
|
||||
@@ -147,32 +137,39 @@ void zgl::shader_program_compiler::compile_shaders(
|
||||
|
||||
for (auto [ shader_set_meta, shader_set ] : std::ranges::views::zip( metadata, shader_sets))
|
||||
{
|
||||
auto shader_missing = false;
|
||||
|
||||
for (auto [ stage_index, handle ] : std::ranges::views::enumerate(shader_set.stages))
|
||||
{
|
||||
if (not handle.valid())
|
||||
{
|
||||
if (source_meta_it->string_count > 0)
|
||||
if (not shader_missing)
|
||||
{
|
||||
shader_data shader{};
|
||||
if (source_meta_it->string_count > 0)
|
||||
{
|
||||
shader_data shader{};
|
||||
|
||||
if (compile_shader(
|
||||
gl_shader_types[stage_index],
|
||||
std::span(source_strings_it.base(), source_meta_it->string_count),
|
||||
shader
|
||||
)) {
|
||||
handle = shader.handle;
|
||||
auto shader_meta = shader_metadata{
|
||||
.geometry = source_req_it->geometry,
|
||||
.stage = source_req_it->stage,
|
||||
.static_enabled = source_meta_it->static_enabled,
|
||||
.dynamic_enable = source_meta_it->dynamic_enable
|
||||
};
|
||||
if (compile_shader(
|
||||
gl_shader_types[stage_index],
|
||||
std::span(source_strings_it.base(), source_meta_it->string_count),
|
||||
shader
|
||||
)) {
|
||||
handle = shader.handle;
|
||||
auto shader_meta = shader_metadata{
|
||||
.geometry = source_req_it->geometry,
|
||||
.stage = source_req_it->stage,
|
||||
.static_enabled = source_meta_it->static_enabled,
|
||||
.dynamic_enable = source_meta_it->dynamic_enable
|
||||
};
|
||||
|
||||
shader_set_meta.static_enabled |= shader_meta.static_enabled;
|
||||
shader_set_meta.dynamic_enable |= shader_meta.dynamic_enable;
|
||||
shader_set_meta.static_enabled |= shader_meta.static_enabled;
|
||||
shader_set_meta.dynamic_enable |= shader_meta.dynamic_enable;
|
||||
|
||||
m_shader_lookup.emplace_back(shader_meta, std::move(shader));
|
||||
}
|
||||
m_shader_lookup.emplace_back(shader_meta, std::move(shader));
|
||||
}
|
||||
}
|
||||
|
||||
shader_missing = not handle.valid() and shading::stage::mandatory[stage_index];
|
||||
}
|
||||
|
||||
source_strings_it += source_meta_it->string_count;
|
||||
@@ -180,6 +177,11 @@ void zgl::shader_program_compiler::compile_shaders(
|
||||
++source_req_it;
|
||||
}
|
||||
}
|
||||
|
||||
if (shader_missing)
|
||||
{
|
||||
shader_set.stages = {};
|
||||
}
|
||||
}
|
||||
|
||||
const auto new_shaders = std::span(m_shader_lookup).subspan(prev_shader_count);
|
||||
@@ -196,16 +198,20 @@ void zgl::shader_program_compiler::compile_shaders(
|
||||
prioritized_metadata_comparator{},
|
||||
&shader_lookup_entry_type::first
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
bool zgl::shader_program_compiler::compile_shader(
|
||||
bool zgl::shader_manager::compile_shader(
|
||||
GLenum shader_type,
|
||||
std::span<const char*> source_strings,
|
||||
shader_data& shader
|
||||
) {
|
||||
|
||||
shader = shader_data(glCreateShader(shader_type));
|
||||
if (const auto e = get_error())
|
||||
{
|
||||
ztu::logger::error("Error while creating shader: %", e.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
glShaderSource(
|
||||
shader.handle.id,
|
||||
@@ -213,13 +219,29 @@ bool zgl::shader_program_compiler::compile_shader(
|
||||
source_strings.data(),
|
||||
nullptr
|
||||
);
|
||||
if (const auto e = get_error())
|
||||
{
|
||||
ztu::logger::error("Error while setting shader source: %", e.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
glCompileShader(shader.handle.id);
|
||||
if (const auto e = get_error())
|
||||
{
|
||||
ztu::logger::error("Error while compiling shader: %", e.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
GLint success;
|
||||
glGetShaderiv(shader.handle.id, GL_COMPILE_STATUS, &success);
|
||||
auto status = GLint{ GL_FALSE };
|
||||
glGetShaderiv(shader.handle.id, GL_COMPILE_STATUS, &status);
|
||||
|
||||
if (not success)
|
||||
if (const auto e = get_error())
|
||||
{
|
||||
ztu::logger::error("Error while retrieving shader compilation status: %", e.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (status == GL_FALSE)
|
||||
{
|
||||
GLint log_length{};
|
||||
glGetShaderiv(shader.handle.id, GL_INFO_LOG_LENGTH, &log_length);
|
||||
@@ -235,8 +257,8 @@ bool zgl::shader_program_compiler::compile_shader(
|
||||
return true;
|
||||
}
|
||||
|
||||
void zgl::shader_program_compiler::preprocess(
|
||||
void zgl::shader_manager::process(
|
||||
const dynamic_shader_source_store& shader_sources
|
||||
) {
|
||||
m_preprocessor.preprocess(shader_sources);
|
||||
m_preprocessor.process(shader_sources);
|
||||
}
|
||||
252
source/opengl/data_managers/shader_program_manager.cpp
Normal file
252
source/opengl/data_managers/shader_program_manager.cpp
Normal file
@@ -0,0 +1,252 @@
|
||||
#include "opengl/data_managers/shader_program_manager.hpp"
|
||||
|
||||
|
||||
struct prioritized_metadata_comparator
|
||||
{
|
||||
using type = zgl::shader_program_metadata;
|
||||
|
||||
bool operator()(const type& a, const type& b) const noexcept
|
||||
{
|
||||
if (a.geometry != b.geometry)
|
||||
{
|
||||
return a.geometry > b.geometry;
|
||||
}
|
||||
|
||||
static constexpr auto more_features = std::popcount<zgl::shading::features::generic::type>;
|
||||
|
||||
return std::ranges::lexicographical_compare(
|
||||
std::array{ a.dynamic_enable, a.static_enabled },
|
||||
std::array{ b.dynamic_enable, b.static_enabled },
|
||||
std::greater{},
|
||||
more_features,
|
||||
more_features
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
void zgl::shader_program_manager::process(
|
||||
const dynamic_shader_source_store& shader_sources
|
||||
) {
|
||||
m_shader_manager.preprocess(shader_sources);
|
||||
}
|
||||
|
||||
void zgl::shader_program_manager::get_handles(
|
||||
const dynamic_shader_source_store& shader_sources,
|
||||
std::span<const shading::shader_program_requirements> requirements,
|
||||
std::span<shader_program_metadata> metadata,
|
||||
std::span<shader_program_handle> shader_programs
|
||||
) {
|
||||
m_shader_requirements_buffer.clear();
|
||||
|
||||
for (auto [ req, program_meta, program_handle ] : std::ranges::views::zip(
|
||||
requirements,
|
||||
metadata,
|
||||
shader_programs
|
||||
)) {
|
||||
|
||||
if (auto shader_match = find_shader_program(req))
|
||||
{
|
||||
const auto& [ meta, handle ] = *shader_match;
|
||||
program_meta.static_enabled = meta.static_enabled;
|
||||
program_meta.dynamic_enable = meta.dynamic_enable;
|
||||
program_handle = handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
program_meta = {};
|
||||
program_handle = {};
|
||||
m_shader_requirements_buffer.emplace_back(
|
||||
req.geometry,
|
||||
req.features
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
m_shader_metadata_buffer.clear();
|
||||
m_shader_metadata_buffer.resize(m_shader_requirements_buffer.size());
|
||||
shader_set_buffer.clear();
|
||||
|
||||
m_shader_manager.get_handles(
|
||||
shader_sources,
|
||||
m_shader_requirements_buffer,
|
||||
m_shader_metadata_buffer,
|
||||
shader_set_buffer
|
||||
);
|
||||
|
||||
auto shader_set_req_it = m_shader_requirements_buffer.begin();
|
||||
auto shader_set_meta_it = m_shader_metadata_buffer.begin();
|
||||
auto shader_set_it = shader_set_buffer.begin();
|
||||
|
||||
const auto prev_shader_program_count = m_shader_program_lookup.size();
|
||||
|
||||
for (auto [ program_meta, program_handle ] : std::ranges::views::zip( metadata, shader_programs))
|
||||
{
|
||||
if (not program_handle.valid())
|
||||
{
|
||||
if (std::ranges::any_of(shader_set_it->stages, &shader_handle::valid))
|
||||
{
|
||||
shader_program_data program{};
|
||||
|
||||
if (link_shader_program(*shader_set_it))
|
||||
{
|
||||
program_handle = program.handle;
|
||||
|
||||
program_meta = shader_program_metadata{
|
||||
.geometry = shader_set_req_it->geometry,
|
||||
.static_enabled = shader_set_meta_it->static_enabled,
|
||||
.dynamic_enable = shader_set_meta_it->dynamic_enable
|
||||
};
|
||||
|
||||
m_shader_program_lookup.emplace_back(program_meta, std::move(program));
|
||||
}
|
||||
}
|
||||
|
||||
++shader_set_req_it;
|
||||
++shader_set_meta_it;
|
||||
++shader_set_it;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const auto new_shader_programs = std::span(m_shader_program_lookup).subspan(prev_shader_program_count);
|
||||
|
||||
std::ranges::sort(
|
||||
new_shader_programs,
|
||||
prioritized_metadata_comparator{},
|
||||
&shader_program_lookup_entry_type::first
|
||||
);
|
||||
|
||||
std::ranges::inplace_merge(
|
||||
m_shader_program_lookup,
|
||||
m_shader_program_lookup.begin() + prev_shader_program_count,
|
||||
prioritized_metadata_comparator{},
|
||||
&shader_program_lookup_entry_type::first
|
||||
);
|
||||
}
|
||||
|
||||
std::optional<std::pair<zgl::shader_program_metadata, zgl::shader_program_handle>> zgl::shader_program_manager::find_shader_program(
|
||||
const shading::shader_program_requirements& requirements
|
||||
) {
|
||||
|
||||
auto shader_program_it = std::ranges::lower_bound(
|
||||
m_shader_program_lookup,
|
||||
requirements.geometry,
|
||||
std::greater{},
|
||||
[](const shader_program_lookup_entry_type& entry)
|
||||
{
|
||||
const auto& meta = entry.first;
|
||||
return meta.geometry;
|
||||
}
|
||||
);
|
||||
|
||||
while (
|
||||
shader_program_it != m_shader_program_lookup.end() and
|
||||
shader_program_it->first.geometry == requirements.geometry
|
||||
) {
|
||||
const auto& [ meta, data ] = *shader_program_it;
|
||||
|
||||
const auto unwanted_static_features = meta.static_enabled & ~requirements.features;
|
||||
const auto required_dynamic_features = requirements.features & ~meta.static_enabled;
|
||||
const auto missing_dynamic_features = required_dynamic_features & ~meta.dynamic_enable;
|
||||
|
||||
if (unwanted_static_features == 0 and missing_dynamic_features == 0)
|
||||
{
|
||||
return std::pair{ meta, data.handle };
|
||||
}
|
||||
|
||||
++shader_program_it;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool zgl::shader_program_manager::link_shader_program(
|
||||
const shader_handle_set& shaders
|
||||
) {
|
||||
const auto program = shader_program_data{ glCreateProgram() };
|
||||
if (const auto e = get_error())
|
||||
{
|
||||
ztu::logger::error("Error while creating shader program: %.", e.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto [ index, entry ] : std::ranges::views::enumerate(std::ranges::views::zip(
|
||||
shaders.stages,
|
||||
shading::stage::names
|
||||
))) {
|
||||
const auto& [ shader, name ] = entry;
|
||||
|
||||
auto attached = false;
|
||||
|
||||
if (shader.id)
|
||||
{
|
||||
glAttachShader(program.handle.id, shader.id);
|
||||
if (const auto e = get_error())
|
||||
{
|
||||
if (shading::stage::mandatory[index])
|
||||
{
|
||||
ztu::logger::error("Error while attaching the mandatory % shader: %.", name, e.message());
|
||||
return false;
|
||||
}
|
||||
ztu::logger::warn("Error while attaching the optional % shader: %.", name, e.message());
|
||||
}
|
||||
else
|
||||
{
|
||||
attached = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (not attached)
|
||||
{
|
||||
ztu::logger::warn("Using default % shader.", name);
|
||||
}
|
||||
}
|
||||
|
||||
glLinkProgram(program.handle.id);
|
||||
if (const auto e = get_error())
|
||||
{
|
||||
ztu::logger::error("Error while linking shader program: %.", e.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
auto status = GLint{ GL_FALSE };
|
||||
glGetProgramiv(program.handle.id, GL_LINK_STATUS, &status);
|
||||
if (const auto e = get_error())
|
||||
{
|
||||
ztu::logger::error("Error while retrieving shader program link status: %.", e.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (status == GL_FALSE) {
|
||||
GLint log_length{};
|
||||
glGetShaderiv(program.handle.id, GL_INFO_LOG_LENGTH, &log_length);
|
||||
|
||||
auto log = std::string(log_length, ' ');
|
||||
glGetProgramInfoLog(program.handle.id, log_length, nullptr, log.data());
|
||||
|
||||
ztu::logger::error("Error while linking program:\n%", log);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
glUseProgram(0);
|
||||
if (const auto e = get_error())
|
||||
{
|
||||
ztu::logger::warn("Error while resetting active shader program: %.", e.message());
|
||||
}
|
||||
|
||||
for (const auto& shader : shaders.stages)
|
||||
{
|
||||
if (shader.id)
|
||||
{
|
||||
glDetachShader(program.handle.id, shader.id);
|
||||
if (const auto e = get_error())
|
||||
{
|
||||
ztu::logger::warn("Error while detaching shader: %.", e.message());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "opengl/data_uploaders/shader_preprocessor.hpp"
|
||||
#include "opengl/data_managers/shader_source_manager.hpp"
|
||||
|
||||
#include "util/logger.hpp"
|
||||
#include <algorithm>
|
||||
@@ -7,6 +7,29 @@
|
||||
|
||||
#include "opengl/shading/shader_metadata_language.hpp"
|
||||
|
||||
static auto mesh_feature_defines = std::array{
|
||||
"#define FACE\n",
|
||||
"#define LINE\n",
|
||||
"#define POINT\n",
|
||||
"#define V_L\n",
|
||||
"#define V_RGB\n",
|
||||
"#define V_A\n",
|
||||
"#define LIGHTING\n",
|
||||
"#define TEXTURE\n",
|
||||
"#define U_RGBA\n",
|
||||
};
|
||||
|
||||
static auto point_cloud_feature_defines = std::array{
|
||||
"#define SQUARE\n",
|
||||
"#define LIGHTING\n",
|
||||
"#define V_L\n",
|
||||
"#define V_RGB\n",
|
||||
"#define V_A\n",
|
||||
"#define U_RGBA\n",
|
||||
"#define RAINBOW\n"
|
||||
};
|
||||
|
||||
|
||||
struct prioritized_feature_set_comparator
|
||||
{
|
||||
using type = zgl::shader_features_set<zgl::shading::features::generic::type>;
|
||||
@@ -53,7 +76,7 @@ private:
|
||||
|
||||
|
||||
|
||||
void zgl::shader_preprocessor::preprocess(
|
||||
void zgl::shader_source_manager::process(
|
||||
const dynamic_shader_source_store& shader_sources
|
||||
) {
|
||||
namespace language = shading::shader_metadata_language;
|
||||
@@ -95,7 +118,7 @@ void zgl::shader_preprocessor::preprocess(
|
||||
}
|
||||
}
|
||||
|
||||
void zgl::shader_preprocessor::fetch_shader_sources(
|
||||
void zgl::shader_source_manager::get_shader_sources(
|
||||
const dynamic_shader_source_store& shader_sources,
|
||||
std::span<const shading::shader_source_requirements> requirements,
|
||||
std::span<preprocessed_shader_source_metadata> metadata,
|
||||
@@ -177,7 +200,7 @@ void zgl::shader_preprocessor::fetch_shader_sources(
|
||||
);
|
||||
}
|
||||
|
||||
void zgl::shader_preprocessor::get_define_strings(
|
||||
void zgl::shader_source_manager::get_define_strings(
|
||||
const shading::model_geometry::types geometry,
|
||||
shading::features::generic::type features,
|
||||
shading::features::generic::type& feature_count,
|
||||
@@ -211,7 +234,7 @@ void zgl::shader_preprocessor::get_define_strings(
|
||||
}
|
||||
|
||||
|
||||
void zgl::shader_preprocessor::tokenize_declarations(
|
||||
void zgl::shader_source_manager::tokenize_declarations(
|
||||
std::string_view source_rest
|
||||
) {
|
||||
namespace language = shading::shader_metadata_language;
|
||||
@@ -274,7 +297,7 @@ void zgl::shader_preprocessor::tokenize_declarations(
|
||||
}
|
||||
}
|
||||
|
||||
bool zgl::shader_preprocessor::parse_stage_declaration(
|
||||
bool zgl::shader_source_manager::parse_stage_declaration(
|
||||
std::span<const std::string_view> values,
|
||||
shader_source_metadata& metadata
|
||||
) {
|
||||
@@ -301,7 +324,7 @@ bool zgl::shader_preprocessor::parse_stage_declaration(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool zgl::shader_preprocessor::parse_geometry_declaration(
|
||||
bool zgl::shader_source_manager::parse_geometry_declaration(
|
||||
std::span<const std::string_view> values,
|
||||
shader_source_metadata& metadata
|
||||
) {
|
||||
@@ -329,7 +352,7 @@ bool zgl::shader_preprocessor::parse_geometry_declaration(
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void zgl::shader_preprocessor::parse_feature_tokens(
|
||||
void zgl::shader_source_manager::parse_feature_tokens(
|
||||
std::span<const std::string_view> values,
|
||||
const ztu::string_lookup<T>& feature_lookup,
|
||||
T& features
|
||||
@@ -349,7 +372,7 @@ void zgl::shader_preprocessor::parse_feature_tokens(
|
||||
}
|
||||
}
|
||||
|
||||
bool zgl::shader_preprocessor::parse_features_declaration(
|
||||
bool zgl::shader_source_manager::parse_features_declaration(
|
||||
std::span<const std::string_view> values,
|
||||
shader_source_metadata& metadata
|
||||
) {
|
||||
@@ -370,7 +393,7 @@ bool zgl::shader_preprocessor::parse_features_declaration(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool zgl::shader_preprocessor::parse_static_enable_declaration(
|
||||
bool zgl::shader_source_manager::parse_static_enable_declaration(
|
||||
std::span<const std::string_view> values,
|
||||
shader_source_metadata& metadata
|
||||
) {
|
||||
@@ -391,7 +414,7 @@ bool zgl::shader_preprocessor::parse_static_enable_declaration(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool zgl::shader_preprocessor::parse_dynamic_enable_declaration(
|
||||
bool zgl::shader_source_manager::parse_dynamic_enable_declaration(
|
||||
std::span<const std::string_view> values,
|
||||
shader_source_metadata& metadata
|
||||
) {
|
||||
@@ -412,7 +435,7 @@ bool zgl::shader_preprocessor::parse_dynamic_enable_declaration(
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<zgl::shader_source_metadata> zgl::shader_preprocessor::parse_metadata_from_tokens()
|
||||
std::optional<zgl::shader_source_metadata> zgl::shader_source_manager::parse_metadata_from_tokens()
|
||||
{
|
||||
namespace language = shading::shader_metadata_language;
|
||||
using namespace std::string_view_literals;
|
||||
150
source/opengl/data_managers/texture_manager.cpp
Normal file
150
source/opengl/data_managers/texture_manager.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
#include "opengl/data_managers/texture_manager.hpp"
|
||||
|
||||
#include <ranges>
|
||||
#include "util/logger.hpp"
|
||||
#include "opengl/error.hpp"
|
||||
|
||||
|
||||
void zgl::texture_manager::process(
|
||||
dynamic_texture_store& store
|
||||
) {
|
||||
m_texture_buffer.clear();
|
||||
|
||||
for (const auto& [ id, texture ] : store)
|
||||
{
|
||||
if (not m_resource_manager.has_resource(id))
|
||||
{
|
||||
m_texture_buffer.emplace_back(id, texture);
|
||||
}
|
||||
}
|
||||
|
||||
m_texture_id_buffer.resize(m_texture_buffer.size());
|
||||
|
||||
glGenTextures(m_texture_id_buffer.size(), m_texture_id_buffer.data());
|
||||
if (const auto e = get_error())
|
||||
{
|
||||
ztu::logger::error("Error while creating % textures: %.", m_texture_id_buffer.size(), e.message());
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto [ entry, texture_id ] : std::ranges::views::zip(m_texture_buffer, m_texture_id_buffer))
|
||||
{
|
||||
auto [ store_id, texture ] = entry;
|
||||
|
||||
GLenum format;
|
||||
switch (texture.components()) {
|
||||
using enum components::texture::flags;
|
||||
case luminance:
|
||||
format = GL_LUMINANCE;
|
||||
break;
|
||||
case luminance | alpha:
|
||||
format = GL_LUMINANCE_ALPHA;
|
||||
break;
|
||||
case red | green | blue:
|
||||
format = GL_RGB;
|
||||
break;
|
||||
case red | green | blue | alpha:
|
||||
format = GL_RGBA;
|
||||
break;
|
||||
default:
|
||||
// TODO create a print statement for these enum flaggy thingies
|
||||
ztu::logger::error("Unsupported texture component configuration: %.", texture.components());
|
||||
continue;
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
if (const auto e = get_error())
|
||||
{
|
||||
ztu::logger::error("Error while binding texture %: %.", texture_id, e.message());
|
||||
return;
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
if (const auto e = get_error())
|
||||
{
|
||||
ztu::logger::warn("Error while setting texture parameters: %.", e.message());
|
||||
}
|
||||
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RGBA8,
|
||||
texture.width(),
|
||||
texture.height(),
|
||||
0,
|
||||
format,
|
||||
GL_UNSIGNED_BYTE,
|
||||
texture.data()
|
||||
);
|
||||
|
||||
if (const auto e = get_error())
|
||||
{
|
||||
ztu::logger::error("Error while setting texture data: %.", e.message());
|
||||
continue;
|
||||
}
|
||||
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
if (const auto e = get_error())
|
||||
{
|
||||
ztu::logger::warn("Error while generating texture mipmaps: %.", e.message());
|
||||
}
|
||||
|
||||
const auto meta = metadata_type{
|
||||
.components = texture.components()
|
||||
};
|
||||
|
||||
m_resource_manager.add_resource(store_id, texture_id, meta);
|
||||
|
||||
texture_id = {};
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
const auto valid_texture_ids = std::ranges::remove(
|
||||
m_texture_id_buffer,
|
||||
0
|
||||
);
|
||||
|
||||
const auto invalid_texture_count = m_texture_id_buffer.size() - valid_texture_ids.size();
|
||||
|
||||
glDeleteTextures(
|
||||
invalid_texture_count,
|
||||
m_texture_id_buffer.data()
|
||||
);
|
||||
if (const auto e = get_error())
|
||||
{
|
||||
ztu::logger::error("Error while deleting % textures: %.", invalid_texture_count, e.message());
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<zgl::texture_manager::handle_type> zgl::texture_manager::get_handle(
|
||||
const store_id_type id
|
||||
) {
|
||||
return m_resource_manager
|
||||
.get_resource(id)
|
||||
.transform(
|
||||
[](auto& resource)
|
||||
{
|
||||
return *reinterpret_cast<handle_type*>(resource);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void zgl::texture_manager::collect_garbage(const bool force)
|
||||
{
|
||||
m_resource_manager.collect_garbage();
|
||||
if (force or m_resource_manager.count_garbage() >= min_garbage_collection_count)
|
||||
{
|
||||
m_texture_id_buffer.clear();
|
||||
m_resource_manager.extract_garbage(m_texture_id_buffer);
|
||||
glDeleteTextures(
|
||||
m_texture_id_buffer.size(),
|
||||
m_texture_id_buffer.data()
|
||||
);
|
||||
}
|
||||
}
|
||||
14
source/opengl/handles/index_buffer_handle.ipp
Normal file
14
source/opengl/handles/index_buffer_handle.ipp
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef INCLUDE_INDEX_BUFFER_HANDLE_IMPLEMENTATION
|
||||
#error Never include this file directly include 'index_buffer_handle.hpp'
|
||||
#endif
|
||||
|
||||
|
||||
void zgl::index_buffer_handle::bind() const
|
||||
{
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_id);
|
||||
}
|
||||
|
||||
void zgl::index_buffer_handle::unbind()
|
||||
{
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
}
|
||||
@@ -25,7 +25,7 @@ shader_program_handle::attribute_support_type shader_program_handle::check_attri
|
||||
|
||||
auto curr_attribute_flag = attribute_support_type{ 1 };
|
||||
for (const auto& attribute : attributes) {
|
||||
const auto location = glGetAttribLocation(program_id, attribute.name);
|
||||
const auto location = glGetAttribLocation(id, attribute.name);
|
||||
if (location == attribute.info.location)
|
||||
{
|
||||
attribute_candidates |= curr_attribute_flag;
|
||||
@@ -36,7 +36,7 @@ shader_program_handle::attribute_support_type shader_program_handle::check_attri
|
||||
auto supported_attributes = attribute_support_type{};
|
||||
|
||||
GLint count;
|
||||
glGetProgramiv(program_id, GL_ACTIVE_ATTRIBUTES, &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)
|
||||
@@ -46,7 +46,7 @@ shader_program_handle::attribute_support_type shader_program_handle::check_attri
|
||||
GLsizei name_length;
|
||||
auto name = std::array<char, 256>{};
|
||||
glGetActiveAttrib(
|
||||
program_id, i,
|
||||
id, i,
|
||||
name.size(),
|
||||
&name_length,
|
||||
&size, &type,
|
||||
@@ -93,12 +93,12 @@ shader_program_handle::uniform_support_type shader_program_handle::check_uniform
|
||||
auto curr_uniform_flag = uniform_support_type{ 1 };
|
||||
for (const auto& uniform : uniforms)
|
||||
{
|
||||
const auto location = glGetUniformLocation(program_id, uniform.name);
|
||||
const auto location = glGetUniformLocation(id, uniform.name);
|
||||
|
||||
if (location == uniform.info.location)
|
||||
{
|
||||
uniform_candidates |= curr_uniform_flag;
|
||||
ztu::logger::debug("[%] '%': %.", program_id, uniform.name, location);
|
||||
ztu::logger::debug("[%] '%': %.", id, uniform.name, location);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -110,7 +110,7 @@ shader_program_handle::uniform_support_type shader_program_handle::check_uniform
|
||||
auto supported_uniforms = uniform_support_type{};
|
||||
|
||||
GLint count;
|
||||
glGetProgramiv(program_id, GL_ACTIVE_UNIFORMS, &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)
|
||||
@@ -120,7 +120,7 @@ shader_program_handle::uniform_support_type shader_program_handle::check_uniform
|
||||
GLsizei name_length;
|
||||
auto name = std::array<char, 256>{};
|
||||
glGetActiveUniform(
|
||||
program_id, i,
|
||||
id, i,
|
||||
name.size(),
|
||||
&name_length,
|
||||
&size, &type,
|
||||
@@ -149,4 +149,9 @@ shader_program_handle::uniform_support_type shader_program_handle::check_uniform
|
||||
|
||||
return supported_uniforms;
|
||||
}
|
||||
|
||||
bool shader_program_handle::valid() const
|
||||
{
|
||||
return id != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace zgl
|
||||
{
|
||||
inline void shader_program_handle::bind() const
|
||||
{
|
||||
glUseProgram(program_id);
|
||||
glUseProgram(id);
|
||||
}
|
||||
|
||||
inline void shader_program_handle::unbind()
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace zgl
|
||||
{
|
||||
inline void texture_handle::bind() const
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
glBindTexture(GL_TEXTURE_2D, m_id);
|
||||
}
|
||||
|
||||
inline void texture_handle::unbind()
|
||||
|
||||
14
source/opengl/handles/vertex_buffer_handle.ipp
Normal file
14
source/opengl/handles/vertex_buffer_handle.ipp
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef INCLUDE_VERTEX_BUFFER_HANDLE_IMPLEMENTATION
|
||||
#error Never include this file directly include 'vertex_buffer_handle.hpp'
|
||||
#endif
|
||||
|
||||
|
||||
void zgl::vertex_buffer_handle::bind() const
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_id);
|
||||
}
|
||||
|
||||
void zgl::vertex_buffer_handle::unbind()
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
67
source/opengl/resource_management/resource_handle.ipp
Normal file
67
source/opengl/resource_management/resource_handle.ipp
Normal file
@@ -0,0 +1,67 @@
|
||||
#ifndef INCLUDE_RESOURCE_HANDLE_IMPLEMENTATION
|
||||
# error Never include this file directly include 'resource_handle.hpp'
|
||||
#endif
|
||||
|
||||
|
||||
zgl::resource_handle::resource_handle(id_type id, reference_counter* manager)
|
||||
: m_id{ id }, m_counter{ manager } {}
|
||||
|
||||
zgl::resource_handle::resource_handle(const resource_handle& other) noexcept
|
||||
: m_id{ other.m_id }, m_counter{ other.m_counter }
|
||||
{
|
||||
if (m_id != 0 and m_counter != nullptr)
|
||||
{
|
||||
m_counter->add_reference(m_id);
|
||||
}
|
||||
}
|
||||
|
||||
zgl::resource_handle& zgl::resource_handle::operator=(
|
||||
const resource_handle& other
|
||||
) noexcept {
|
||||
if (&other != this)
|
||||
{
|
||||
this->~resource_handle();
|
||||
|
||||
m_id = other.m_id;
|
||||
m_counter = other.m_counter;
|
||||
|
||||
if (m_id != 0 and m_counter != nullptr)
|
||||
{
|
||||
m_counter->add_reference(m_id);
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
zgl::resource_handle::resource_handle(resource_handle&& other) noexcept
|
||||
: m_id{ other.m_id }, m_counter{ other.m_counter }
|
||||
{
|
||||
other.m_id = 0;
|
||||
other.m_counter = nullptr;
|
||||
}
|
||||
|
||||
zgl::resource_handle& zgl::resource_handle::resource_handle::operator=(
|
||||
resource_handle&& other
|
||||
) noexcept {
|
||||
if (&other != this)
|
||||
{
|
||||
this->~resource_handle();
|
||||
|
||||
m_id = other.m_id;
|
||||
m_counter = other.m_counter;
|
||||
|
||||
other.m_id = 0;
|
||||
other.m_counter = nullptr;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
zgl::resource_handle::~resource_handle()
|
||||
{
|
||||
if (m_id != 0 and m_counter != nullptr)
|
||||
{
|
||||
m_counter->remove_reference(m_id);
|
||||
}
|
||||
}
|
||||
139
source/opengl/resource_management/resource_manager.ipp
Normal file
139
source/opengl/resource_management/resource_manager.ipp
Normal file
@@ -0,0 +1,139 @@
|
||||
#ifndef INCLUDE_RESOURCE_MANAGER_IMPLEMENTATION
|
||||
# error Never include this file directly include 'resource_manager.hpp'
|
||||
#endif
|
||||
|
||||
#include <ranges>
|
||||
|
||||
|
||||
template<typename StoreID, typename MetaData>
|
||||
bool zgl::resource_manager<StoreID, MetaData>::has_resource(StoreID store_id)
|
||||
{
|
||||
std::shared_lock lock(m_lock);
|
||||
return m_resource_lookup.contains(store_id);
|
||||
}
|
||||
|
||||
template<typename StoreID, typename MetaData>
|
||||
void zgl::resource_manager<StoreID, MetaData>::add_resource(StoreID store_id, gl_id_type gl_id, MetaData meta)
|
||||
{
|
||||
std::unique_lock lock(m_lock);
|
||||
m_resource_lookup.emplace(store_id, { gl_id, std::move(meta) });
|
||||
m_reference_counters.emplace(gl_id, 1);
|
||||
}
|
||||
|
||||
|
||||
template<typename StoreID, typename MetaData>
|
||||
std::optional<std::pair<zgl::resource_handle, MetaData>> zgl::resource_manager<StoreID, MetaData>::get_resource(
|
||||
StoreID store_id
|
||||
) {
|
||||
std::unique_lock lock(m_lock);
|
||||
|
||||
const auto resource_it = m_resource_lookup.find(store_id);
|
||||
if (resource_it == m_resource_lookup.end())
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const auto gl_id = resource_it.first;
|
||||
|
||||
auto [ counter_it, inserted ] = m_reference_counters.try_emplace(gl_id, 0);
|
||||
|
||||
++counter_it->second;
|
||||
|
||||
return std::pair{ resource_handle(gl_id, this), resource_it->second };
|
||||
}
|
||||
|
||||
template<typename StoreID, typename MetaData>
|
||||
void zgl::resource_manager<StoreID, MetaData>::collect_garbage()
|
||||
{
|
||||
std::unique_lock lock(m_lock);
|
||||
|
||||
for (auto& counter : m_reference_counters | std::ranges::views::values)
|
||||
{
|
||||
if (counter & unused_resource_flag)
|
||||
{
|
||||
const auto value = counter & ~unused_resource_flag;
|
||||
counter = (value + 1) | unused_resource_flag;
|
||||
}
|
||||
}
|
||||
|
||||
std::erase_if(
|
||||
m_reference_counters,
|
||||
[&](const auto& entry)
|
||||
{
|
||||
auto& counter = entry.second;
|
||||
|
||||
const auto value = counter & ~unused_resource_flag;
|
||||
|
||||
if (value == counter) // Still in use
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value < max_unused_collection_cycle_count)
|
||||
{
|
||||
counter = (value + 1) | unused_resource_flag;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_unused_handles.emplace(entry.first);
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
std::erase_if(
|
||||
m_resource_lookup,
|
||||
[&](const auto& entry)
|
||||
{
|
||||
return m_unused_handles.contains(entry.second);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<typename StoreID, typename MetaData>
|
||||
void zgl::resource_manager<StoreID, MetaData>::add_reference(const gl_id_type id)
|
||||
{
|
||||
std::unique_lock lock(m_lock);
|
||||
auto [it, inserted] = m_reference_counters.try_emplace(id, 0);
|
||||
++it->second;
|
||||
}
|
||||
|
||||
template<typename StoreID, typename MetaData>
|
||||
void zgl::resource_manager<StoreID, MetaData>::remove_reference(const gl_id_type id)
|
||||
{
|
||||
std::unique_lock lock(m_lock);
|
||||
if (const auto it = m_reference_counters.find(id); it != m_reference_counters.end())
|
||||
{
|
||||
if (it->second == 1)
|
||||
{
|
||||
it->second = unused_resource_flag;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename StoreID, typename MetaData>
|
||||
typename zgl::resource_manager<StoreID, MetaData>::size_type zgl::resource_manager<StoreID, MetaData>::count_garbage()
|
||||
{
|
||||
std::shared_lock lock(m_lock);
|
||||
return m_unused_handles.size();
|
||||
}
|
||||
|
||||
template<typename StoreID, typename MetaData>
|
||||
void zgl::resource_manager<StoreID, MetaData>::extract_garbage(
|
||||
std::vector<gl_id_type>& dst
|
||||
) {
|
||||
{
|
||||
std::shared_lock lock(m_lock);
|
||||
dst.reserve(m_unused_handles.size());
|
||||
}
|
||||
{
|
||||
std::unique_lock lock(m_lock);
|
||||
|
||||
dst.resize(m_unused_handles.size());
|
||||
|
||||
std::ranges::copy(m_unused_handles, dst.begin());
|
||||
|
||||
m_unused_handles.clear();
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ void shader_program_lookup::add(
|
||||
const auto uniforms = shader_program_handle.check_uniform_support(all_uniforms);
|
||||
|
||||
ztu::logger::debug("add [%] uniforms: % attributes: %",
|
||||
shader_program_handle.program_id,
|
||||
shader_program_handle.id,
|
||||
std::bitset<32>(uniforms),
|
||||
std::bitset<32>(attributes)
|
||||
);
|
||||
@@ -185,7 +185,7 @@ void shader_program_lookup::print() {
|
||||
const auto uniforms = m_mesh_shader_program_uniforms[i];
|
||||
const auto [ attributes, locations ] = m_mesh_shader_program_attributes[i];
|
||||
ztu::logger::debug("[%] uniforms: % attributes: % locations: %",
|
||||
shader.program_id,
|
||||
shader.id,
|
||||
std::bitset<32>(uniforms),
|
||||
std::bitset<32>(attributes),
|
||||
std::bitset<32>(locations)
|
||||
|
||||
Reference in New Issue
Block a user