diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index d0c82d8..742833a 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -140,6 +140,7 @@
+
diff --git a/.idea/editor.xml b/.idea/editor.xml
index f6606eb..a5f440a 100644
--- a/.idea/editor.xml
+++ b/.idea/editor.xml
@@ -98,483 +98,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 0b76fe5..a8443ba 100755
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,5 +1,10 @@
+
+
+
+
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2512da5..23bdf7b 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,7 +28,6 @@ add_executable(z3d main.cpp
include/opengl/data/mesh_data.hpp
include/opengl/data/point_cloud_data.hpp
include/opengl/data/shader_program_data.hpp
- include/opengl/data/texture_data.hpp
include/scene/lighting_setup.hpp
include/rendering/batch_renderers/mesh_batch_renderer.hpp
include/opengl/error.hpp
@@ -144,7 +143,7 @@ add_executable(z3d main.cpp
include/assets/dynamic_data_loaders/dynamic_texture_loader.hpp
source/assets/dynamic_data_loaders/dynamic_texture_loader.cpp
include/assets/dynamic_data_stores/dynamic_texture_store.hpp
- include/opengl/data_uploaders/texture_data_uploader.hpp
+ include/opengl/data_managers/texture_manager.hpp
include/assets/dynamic_data_stores/dynamic_vertex_store.hpp
include/assets/prefetch_lookups/mesh_prefetch_lookup.hpp
include/assets/prefetch_lookups/point_cloud_prefetch_lookup.hpp
@@ -178,16 +177,14 @@ add_executable(z3d main.cpp
include/assets/prefetch_lookup.hpp
source/assets/prefetch_lookups/pose_prefetch_lookup.cpp
include/assets/dynamic_data_store.hpp
- include/opengl/data_uploaders/shader_program_compiler.hpp
include/opengl/metadata/shader_source_metadata.hpp
- source/opengl/data_uploaders/shader_compiler.cpp
+ source/opengl/data_managers/shader_manager.cpp
include/opengl/shading/model_geometry.hpp
include/opengl/shading/shader_stage.hpp
include/opengl/shading/requirements/shader_program_requirements.hpp
- include/opengl/shading/shader_set.hpp
include/opengl/shading/attributes/mesh_attributes.hpp
- include/opengl/data_uploaders/shader_preprocessor.hpp
- source/opengl/data_uploaders/shader_preprocessor.cpp
+ include/opengl/data_managers/shader_source_manager.hpp
+ source/opengl/data_managers/shader_source_manager.cpp
include/opengl/shading/shader_metadata_language.hpp
include/opengl/shading/features/generic_features.hpp
include/opengl/shading/features/combined_features.hpp
@@ -198,6 +195,27 @@ add_executable(z3d main.cpp
include/opengl/metadata/shader_set_metadata.hpp
include/opengl/handles/shader_handle_set.hpp
include/opengl/shading/requirements/shader_set_requirements.hpp
+ include/opengl/data_managers/shader_program_manager.hpp
+ include/opengl/metadata/shader_program_metadata.hpp
+ source/opengl/data_managers/shader_program_manager.cpp
+ source/opengl/data_managers/texture_manager.cpp
+ include/util/reference_counter.hpp
+ include/opengl/resource_management/resource_manager.hpp
+ source/opengl/resource_management/resource_manager.ipp
+ include/opengl/data_managers/buffer_manager.hpp
+ include/opengl/data_managers/shader_manager.hpp
+ include/opengl/data_managers/mesh_vertex_buffer_manager.hpp
+ source/opengl/data_managers/mesh_vertex_buffer_manager.cpp
+ include/opengl/resource_management/reference_counter.hpp
+ include/opengl/resource_management/reference_counter.hpp
+ include/opengl/resource_management/resource_handle.hpp
+ source/opengl/resource_management/resource_handle.ipp
+ include/opengl/handles/vertex_buffer_handle.hpp
+ source/opengl/handles/vertex_buffer_handle.ipp
+ include/opengl/handles/index_buffer_handle.hpp
+ source/opengl/handles/index_buffer_handle.ipp
+ include/opengl/metadata/texture_metadata.hpp
+ include/opengl/metadata/vertex_buffer_metadata.hpp
)
target_include_directories(z3d PRIVATE include)
diff --git a/include/opengl/data/shader_program_data.hpp b/include/opengl/data/shader_program_data.hpp
index e94f79d..b03decd 100755
--- a/include/opengl/data/shader_program_data.hpp
+++ b/include/opengl/data/shader_program_data.hpp
@@ -9,21 +9,11 @@
namespace zgl
{
-class shader_program_data
+struct shader_program_data
{
-private:
- explicit shader_program_data(GLuint program_id);
-
-public:
-
shader_program_data() = default;
- [[nodiscard]] static std::error_code build_from(
- const shader_handle& vertex_shader,
- const shader_handle& geometry_shader,
- const shader_handle& fragment_shader,
- shader_program_data& data
- );
+ explicit shader_program_data(GLuint program_id);
shader_program_data(const shader_program_data& other) = delete;
shader_program_data& operator=(const shader_program_data& other) = delete;
@@ -31,12 +21,9 @@ public:
shader_program_data(shader_program_data&& other) noexcept ;
shader_program_data& operator=(shader_program_data&& other) noexcept;
- [[nodiscard]] shader_program_handle handle() const;
-
~shader_program_data();
-private:
- shader_program_handle m_handle{};
+ shader_program_handle handle{};
};
}
diff --git a/include/opengl/data/texture_data.hpp b/include/opengl/data/texture_data.hpp
deleted file mode 100644
index 44f6d37..0000000
--- a/include/opengl/data/texture_data.hpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#pragma once
-
-#include "GL/glew.h"
-#include "opengl/handles/texture_handle.hpp"
-
-#include
-
-namespace zgl
-{
-struct texture_data
-{
-private:
- explicit texture_data(GLuint texture_id);
-
-public:
- texture_data() = default;
-
- template
- [[nodiscard]] static std::error_code build_from(
- std::span buffer,
- GLenum format,
- GLenum type,
- GLsizei width,
- GLsizei height,
- texture_data& data
- );
-
- texture_data(const texture_data&) = delete;
- texture_data& operator=(const texture_data&) = delete;
-
- texture_data(texture_data&&) noexcept;
- texture_data& operator=(texture_data&&) noexcept;
-
- ~texture_data();
-
- [[nodiscard]] texture_handle handle() const;
-
-private:
- texture_handle m_handle{};
-};
-}
-
-#define INCLUDE_TEXTURE_DATA_IMPLEMENTATION
-#include "opengl/data/texture_data.ipp"
-#undef INCLUDE_TEXTURE_DATA_IMPLEMENTATION
diff --git a/include/opengl/data_managers/buffer_manager.hpp b/include/opengl/data_managers/buffer_manager.hpp
new file mode 100644
index 0000000..ac01620
--- /dev/null
+++ b/include/opengl/data_managers/buffer_manager.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+namespace zgl
+{
+
+class buffer_manager
+{
+public:
+ using store_type = dynamic_texture_store;
+ using store_id_type = store_type::id_type;
+ using resource_manager_type = resource_manager;
+ using resource_type = resource_manager_type::resource_handle;
+ using handle_type = texture_handle;
+
+ static constexpr std::size_t min_garbage_collection_count = 4;
+
+ void process(store_type& store);
+
+ std::optional get_handle(store_id_type id);
+
+ void collect_garbage(bool force = false);
+
+private:
+
+ resource_manager m_resource_manager;
+
+ std::vector> m_texture_buffer;
+ std::vector m_texture_id_buffer;
+
+
+
+};
+
+
+}
+
diff --git a/include/opengl/data_managers/mesh_vertex_buffer_manager.hpp b/include/opengl/data_managers/mesh_vertex_buffer_manager.hpp
new file mode 100644
index 0000000..cbd459c
--- /dev/null
+++ b/include/opengl/data_managers/mesh_vertex_buffer_manager.hpp
@@ -0,0 +1,32 @@
+#pragma once
+
+
+#include "assets/dynamic_data_stores/dynamic_mesh_store.hpp"
+#include "opengl/resource_management/resource_manager.hpp"
+#include "opengl/handles/vertex_buffer_handle.hpp"
+#include "opengl/metadata/vertex_buffer_metadata.hpp"
+
+namespace zgl
+{
+class mesh_vertex_buffer_manager
+{
+public:
+ using store_type = dynamic_mesh_store;
+ using store_id_type = store_type::id_type;
+ using metadata_type = vertex_buffer_metadata;
+ using handle_type = vertex_buffer_handle;
+ using resource_manager_type = resource_manager;
+ using texture_entry_type = std::pair;
+
+ static constexpr std::size_t min_garbage_collection_count = 4;
+
+ void process(store_type& store);
+
+ std::optional get_handle(store_id_type id);
+
+ void collect_garbage(bool force = false);
+
+private:
+ resource_manager_type m_resource_manager;
+};
+}
diff --git a/include/opengl/data_uploaders/shader_compiler.hpp b/include/opengl/data_managers/shader_manager.hpp
similarity index 70%
rename from include/opengl/data_uploaders/shader_compiler.hpp
rename to include/opengl/data_managers/shader_manager.hpp
index cd19e51..f96af0c 100644
--- a/include/opengl/data_uploaders/shader_compiler.hpp
+++ b/include/opengl/data_managers/shader_manager.hpp
@@ -10,7 +10,7 @@
#include "opengl/shader_program_lookup.hpp"
#include "opengl/handles/shader_handle.hpp"
#include "util/string_lookup.hpp"
-#include "shader_preprocessor.hpp"
+#include "shader_source_manager.hpp"
#include "opengl/metadata/shader_metadata.hpp"
#include "opengl/data/shader_data.hpp"
#include "opengl/handles/shader_handle_set.hpp"
@@ -20,26 +20,16 @@
namespace zgl
{
-class shader_program_compiler
+class shader_manager
{
using shader_lookup_entry_type = std::pair;
-
- static constexpr auto gl_shader_types = std::array{
- GL_VERTEX_SHADER,
- GL_TESS_CONTROL_SHADER,
- GL_TESS_EVALUATION_SHADER,
- GL_GEOMETRY_SHADER,
- GL_FRAGMENT_SHADER
- };
-
-
public:
- void preprocess(
+ void process(
const dynamic_shader_source_store& shader_sources
);
- void compile_shaders(
+ void get_handles(
const dynamic_shader_source_store& shader_sources,
std::span requirements,
std::span metadata,
@@ -47,22 +37,22 @@ public:
);
protected:
- shader_handle find_shader(
+ std::optional> find_shader(
const shading::shader_requirements& requirements
);
- bool compile_shader(
+ static bool compile_shader(
GLenum shader_type,
std::span source_strings,
shader_data& shader
);
private:
- shader_preprocessor m_preprocessor{};
+ shader_source_manager m_preprocessor{};
std::vector m_source_requirement_buffer{};
- std::vector m_preprocessed_shader_source_metadata_buffer;
- std::vector m_source_strings_buffer;
- std::vector m_shader_lookup;
+ std::vector m_preprocessed_shader_source_metadata_buffer{};
+ std::vector m_source_strings_buffer{};
+ std::vector m_shader_lookup{};
};
}
diff --git a/include/opengl/data_managers/shader_program_manager.hpp b/include/opengl/data_managers/shader_program_manager.hpp
new file mode 100644
index 0000000..010717e
--- /dev/null
+++ b/include/opengl/data_managers/shader_program_manager.hpp
@@ -0,0 +1,50 @@
+#pragma once
+
+#include "shader_manager.hpp"
+#include "assets/dynamic_data_stores/dynamic_shader_source_store.hpp"
+#include "opengl/data/shader_program_data.hpp"
+#include "opengl/shading/requirements/shader_program_requirements.hpp"
+#include "opengl/metadata/shader_program_metadata.hpp"
+
+namespace zgl
+{
+
+class shader_program_manager
+{
+ using shader_program_lookup_entry_type = std::pair<
+ shader_program_metadata,
+ shader_program_data
+ >;
+
+public:
+ void process(
+ const dynamic_shader_source_store& shader_sources
+ );
+
+ void get_handles(
+ const dynamic_shader_source_store& shader_sources,
+ std::span requirements,
+ std::span metadata,
+ std::span shader_programs
+ );
+
+protected:
+ std::optional> find_shader_program(
+ const shading::shader_program_requirements& requirements
+ );
+
+ bool link_shader_program(
+ const shader_handle_set& shaders
+ );
+
+ shader_manager m_shader_manager;
+ std::vector m_shader_program_lookup;
+
+private:
+
+ std::vector m_shader_requirements_buffer;
+ std::vector m_shader_metadata_buffer;
+ std::vector shader_set_buffer;
+};
+
+}
diff --git a/include/opengl/data_uploaders/shader_preprocessor.hpp b/include/opengl/data_managers/shader_source_manager.hpp
similarity index 81%
rename from include/opengl/data_uploaders/shader_preprocessor.hpp
rename to include/opengl/data_managers/shader_source_manager.hpp
index 5852aed..8e214c9 100644
--- a/include/opengl/data_uploaders/shader_preprocessor.hpp
+++ b/include/opengl/data_managers/shader_source_manager.hpp
@@ -15,21 +15,20 @@
namespace zgl {
-class shader_preprocessor {
+class shader_source_manager {
public:
- void preprocess(
+ void process(
const dynamic_shader_source_store& shader_sources
);
- void fetch_shader_sources(
+ void get_shader_sources(
const dynamic_shader_source_store& shader_sources,
std::span requirements,
std::span metadata,
std::vector& shader_strings
);
-
protected:
void tokenize_declarations(std::string_view source);
@@ -76,28 +75,6 @@ protected:
);
private:
- inline 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",
- };
-
- inline 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"
- };
-
std::vector m_value_token_buffer;
std::vector m_declaration_token_count_buffer;
std::array m_declaration_type_index_buffer;
diff --git a/include/opengl/data_managers/texture_manager.hpp b/include/opengl/data_managers/texture_manager.hpp
new file mode 100644
index 0000000..2895719
--- /dev/null
+++ b/include/opengl/data_managers/texture_manager.hpp
@@ -0,0 +1,41 @@
+#pragma once
+
+#include
+
+#include "assets/dynamic_read_buffers/dynamic_texture_buffer.hpp"
+#include "assets/dynamic_data_stores/dynamic_texture_store.hpp"
+#include "opengl/handles/texture_handle.hpp"
+#include
+
+#include "opengl/metadata/texture_metadata.hpp"
+#include "opengl/resource_management/resource_manager.hpp"
+
+namespace zgl
+{
+class texture_manager
+{
+public:
+ using store_type = dynamic_texture_store;
+ using store_id_type = store_type::id_type;
+ using metadata_type = texture_metadata;
+ using handle_type = texture_handle;
+ using resource_manager_type = resource_manager;
+ using texture_entry_type = std::pair;
+
+ static constexpr std::size_t min_garbage_collection_count = 4;
+
+ void process(store_type& store);
+
+ std::optional get_handle(store_id_type id);
+
+ void collect_garbage(bool force = false);
+
+private:
+
+ resource_manager_type m_resource_manager;
+
+ std::vector> m_texture_buffer;
+ std::vector m_texture_id_buffer;
+};
+
+}
diff --git a/include/opengl/data_uploaders/shader_program_compiler.hpp b/include/opengl/data_uploaders/shader_program_compiler.hpp
deleted file mode 100644
index d144cc0..0000000
--- a/include/opengl/data_uploaders/shader_program_compiler.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#pragma once
-
-#include
-#include "assets/dynamic_data_stores/dynamic_shader_source_store.hpp"
-#include "opengl/shader_program_lookup.hpp"
-#include "opengl/handles/shader_handle.hpp"
-#include "opengl/handles/shader_program_handle.hpp"
-#include "../metadata/shader_source_metadata.hpp"
-#include "shading/shader_program_requirements.hpp"
-
-namespace zgl
-{
-
-class shader_program_compiler
-{
-
-public:
-
-
- // compile shader programs for given requirements
- // cache shader programs with their capabilities
- // store sstream for creating defines
-
- // register shader source code
- // store define types for these shaders as bitmap
- void register_shader_sources(
- const dynamic_shader_source_store& shader_sources
- );
-
- void compile_shader_programs(
- const dynamic_shader_source_store& shader_sources,
- std::span requirements,
- std::vector& shader_handles
- );
-
- // create metadata for all sources
-
- // get
-ś
-protected:
-
-
-
-private:
- std::vector shader_lookup;
- std::vector shader_program_lookup;
-
-};
-
-}
\ No newline at end of file
diff --git a/include/opengl/data_uploaders/texture_data_uploader.hpp b/include/opengl/data_uploaders/texture_data_uploader.hpp
deleted file mode 100644
index 3ece240..0000000
--- a/include/opengl/data_uploaders/texture_data_uploader.hpp
+++ /dev/null
@@ -1,78 +0,0 @@
-#pragma once
-
-#include "../../assets/dynamic_read_buffers"
-#include "assets/dynamic_data_stores/dynamic_texture_store.hpp"
-#include "opengl/data/texture_data.hpp"
-#include
-
-namespace zgl
-{
-class texture_data_uploader
-{
-
- void upload(
- std::span dynamic_data,
- std::span dynamic_data_ids
- ) {
-
- std::vector texture_ids;
-
- texture_ids.resize(dynamic_data.size());
-
- glGenTextures(texture_ids.size(), texture_ids.data());
-
- const auto invalid_texture_ids = std::ranges::partition(
- texture_ids,
- [](GLuint texture_id)
- {
- 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:
- return false;
- }
-
- 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,
- texture.width(),
- texture.height(),
- 0,
- format,
- GL_UNSIGNED_BYTE,
- texture.data()
- );
- glGenerateMipmap(GL_TEXTURE_2D);
-
- return true;
- }
- );
-
- glBindTexture(GL_TEXTURE_2D, 0);
-
- glDeleteTextures(invalid_texture_ids.size(), invalid_texture_ids.data());
-
- invalid_texture_ids.resize(texture_ids.size() - invalid_texture_ids.size());
- }
-};
-}
diff --git a/include/opengl/error.hpp b/include/opengl/error.hpp
index 8b2b620..e3984c1 100644
--- a/include/opengl/error.hpp
+++ b/include/opengl/error.hpp
@@ -68,6 +68,11 @@ struct category : std::error_category
return { static_cast(e), error_category() };
}
+[[nodiscard]] inline std::error_code get_error()
+{
+ return make_error_code(glGetError());
+}
+
} // namespace zgl
template<>
diff --git a/include/opengl/handles/index_buffer_handle.hpp b/include/opengl/handles/index_buffer_handle.hpp
new file mode 100644
index 0000000..0372f0d
--- /dev/null
+++ b/include/opengl/handles/index_buffer_handle.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include "opengl/resource_management/resource_handle.hpp"
+
+namespace zgl
+{
+
+struct index_buffer_handle : resource_handle
+{
+ inline void bind() const;
+ inline static void unbind();
+};
+
+}
+
+#define INCLUDE_INDEX_BUFFER_HANDLE_IMPLEMENTATION
+#include "opengl/handles/index_buffer_handle.ipp"
+#undef INCLUDE_INDEX_BUFFER_HANDLE_IMPLEMENTATION
\ No newline at end of file
diff --git a/include/opengl/handles/shader_handle_set.hpp b/include/opengl/handles/shader_handle_set.hpp
index e429d3c..56ad7df 100644
--- a/include/opengl/handles/shader_handle_set.hpp
+++ b/include/opengl/handles/shader_handle_set.hpp
@@ -7,7 +7,7 @@ namespace zgl
struct shader_handle_set
{
- std::array stages;
+ std::array stages;
};
}
diff --git a/include/opengl/handles/shader_program_handle.hpp b/include/opengl/handles/shader_program_handle.hpp
index 59fa5fc..5a3d9af 100644
--- a/include/opengl/handles/shader_program_handle.hpp
+++ b/include/opengl/handles/shader_program_handle.hpp
@@ -24,7 +24,9 @@ struct shader_program_handle
[[nodiscard]] uniform_support_type check_uniform_support(std::span uniforms) const;
- GLuint program_id{ 0 };
+ [[nodiscard]] bool valid() const;
+
+ GLuint id{ 0 };
};
}
diff --git a/include/opengl/handles/texture_handle.hpp b/include/opengl/handles/texture_handle.hpp
index 084efc2..61a6b83 100644
--- a/include/opengl/handles/texture_handle.hpp
+++ b/include/opengl/handles/texture_handle.hpp
@@ -1,15 +1,16 @@
#pragma once
-#include "GL/glew.h"
+#include "opengl/resource_management/resource_handle.hpp"
-namespace zgl {
-struct texture_handle
+namespace zgl
+{
+
+struct texture_handle : resource_handle
{
inline void bind() const;
inline static void unbind();
-
- GLuint texture_id{ 0 };
};
+
}
#define INCLUDE_TEXTURE_INSTANCE_IMPLEMENTATION
diff --git a/include/opengl/handles/vertex_buffer_handle.hpp b/include/opengl/handles/vertex_buffer_handle.hpp
new file mode 100644
index 0000000..1c184d2
--- /dev/null
+++ b/include/opengl/handles/vertex_buffer_handle.hpp
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "opengl/resource_management/resource_handle.hpp"
+
+
+namespace zgl
+{
+
+struct vertex_buffer_handle : resource_handle
+{
+ inline void bind() const;
+ inline static void unbind();
+};
+
+}
+
+#define INCLUDE_VERTEX_BUFFER_HANDLE_IMPLEMENTATION
+#include "opengl/handles/vertex_buffer_handle.ipp"
+#undef INCLUDE_VERTEX_BUFFER_HANDLE_IMPLEMENTATION
\ No newline at end of file
diff --git a/include/opengl/metadata/shader_program_metadata.hpp b/include/opengl/metadata/shader_program_metadata.hpp
new file mode 100644
index 0000000..c0e4d96
--- /dev/null
+++ b/include/opengl/metadata/shader_program_metadata.hpp
@@ -0,0 +1,15 @@
+#pragma once
+
+#include "opengl/shading/model_geometry.hpp"
+#include "opengl/shading/features/generic_features.hpp"
+
+namespace zgl {
+
+struct shader_program_metadata
+{
+ shading::model_geometry::types geometry;
+ shading::features::generic::type static_enabled{};
+ shading::features::generic::type dynamic_enable{};
+};
+
+}
diff --git a/include/opengl/metadata/shader_set_metadata.hpp b/include/opengl/metadata/shader_set_metadata.hpp
index 539149f..6f9bb52 100644
--- a/include/opengl/metadata/shader_set_metadata.hpp
+++ b/include/opengl/metadata/shader_set_metadata.hpp
@@ -1,7 +1,5 @@
#pragma once
-#include "opengl/shading/model_geometry.hpp"
-#include "opengl/shading/shader_stage.hpp"
#include "opengl/shading/features/generic_features.hpp"
namespace zgl
diff --git a/include/opengl/metadata/texture_metadata.hpp b/include/opengl/metadata/texture_metadata.hpp
new file mode 100644
index 0000000..7f11651
--- /dev/null
+++ b/include/opengl/metadata/texture_metadata.hpp
@@ -0,0 +1,13 @@
+#pragma once
+
+#include "assets/components/texture_components.hpp"
+
+namespace zgl
+{
+
+struct texture_metadata
+{
+ components::texture::flags components;
+};
+
+}
diff --git a/include/opengl/metadata/vertex_buffer_metadata.hpp b/include/opengl/metadata/vertex_buffer_metadata.hpp
new file mode 100644
index 0000000..80cf2b9
--- /dev/null
+++ b/include/opengl/metadata/vertex_buffer_metadata.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "assets/components/texture_components.hpp"
+#include
+
+#include "GL/glew.h"
+
+namespace zgl
+{
+
+struct vertex_buffer_metadata
+{
+ static constexpr std::size_t max_component_count = 8;
+
+ struct component
+ {
+ GLenum type{ GL_INVALID_ENUM };
+ GLint length{ 0 };
+ };
+
+ std::array components{};
+ GLuint component_count{};
+ GLsizei stride{};
+};
+
+}
diff --git a/include/opengl/resource_management/reference_counter.hpp b/include/opengl/resource_management/reference_counter.hpp
new file mode 100644
index 0000000..58bf6ba
--- /dev/null
+++ b/include/opengl/resource_management/reference_counter.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include "GL/glew.h"
+
+namespace zgl
+{
+
+class reference_counter
+{
+public:
+ using gl_id_type = GLuint;
+
+ virtual void add_reference(gl_id_type id) = 0;
+
+ virtual void remove_reference(gl_id_type id) = 0;
+
+};
+
+
+}
\ No newline at end of file
diff --git a/include/opengl/resource_management/resource_handle.hpp b/include/opengl/resource_management/resource_handle.hpp
new file mode 100644
index 0000000..4c62c62
--- /dev/null
+++ b/include/opengl/resource_management/resource_handle.hpp
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "resource_manager.hpp"
+
+namespace zgl
+{
+
+class resource_handle
+{
+public:
+ using id_type = reference_counter::gl_id_type;
+
+ resource_handle() = default;
+
+ inline resource_handle(id_type id, reference_counter* manager);
+
+ resource_handle(const resource_handle& other) = delete;
+ resource_handle& operator=(const resource_handle& other) = delete;
+
+ inline resource_handle(resource_handle&& other) noexcept;
+ inline resource_handle& operator=(resource_handle&& other) noexcept;
+
+ inline ~resource_handle();
+
+protected:
+ id_type m_id{ 0 };
+
+private:
+ reference_counter* m_counter{ nullptr };
+};
+
+}
+
+#define INCLUDE_RESOURCE_HANDLE_IMPLEMENTATION
+#include "opengl/resource_management/resource_handle.ipp"
+#undef INCLUDE_RESOURCE_HANDLE_IMPLEMENTATION
\ No newline at end of file
diff --git a/include/opengl/resource_management/resource_manager.hpp b/include/opengl/resource_management/resource_manager.hpp
new file mode 100644
index 0000000..e7ffa71
--- /dev/null
+++ b/include/opengl/resource_management/resource_manager.hpp
@@ -0,0 +1,55 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+
+#include "opengl/resource_management/reference_counter.hpp"
+namespace zgl
+{
+
+
+template
+class resource_manager : public reference_counter
+{
+public:
+ using gl_id_type = GLuint;
+ using size_type = std::uint64_t;
+ using resource_entry_type = std::pair;
+
+ friend class resource_handle;
+
+ bool has_resource(StoreID store_id);
+
+ std::optional> get_resource(StoreID store_id);
+
+ void collect_garbage();
+
+ void add_resource(StoreID store_id, gl_id_type gl_id, MetaData meta);
+
+ [[nodiscard]] size_type count_garbage();
+
+ void extract_garbage(std::vector& dst);
+
+ void add_reference(gl_id_type id) override;
+
+ void remove_reference(gl_id_type id) override;
+
+private:
+ static constexpr size_type unused_resource_flag = size_type{ 1 } << (sizeof(size_type) * 8 - 1);
+
+ size_type max_unused_collection_cycle_count;
+
+ std::shared_mutex m_lock;
+ std::unordered_map m_resource_lookup;
+ std::unordered_map m_reference_counters;
+ std::unordered_set m_unused_handles;
+};
+
+}
+
+#define INCLUDE_RESOURCE_MANAGER_IMPLEMENTATION
+#include "opengl/resource_management/resource_manager.ipp"
+#undef INCLUDE_RESOURCE_MANAGER_IMPLEMENTATION
diff --git a/include/opengl/shading/requirements/shader_program_requirements.hpp b/include/opengl/shading/requirements/shader_program_requirements.hpp
index 9b41502..4f58640 100644
--- a/include/opengl/shading/requirements/shader_program_requirements.hpp
+++ b/include/opengl/shading/requirements/shader_program_requirements.hpp
@@ -1,44 +1,16 @@
#pragma once
-#include "model_geometry.hpp"
-#include "shader_stage.hpp"
-#include "features/mesh_features.hpp"
-#include "features/point_cloud_features.hpp"
-#include "features/generic_features.hpp"
+#include "opengl/shading/model_geometry.hpp"
+#include "opengl/shading/features/generic_features.hpp"
namespace zgl::shading
{
-
struct shader_program_requirements
{
-
- static constexpr auto geometry_bits = static_cast(std::bit_width(model_geometry::names.size()));
- static constexpr auto feature_bits = sizeof(features::generic::type) * 8 - geometry_bits;
-
- explicit shader_program_requirements(const features::mesh::flags mesh_features) :
- shader_program_requirements(model_geometry::types::mesh, static_cast(mesh_features)) {}
-
- explicit shader_program_requirements(const features::point_cloud::flags point_cloud_features) :
- shader_program_requirements(model_geometry::types::point_cloud, static_cast(point_cloud_features)) {}
-
- shader_program_requirements(const model_geometry::types geometry_type, const features::generic::type generic_features) :
- geometry_type{ geometry_type }, features{ generic_features } {}
-
-
- [[nodiscard]] auto operator<=>(const shader_program_requirements& other) const noexcept
- {
- return (
- std::tie(this->geometry_type, std::popcount(this->features)) <=>
- std::tie(other.geometry_type, std::popcount(other.features))
- );
- }
-
- [[nodiscard]] bool operator==(const shader_program_requirements& other) const noexcept = default;
-
- model_geometry::types geometry_type : geometry_bits;
- features::generic::type features : feature_bits;
+ model_geometry::types geometry;
+ features::generic::type features;
};
-
+}
/*
struct shader_program_metadata
{
@@ -83,4 +55,3 @@ struct shader_program_metadata
generic_feature_type m_dynamic_enable;
};*/
-};
diff --git a/include/opengl/shading/shader_set.hpp b/include/opengl/shading/shader_set.hpp
deleted file mode 100644
index 0c2fa5e..0000000
--- a/include/opengl/shading/shader_set.hpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma once
-
-#include "opengl/handles/shader_handle.hpp"
-
-namespace zgl
-{
-struct shader_set
-{
- shader_handle vertex_shader;
- shader_handle tesselation_control_shader;
- shader_handle tesselation_evaluation_shader;
- shader_handle geometry_shader;
- shader_handle fragment_shader;
-};
-}
diff --git a/include/opengl/shading/shader_stage.hpp b/include/opengl/shading/shader_stage.hpp
index 5e41bfc..09ee2a9 100644
--- a/include/opengl/shading/shader_stage.hpp
+++ b/include/opengl/shading/shader_stage.hpp
@@ -28,4 +28,12 @@ inline constexpr auto names = std::array{
"fragment"
};
+static constexpr auto mandatory = std::array{
+ true,
+ false,
+ false,
+ false,
+ true
+};
+
}
diff --git a/include/util/reference_counter.hpp b/include/util/reference_counter.hpp
new file mode 100644
index 0000000..e143fcc
--- /dev/null
+++ b/include/util/reference_counter.hpp
@@ -0,0 +1,55 @@
+#pragma once
+
+#include
+#include
+
+/*
+ * Code taken Daniel Anderson's Talk "When Lock-Free Still Isn't Enough" Slide 28:
+ * https://github.com/CppCon/CppCon2024/blob/main/Presentations/When_Lock-Free_Still_Isn't_Enough.pdf
+ */
+
+struct reference_counter
+{
+ using size_type = std::uint64_t;
+
+ static constexpr size_type bit_count = sizeof(size_type) * 8;
+ static constexpr size_type was_zero_flag = size_type{ 1 } << (bit_count - 1);
+ static constexpr size_type has_helped_flag = size_type{ 1 } << (bit_count - 2);
+
+ bool increment()
+ {
+ const auto prev_count = m_counter.fetch_add(1);
+ return (prev_count & was_zero_flag) == 0;
+ }
+
+ bool decrement()
+ {
+ if (m_counter.fetch_sub(1) == 1)
+ {
+ auto e = size_type{};
+ if (m_counter.compare_exchange_strong(e, was_zero_flag))
+ {
+ return true;
+ }
+
+ if ((e & has_helped_flag) and (m_counter.exchange(was_zero_flag) & has_helped_flag))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ size_type count()
+ {
+ auto value = m_counter.load();
+ if (value == 0 and m_counter.compare_exchange_strong(value, was_zero_flag | has_helped_flag))
+ {
+ return 0;
+ }
+ return value & was_zero_flag ? 0 : value;
+ }
+
+private:
+ std::atomic m_counter{ 1 };
+};
diff --git a/source/opengl/data/shader_program_data.ipp b/source/opengl/data/shader_program_data.ipp
index 3389ca7..3d683a0 100755
--- a/source/opengl/data/shader_program_data.ipp
+++ b/source/opengl/data/shader_program_data.ipp
@@ -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;
-}
}
diff --git a/source/opengl/data/texture_data.ipp b/source/opengl/data/texture_data.ipp
index c1d44c8..4c2c8c7 100644
--- a/source/opengl/data/texture_data.ipp
+++ b/source/opengl/data/texture_data.ipp
@@ -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
-std::error_code texture_data::build_from(
- std::span 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 };
}
}
diff --git a/source/opengl/data_managers/mesh_vertex_buffer_manager.cpp b/source/opengl/data_managers/mesh_vertex_buffer_manager.cpp
new file mode 100644
index 0000000..fb0af2b
--- /dev/null
+++ b/source/opengl/data_managers/mesh_vertex_buffer_manager.cpp
@@ -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
+void dynamic_vertex_buffer::build_vertex_buffer(
+ std::vector& vertex_buffer,
+ std::size_t& component_count,
+ std::array& component_types,
+ std::array& component_lengths,
+ GLsizei& stride
+) const {
+ const auto for_all_components = [&](auto&& f, const T default_value)
+ {
+ return std::apply(
+ [&](const auto&... component_buffer)
+ {
+ std::array 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](const std::vector>&, std::size_t)
+ {
+ ++component_count;
+ return zgl::type_utils::to_gl_type();
+ },
+ [&component_count](const std::vector&, std::size_t)
+ {
+ ++component_count;
+ return zgl::type_utils::to_gl_type();
+ }
+ },
+ GLenum{ GL_INVALID_VALUE }
+ );
+
+ const auto element_counts = for_all_components(
+ [](const std::vector& buffer, std::size_t)
+ {
+ return buffer.size();
+ },
+ std::numeric_limits::max()
+ );
+
+ const auto minimum_element_count = std::ranges::min(element_counts);
+
+ component_lengths = for_all_components(
+ ztu::specialised_lambda
+ {
+ [](const std::vector&, std::size_t)
+ {
+ return 1;
+ },
+ [](const std::vector>&, std::size_t)
+ {
+ return Count;
+ }
+ },
+ GLsizei{ 0 }
+ );
+
+ auto component_sizes = std::array{};
+ 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(
+ [&](const std::vector& 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);
+}
\ No newline at end of file
diff --git a/source/opengl/data_uploaders/shader_compiler.cpp b/source/opengl/data_managers/shader_manager.cpp
similarity index 62%
rename from source/opengl/data_uploaders/shader_compiler.cpp
rename to source/opengl/data_managers/shader_manager.cpp
index 890cede..6a8bc1b 100644
--- a/source/opengl/data_uploaders/shader_compiler.cpp
+++ b/source/opengl/data_managers/shader_manager.cpp
@@ -1,7 +1,9 @@
-#include "opengl/data_uploaders/shader_compiler.hpp"
+#include "opengl/data_managers/shader_manager.hpp"
#include
#include
+
+#include "opengl/error.hpp"
#include "util/logger.hpp"
@@ -33,13 +35,17 @@ struct prioritized_metadata_comparator
}
};
+static constexpr auto gl_shader_types = std::array{
+ 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> 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 requirements,
std::span 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(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 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);
}
\ No newline at end of file
diff --git a/source/opengl/data_managers/shader_program_manager.cpp b/source/opengl/data_managers/shader_program_manager.cpp
new file mode 100644
index 0000000..e162f87
--- /dev/null
+++ b/source/opengl/data_managers/shader_program_manager.cpp
@@ -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;
+
+ 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 requirements,
+ std::span metadata,
+ std::span 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> 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;
+}
\ No newline at end of file
diff --git a/source/opengl/data_uploaders/shader_preprocessor.cpp b/source/opengl/data_managers/shader_source_manager.cpp
similarity index 91%
rename from source/opengl/data_uploaders/shader_preprocessor.cpp
rename to source/opengl/data_managers/shader_source_manager.cpp
index 9602dc4..1ff1afd 100644
--- a/source/opengl/data_uploaders/shader_preprocessor.cpp
+++ b/source/opengl/data_managers/shader_source_manager.cpp
@@ -1,4 +1,4 @@
-#include "opengl/data_uploaders/shader_preprocessor.hpp"
+#include "opengl/data_managers/shader_source_manager.hpp"
#include "util/logger.hpp"
#include
@@ -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;
@@ -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 requirements,
std::span 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 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 values,
shader_source_metadata& metadata
) {
@@ -329,7 +352,7 @@ bool zgl::shader_preprocessor::parse_geometry_declaration(
}
template
-void zgl::shader_preprocessor::parse_feature_tokens(
+void zgl::shader_source_manager::parse_feature_tokens(
std::span values,
const ztu::string_lookup& 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 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 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 values,
shader_source_metadata& metadata
) {
@@ -412,7 +435,7 @@ bool zgl::shader_preprocessor::parse_dynamic_enable_declaration(
return true;
}
-std::optional zgl::shader_preprocessor::parse_metadata_from_tokens()
+std::optional zgl::shader_source_manager::parse_metadata_from_tokens()
{
namespace language = shading::shader_metadata_language;
using namespace std::string_view_literals;
diff --git a/source/opengl/data_managers/texture_manager.cpp b/source/opengl/data_managers/texture_manager.cpp
new file mode 100644
index 0000000..8dda669
--- /dev/null
+++ b/source/opengl/data_managers/texture_manager.cpp
@@ -0,0 +1,150 @@
+#include "opengl/data_managers/texture_manager.hpp"
+
+#include
+#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::get_handle(
+ const store_id_type id
+) {
+ return m_resource_manager
+ .get_resource(id)
+ .transform(
+ [](auto& resource)
+ {
+ return *reinterpret_cast(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()
+ );
+ }
+}
\ No newline at end of file
diff --git a/source/opengl/handles/index_buffer_handle.ipp b/source/opengl/handles/index_buffer_handle.ipp
new file mode 100644
index 0000000..593a057
--- /dev/null
+++ b/source/opengl/handles/index_buffer_handle.ipp
@@ -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);
+}
diff --git a/source/opengl/handles/shader_program_handle.cpp b/source/opengl/handles/shader_program_handle.cpp
index 589c813..90136f4 100644
--- a/source/opengl/handles/shader_program_handle.cpp
+++ b/source/opengl/handles/shader_program_handle.cpp
@@ -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{};
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{};
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;
+}
}
diff --git a/source/opengl/handles/shader_program_handle.ipp b/source/opengl/handles/shader_program_handle.ipp
index 537dbbd..a7c6e02 100755
--- a/source/opengl/handles/shader_program_handle.ipp
+++ b/source/opengl/handles/shader_program_handle.ipp
@@ -9,7 +9,7 @@ namespace zgl
{
inline void shader_program_handle::bind() const
{
- glUseProgram(program_id);
+ glUseProgram(id);
}
inline void shader_program_handle::unbind()
diff --git a/source/opengl/handles/texture_handle.ipp b/source/opengl/handles/texture_handle.ipp
index 0693a93..664494f 100644
--- a/source/opengl/handles/texture_handle.ipp
+++ b/source/opengl/handles/texture_handle.ipp
@@ -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()
diff --git a/source/opengl/handles/vertex_buffer_handle.ipp b/source/opengl/handles/vertex_buffer_handle.ipp
new file mode 100644
index 0000000..2236799
--- /dev/null
+++ b/source/opengl/handles/vertex_buffer_handle.ipp
@@ -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);
+}
diff --git a/source/opengl/resource_management/resource_handle.ipp b/source/opengl/resource_management/resource_handle.ipp
new file mode 100644
index 0000000..7ea9910
--- /dev/null
+++ b/source/opengl/resource_management/resource_handle.ipp
@@ -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);
+ }
+}
diff --git a/source/opengl/resource_management/resource_manager.ipp b/source/opengl/resource_management/resource_manager.ipp
new file mode 100644
index 0000000..7319b86
--- /dev/null
+++ b/source/opengl/resource_management/resource_manager.ipp
@@ -0,0 +1,139 @@
+#ifndef INCLUDE_RESOURCE_MANAGER_IMPLEMENTATION
+# error Never include this file directly include 'resource_manager.hpp'
+#endif
+
+#include
+
+
+template
+bool zgl::resource_manager::has_resource(StoreID store_id)
+{
+ std::shared_lock lock(m_lock);
+ return m_resource_lookup.contains(store_id);
+}
+
+template
+void zgl::resource_manager::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
+std::optional> zgl::resource_manager::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
+void zgl::resource_manager::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
+void zgl::resource_manager::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
+void zgl::resource_manager::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 zgl::resource_manager::size_type zgl::resource_manager::count_garbage()
+{
+ std::shared_lock lock(m_lock);
+ return m_unused_handles.size();
+}
+
+template
+void zgl::resource_manager::extract_garbage(
+ std::vector& 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();
+ }
+}
diff --git a/source/opengl/shader_program_lookup.cpp b/source/opengl/shader_program_lookup.cpp
index fd9633a..7f317da 100644
--- a/source/opengl/shader_program_lookup.cpp
+++ b/source/opengl/shader_program_lookup.cpp
@@ -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)
diff --git a/source/rendering/batch_renderers/mesh_batch_renderer.cpp b/source/rendering/batch_renderers/mesh_batch_renderer.cpp
index 426cd92..b610264 100644
--- a/source/rendering/batch_renderers/mesh_batch_renderer.cpp
+++ b/source/rendering/batch_renderers/mesh_batch_renderer.cpp
@@ -120,9 +120,9 @@ std::optional mesh_batch_renderer::add(
ztu::logger::debug(
"shaders: % % %",
- base_shader->program_id,
- point_shader->program_id,
- lit_shader->program_id
+ base_shader->id,
+ point_shader->id,
+ lit_shader->id
);
batch_index = m_batches.size();
diff --git a/source/viewer/asset_loader.cpp b/source/viewer/asset_loader.cpp
index 0f0bfc9..9deab25 100644
--- a/source/viewer/asset_loader.cpp
+++ b/source/viewer/asset_loader.cpp
@@ -556,7 +556,7 @@ bool asset_loader::unload(const zgl::shader_program_handle& shader_handle)
const auto it = std::find_if(
m_gl_shader_program_data.begin(), m_gl_shader_program_data.end(),
[&shader_handle](const auto& gl_shader_data) {
- return gl_shader_data.handle().program_id == shader_handle.program_id;
+ return gl_shader_data.handle().program_id == shader_handle.id;
}
);
diff --git a/source/viewer/dynamic_shader_program_loading.cpp b/source/viewer/dynamic_shader_program_loading.cpp
index 2bb314a..f9ca3b9 100644
--- a/source/viewer/dynamic_shader_program_loading.cpp
+++ b/source/viewer/dynamic_shader_program_loading.cpp
@@ -257,7 +257,7 @@ void viewer::dynamic_shader_program_loading::load_directory(
ztu::logger::debug(
"Linked (vertex: % geometry: % fragment: %) -> %",
vertex.id, geometry.id, fragment.id,
- program_handle.program_id
+ program_handle.id
);