diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c8d290..2512da5 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,11 +102,11 @@ add_executable(z3d main.cpp source/opengl/handles/shader_program_handle.cpp include/opengl/shader_program_lookup.hpp source/opengl/shader_program_lookup.cpp - include/shader_program/attributes/point_cloud_attributes.hpp - include/shader_program/uniforms/mesh_uniforms.hpp - include/shader_program/uniforms/point_cloud_uniforms.hpp - include/shader_program/features/mesh_features.hpp - include/shader_program/features/point_cloud_features.hpp + include/opengl/shading/attributes/point_cloud_attributes.hpp + include/opengl/shading/uniforms/mesh_uniforms.hpp + include/opengl/shading/uniforms/point_cloud_uniforms.hpp + include/opengl/shading/features/mesh_features.hpp + include/opengl/shading/features/point_cloud_features.hpp include/rendering/requirements/mesh_requirements.hpp include/rendering/requirements/point_cloud_requirements.hpp include/rendering/modes/mesh_modes.hpp @@ -179,10 +179,25 @@ add_executable(z3d main.cpp source/assets/prefetch_lookups/pose_prefetch_lookup.cpp include/assets/dynamic_data_store.hpp include/opengl/data_uploaders/shader_program_compiler.hpp - include/shader_program/metadata_type.hpp + include/opengl/metadata/shader_source_metadata.hpp source/opengl/data_uploaders/shader_compiler.cpp - include/shader_program/geometry.hpp - include/shader_program/stage.hpp + 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/shading/shader_metadata_language.hpp + include/opengl/shading/features/generic_features.hpp + include/opengl/shading/features/combined_features.hpp + include/opengl/shading/requirements/shader_source_requirements.hpp + include/opengl/metadata/preprocessed_shader_source_metadata.hpp + include/opengl/shading/requirements/shader_requirements.hpp + include/opengl/metadata/shader_metadata.hpp + include/opengl/metadata/shader_set_metadata.hpp + include/opengl/handles/shader_handle_set.hpp + include/opengl/shading/requirements/shader_set_requirements.hpp ) target_include_directories(z3d PRIVATE include) diff --git a/include/opengl/data/shader_data.hpp b/include/opengl/data/shader_data.hpp index 72a3791..9f7bbdb 100644 --- a/include/opengl/data/shader_data.hpp +++ b/include/opengl/data/shader_data.hpp @@ -7,34 +7,21 @@ namespace zgl { -class shader_data +struct shader_data { -private: - explicit shader_data(GLuint shader_id, GLenum type); - -public: - shader_data() = default; - [[nodiscard]] static std::error_code build_from( - GLenum type, - const std::string& source, - shader_data& data - ); + inline shader_data(GLuint id); shader_data(const shader_data& other) = delete; shader_data& operator=(const shader_data& other) = delete; - shader_data(shader_data&& other) noexcept; - shader_data& operator=(shader_data&& other) noexcept; + inline shader_data(shader_data&& other) noexcept; + inline shader_data& operator=(shader_data&& other) noexcept; - [[nodiscard]] shader_handle handle() const; + inline ~shader_data(); - ~shader_data(); - -private: - shader_handle m_handle{}; - GLenum m_type{ GL_INVALID_ENUM }; + shader_handle handle{}; }; } diff --git a/include/opengl/data_uploaders/shader_compiler.hpp b/include/opengl/data_uploaders/shader_compiler.hpp index 2e1db7b..cd19e51 100644 --- a/include/opengl/data_uploaders/shader_compiler.hpp +++ b/include/opengl/data_uploaders/shader_compiler.hpp @@ -9,195 +9,60 @@ #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 "shader_program/metadata_type.hpp" -#include "shader_program/features/mesh_features.hpp" -#include "shader_program/features/point_cloud_features.hpp" #include "util/string_lookup.hpp" -#include "shader_program/metadata_type.hpp" +#include "shader_preprocessor.hpp" +#include "opengl/metadata/shader_metadata.hpp" +#include "opengl/data/shader_data.hpp" +#include "opengl/handles/shader_handle_set.hpp" +#include "opengl/shading/requirements/shader_requirements.hpp" +#include "opengl/metadata/shader_set_metadata.hpp" +#include "opengl/shading/requirements/shader_set_requirements.hpp" namespace zgl { class shader_program_compiler { + 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 register_shader_sources( + void preprocess( const dynamic_shader_source_store& shader_sources ); void compile_shaders( const dynamic_shader_source_store& shader_sources, - std::span required_capabilities, - std::vector& shader_handles + std::span requirements, + std::span metadata, + std::span shader_sets ); - protected: - void tokenize_declarations( - std::string_view source, - std::vector tokens, - std::vector declaration_token_counts, - std::span declaration_type_indices + shader_handle find_shader( + const shading::shader_requirements& requirements ); - std::optional parse_metadata_from_tokens( - std::span tokens, - std::span declaration_token_counts, - std::span declaration_type_indices - ); - - [[nodiscard]] static bool parse_stage_declaration( - std::span tokens, - shader_program::metadata_type& metadata - ); - - [[nodiscard]] static bool parse_geometry_declaration( - std::span tokens, - shader_program::metadata_type& metadata - ); - - [[nodiscard]] static bool parse_features_declaration( - std::span tokens, - shader_program::metadata_type& metadata - ); - - [[nodiscard]] static bool parse_static_enable_declaration( - std::span tokens, - shader_program::metadata_type& metadata - ); - - [[nodiscard]] static bool parse_dynamic_enable_declaration( - std::span tokens, - shader_program::metadata_type& metadata - ); - - template - static void parse_feature_tokens( - std::span tokens, - const ztu::string_lookup& feature_lookup, - T& features - ); - - std::optional zgl::shader_program_compiler::find_compatible_shader_source( - shader_program::metadata_type& requirements - ); - - template - void add_required_feature_defines( - T toggle_flags, - std::span defines, - std::vector& shader_strings + bool compile_shader( + GLenum shader_type, + std::span source_strings, + shader_data& shader ); private: - enum class metadata_declaration_type : std::size_t - { - stage = 0, - geometry = 1, - features = 2, - static_enable = 3, - dynamic_enable = 4, - invalid = std::numeric_limits::max() - }; + shader_preprocessor m_preprocessor{}; - inline static auto declaration_lookup = ztu::string_lookup{ - { "STAGE", metadata_declaration_type::stage }, - { "GEOMETRY", metadata_declaration_type::geometry }, - { "FEATURES", metadata_declaration_type::features }, - { "STATIC_ENABLE", metadata_declaration_type::static_enable } - { "DYNAMIC_ENABLE", metadata_declaration_type::dynamic_enable } - }; - - inline static auto stage_lookup = ztu::string_lookup{ - { "VERTEX", shader_program::stage::types::vertex }, - { "GEOMETRY", shader_program::stage::types::geometry }, - { "FRAGMENT", shader_program::stage::types::fragment }, - }; - - inline static auto geometry_lookup = ztu::string_lookup{ - { "MESH", shader_program::geometry::types::mesh }, - { "POINT_CLOUD", shader_program::geometry::types::point_cloud } - }; - - inline static auto mesh_feature_lookup = [] - { - using namespace shader_program::features::mesh; - - auto lookup = ztu::string_lookup{}; - lookup.reserve(all.size()); - - constexpr auto all_flags = std::array{ - flags::face, flags::line, flags::point, - flags::luminance, flags::color, flags::alpha, - flags::lighting, flags::texture, flags::uniform_color - }; - - for (const auto& [ define, flag ] : std::ranges::views::zip(defines, all_flags)) - { - lookup.emplace(std::string(define), flag); - } - - return lookup; - }(); - - inline static auto point_cloud_feature_lookup = [] - { - using namespace shader_program::features::point_cloud; - - auto lookup = ztu::string_lookup{}; - lookup.reserve(all.size()); - - constexpr auto all_flags = std::array{ - flags::square, flags::lighting, flags::luminance, - flags::color, flags::alpha, flags::uniform_color, - flags::rainbow - }; - - for (const auto& [ define, flag ] : std::ranges::views::zip(defines, all_flags)) - { - lookup.emplace(std::string(define), flag); - } - - return lookup; - }(); - - inline static auto mesh_feature_defines = [] - { - using namespace shader_program::features::mesh; - - auto statements = std::array{}; - - std::ranges::transform( - defines, - statements.begin(), - [](const auto& name) { - return std::format("#define {}\n", name); - } - ); - - return statements; - }(); - - inline static auto point_cloud_feature_defines = [] - { - using namespace shader_program::features::point_cloud; - - auto statements = std::array{}; - - std::ranges::transform( - defines, - statements.begin(), - [](const auto& name) { - return std::format("#define {}\n", name); - } - ); - - return statements; - }(); - - - std::vector> shader_lookup; + 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; }; } diff --git a/include/opengl/data_uploaders/shader_preprocessor.hpp b/include/opengl/data_uploaders/shader_preprocessor.hpp new file mode 100644 index 0000000..5852aed --- /dev/null +++ b/include/opengl/data_uploaders/shader_preprocessor.hpp @@ -0,0 +1,110 @@ +#pragma once + +#include +#include +#include +#include +#include "util/string_lookup.hpp" + +#include "../metadata/shader_source_metadata.hpp" +#include "opengl/shading/requirements/shader_source_requirements.hpp" +#include "opengl/metadata/preprocessed_shader_source_metadata.hpp" + +#include "assets/dynamic_data_stores/dynamic_shader_source_store.hpp" +#include "opengl/shading/shader_source_set.hpp" + +namespace zgl { + +class shader_preprocessor { + +public: + void preprocess( + const dynamic_shader_source_store& shader_sources + ); + + void fetch_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); + + std::optional parse_metadata_from_tokens(); + + [[nodiscard]] static bool parse_stage_declaration( + std::span values, + shader_source_metadata& metadata + ); + + [[nodiscard]] static bool parse_geometry_declaration( + std::span tokens, + shader_source_metadata& metadata + ); + + [[nodiscard]] static bool parse_features_declaration( + std::span values, + shader_source_metadata& metadata + ); + + [[nodiscard]] static bool parse_static_enable_declaration( + std::span values, + shader_source_metadata& metadata + ); + + [[nodiscard]] static bool parse_dynamic_enable_declaration( + std::span values, + shader_source_metadata& metadata + ); + + template + static void parse_feature_tokens( + std::span values, + const ztu::string_lookup& feature_lookup, + T& features + ); + + static void get_define_strings( + shading::model_geometry::types geometry, + shading::features::generic::type features, + shading::features::generic::type& feature_count, + std::vector& defines + ); + +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; + + using source_lookup_entry_type = std::pair; + using source_lookup_type = std::vector; + + source_lookup_type m_shader_source_lookup; +}; +} diff --git a/include/opengl/data_uploaders/shader_program_compiler.hpp b/include/opengl/data_uploaders/shader_program_compiler.hpp index c491091..d144cc0 100644 --- a/include/opengl/data_uploaders/shader_program_compiler.hpp +++ b/include/opengl/data_uploaders/shader_program_compiler.hpp @@ -3,13 +3,18 @@ #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 +{ -template class shader_program_compiler { - public: +public: // compile shader programs for given requirements @@ -22,21 +27,24 @@ class shader_program_compiler const dynamic_shader_source_store& shader_sources ); - void compile_shaders( + void compile_shader_programs( const dynamic_shader_source_store& shader_sources, - std::span required_capabilities, - std::vector& shader_handles + std::span requirements, + std::vector& shader_handles ); // create metadata for all sources // get - +ś protected: private: - std::unordered_map shader_capabilities; + std::vector shader_lookup; + std::vector shader_program_lookup; }; + +} \ No newline at end of file diff --git a/include/opengl/handles/shader_handle.hpp b/include/opengl/handles/shader_handle.hpp index a6aeee5..7e8e925 100644 --- a/include/opengl/handles/shader_handle.hpp +++ b/include/opengl/handles/shader_handle.hpp @@ -8,6 +8,11 @@ struct shader_handle { constexpr bool operator==(const shader_handle&) const = default; - GLuint shader_id{ 0 }; + constexpr bool valid() const + { + return id != 0; + } + + GLuint id{ 0 }; }; } \ No newline at end of file diff --git a/include/opengl/handles/shader_handle_set.hpp b/include/opengl/handles/shader_handle_set.hpp new file mode 100644 index 0000000..e429d3c --- /dev/null +++ b/include/opengl/handles/shader_handle_set.hpp @@ -0,0 +1,13 @@ +#pragma once +#include "shader_handle.hpp" +#include "opengl/shading/shader_stage.hpp" + +namespace zgl +{ + +struct shader_handle_set +{ + std::array stages; +}; + +} diff --git a/include/opengl/metadata/preprocessed_shader_source_metadata.hpp b/include/opengl/metadata/preprocessed_shader_source_metadata.hpp new file mode 100644 index 0000000..c9faf90 --- /dev/null +++ b/include/opengl/metadata/preprocessed_shader_source_metadata.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "opengl/shading/features/generic_features.hpp" + +namespace zgl +{ +struct preprocessed_shader_source_metadata +{ + shading::features::generic::type static_enabled{}; + shading::features::generic::type dynamic_enable{}; + shading::features::generic::type string_count{}; +}; +} diff --git a/include/opengl/metadata/shader_metadata.hpp b/include/opengl/metadata/shader_metadata.hpp new file mode 100644 index 0000000..c4f3151 --- /dev/null +++ b/include/opengl/metadata/shader_metadata.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "opengl/shading/model_geometry.hpp" +#include "opengl/shading/shader_stage.hpp" +#include "opengl/shading/features/generic_features.hpp" + +namespace zgl +{ +struct shader_metadata +{ + shading::model_geometry::types geometry; + shading::stage::types stage; + 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 new file mode 100644 index 0000000..539149f --- /dev/null +++ b/include/opengl/metadata/shader_set_metadata.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include "opengl/shading/model_geometry.hpp" +#include "opengl/shading/shader_stage.hpp" +#include "opengl/shading/features/generic_features.hpp" + +namespace zgl +{ +struct shader_set_metadata +{ + shading::features::generic::type static_enabled{}; + shading::features::generic::type dynamic_enable{}; +}; +} diff --git a/include/opengl/metadata/shader_source_metadata.hpp b/include/opengl/metadata/shader_source_metadata.hpp new file mode 100644 index 0000000..f3c4c6f --- /dev/null +++ b/include/opengl/metadata/shader_source_metadata.hpp @@ -0,0 +1,91 @@ +#pragma once + +#include +#include + +#include "../shading/model_geometry.hpp" +#include "../shading/shader_stage.hpp" +#include "../shading/features/mesh_features.hpp" +#include "../shading/features/point_cloud_features.hpp" +#include "../shading/features/generic_features.hpp" +#include + +// TODO move implementation to .ipp file +namespace zgl +{ + +template +struct shader_features_set +{ + T features, static_enable, dynamic_enable; + + template + [[nodiscard]] shader_features_set cast() const noexcept + { + return { + .features = static_cast(features), + .static_enable = static_cast(static_enable), + .dynamic_enable = static_cast(dynamic_enable) + }; + } + + // TODO this may not compile + [[nodiscard]] bool operator==(const shader_features_set& other) const noexcept = default; +}; + + +struct shader_source_metadata +{ + union combined_feature_set_type { + shader_features_set mesh; + shader_features_set point_cloud; + }; + + using generic_feature_set_type = shader_features_set; + + shading::model_geometry::types geometry; + combined_feature_set_type feature_set; + shading::stage::types stage; + + [[nodiscard]] generic_feature_set_type generic_feature_set() const noexcept + { + switch (geometry) + { + case shading::model_geometry::types::mesh: + return feature_set.mesh.cast(); + case shading::model_geometry::types::point_cloud: + return feature_set.point_cloud.cast(); + default: + std::unreachable(); + } + } + + void from_generic_feature_set(const generic_feature_set_type& generic_feature_set) noexcept + { + switch (geometry) + { + case shading::model_geometry::types::mesh: + feature_set.mesh = generic_feature_set.cast(); + case shading::model_geometry::types::point_cloud: + feature_set.point_cloud = generic_feature_set.cast(); + } + std::unreachable(); + } + + bool operator==(const shader_source_metadata& other) const noexcept + { + if (this->stage != other.stage) + { + return false; + } + + if (this->geometry != other.geometry) + { + return false; + } + + return this->generic_feature_set() == other.generic_feature_set(); + } +}; + +} diff --git a/include/opengl/shading/attributes/mesh_attributes.hpp b/include/opengl/shading/attributes/mesh_attributes.hpp new file mode 100644 index 0000000..32f3af4 --- /dev/null +++ b/include/opengl/shading/attributes/mesh_attributes.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include "opengl/shader_program_variable.hpp" + +#include "util/enum_bitfield_operators.hpp" +#include +#include + +namespace zgl::shading::attributes::mesh +{ + +enum class flags : std::uint8_t +{ + none = 0, + position = 1 << 0, + normal = 1 << 1, + luminance = 1 << 2, + color = 1 << 3, + alpha = 1 << 4, + tex_coord = 1 << 5 +}; + +constexpr inline auto position = shader_program_variable({ GL_FLOAT_VEC3, 0 }, "model_vertex_position"); +constexpr inline auto normal = shader_program_variable({ GL_FLOAT_VEC3, 1 }, "model_vertex_normal"); +constexpr inline auto luminance = shader_program_variable({ GL_FLOAT, 2 }, "model_vertex_l"); +constexpr inline auto color = shader_program_variable({ GL_FLOAT_VEC3, 2 }, "model_vertex_rgb"); +constexpr inline auto alpha = shader_program_variable({ GL_FLOAT, 3 }, "model_vertex_a"); +constexpr inline auto tex_coord = shader_program_variable({ GL_FLOAT_VEC2, 2 }, "model_vertex_tex_coord"); + +constexpr inline auto all = std::array{ + position, normal, luminance, color, alpha, tex_coord +}; + +constexpr inline auto names = std::array{ + "position", + "normal", + "luminance", + "color", + "alpha", + "tex_coord" +}; + +} + +DEFINE_ENUM_BITFIELD_OPERATORS(zgl::shading::attributes::mesh::flags) diff --git a/include/opengl/shading/attributes/point_cloud_attributes.hpp b/include/opengl/shading/attributes/point_cloud_attributes.hpp new file mode 100644 index 0000000..05b5dc6 --- /dev/null +++ b/include/opengl/shading/attributes/point_cloud_attributes.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include "opengl/shader_program_variable.hpp" +#include +#include "util/enum_bitfield_operators.hpp" +#include + +namespace zgl::shading::attributes::point_cloud +{ + +enum class flags : std::uint8_t +{ + none = 0, + position = 1 << 0, + normal = 1 << 1, + luminance = 1 << 2, + color = 1 << 2, + alpha = 1 << 3 +}; + +constexpr inline auto position = shader_program_variable({ GL_FLOAT_VEC3, 0 }, "model_vertex_position"); +constexpr inline auto normal = shader_program_variable({ GL_FLOAT_VEC3, 1 }, "model_vertex_normal"); +constexpr inline auto luminance = shader_program_variable({ GL_FLOAT_VEC3, 1 }, "model_vertex_l"); +constexpr inline auto color = shader_program_variable({ GL_FLOAT_VEC3, 1 }, "model_vertex_rgb"); +constexpr inline auto alpha = shader_program_variable({ GL_FLOAT_VEC3, 1 }, "model_vertex_a"); + +constexpr inline auto all = std::array{ + position, normal, luminance, color, alpha +}; + +constexpr inline auto names = std::array{ + "position", + "normal", + "luminance", + "color", + "alpha" +}; + + +} + +DEFINE_ENUM_BITFIELD_OPERATORS(zgl::shading::attributes::point_cloud::flags) diff --git a/include/opengl/shading/features/combined_features.hpp b/include/opengl/shading/features/combined_features.hpp new file mode 100644 index 0000000..a328830 --- /dev/null +++ b/include/opengl/shading/features/combined_features.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include + +#include "opengl/shading/model_geometry.hpp" +#include "mesh_features.hpp" +#include "point_cloud_features.hpp" +#include "generic_features.hpp" + +namespace zgl::shading::features::combined +{ +union type +{ + features::mesh::flags mesh; + features::point_cloud::flags point_cloud; + + [[nodiscard]] features::generic::type to_generic(const model_geometry::types geometry) const noexcept + { + switch (geometry) + { + case model_geometry::types::mesh: + return static_cast(mesh); + case model_geometry::types::point_cloud: + return static_cast(point_cloud); + } + std::unreachable(); + } + + void from_generic( + const model_geometry::types geometry, + const features::generic::type new_features + ) noexcept { + switch (geometry) + { + case model_geometry::types::mesh: + mesh = static_cast(new_features); + case model_geometry::types::point_cloud: + point_cloud = static_cast(new_features); + } + std::unreachable(); + } +}; +} diff --git a/include/opengl/shading/features/generic_features.hpp b/include/opengl/shading/features/generic_features.hpp new file mode 100644 index 0000000..105466d --- /dev/null +++ b/include/opengl/shading/features/generic_features.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "mesh_features.hpp" +#include "point_cloud_features.hpp" + +namespace zgl::shading::features::generic +{ +using type = std::make_unsigned_t, + std::underlying_type_t +>>; +} \ No newline at end of file diff --git a/include/shader_program/features/mesh_features.hpp b/include/opengl/shading/features/mesh_features.hpp similarity index 84% rename from include/shader_program/features/mesh_features.hpp rename to include/opengl/shading/features/mesh_features.hpp index 828b276..8981896 100644 --- a/include/shader_program/features/mesh_features.hpp +++ b/include/opengl/shading/features/mesh_features.hpp @@ -1,14 +1,12 @@ #pragma once -#include "assets/components/mesh_vertex_components.hpp" -#include "assets/components/point_cloud_vertex_components.hpp" -#include "assets/components/material_components.hpp" -#include "shader_program/attributes/mesh_attributes.hpp" -#include "shader_program/uniforms/mesh_uniforms.hpp" +#include "opengl/shading/attributes/mesh_attributes.hpp" +#include "opengl/shading/uniforms/mesh_uniforms.hpp" +#include "util/enum_bitfield_operators.hpp" #include #include -namespace shader_program::features::mesh +namespace zgl::shading::features::mesh { struct type @@ -119,16 +117,6 @@ constexpr inline auto names = std::array{ "uniform_color" }; -constexpr inline auto defines = std::array{ - "FACE", - "LINE", - "POINT", - "V_L", - "V_RGB", - "V_A", - "LIGHTING", - "TEXTURE", - "U_RGBA" -}; - } + +DEFINE_ENUM_BITFIELD_OPERATORS(zgl::shading::features::mesh::flags) diff --git a/include/shader_program/features/point_cloud_features.hpp b/include/opengl/shading/features/point_cloud_features.hpp similarity index 87% rename from include/shader_program/features/point_cloud_features.hpp rename to include/opengl/shading/features/point_cloud_features.hpp index 8fe1019..9bd01dc 100644 --- a/include/shader_program/features/point_cloud_features.hpp +++ b/include/opengl/shading/features/point_cloud_features.hpp @@ -1,14 +1,14 @@ #pragma once -#include "shader_program/attributes/point_cloud_attributes.hpp" -#include "shader_program/uniforms/point_cloud_uniforms.hpp" +#include "opengl/shading/attributes/point_cloud_attributes.hpp" +#include "opengl/shading/uniforms/point_cloud_uniforms.hpp" #include "assets/components/mesh_vertex_components.hpp" #include "assets/components/point_cloud_vertex_components.hpp" #include -namespace shader_program::features::point_cloud +namespace zgl::shading::features::point_cloud { struct type @@ -98,15 +98,4 @@ constexpr inline auto names = std::array{ "rainbow" }; -constexpr inline auto defines = std::array{ - "SQUARE", - "LIGHTING", - "V_L", - "V_RGB", - "V_A", - "U_RGBA", - "RAINBOW" -}; - - } diff --git a/include/shader_program/geometry.hpp b/include/opengl/shading/model_geometry.hpp similarity index 74% rename from include/shader_program/geometry.hpp rename to include/opengl/shading/model_geometry.hpp index 273bc91..1edf837 100644 --- a/include/shader_program/geometry.hpp +++ b/include/opengl/shading/model_geometry.hpp @@ -4,7 +4,7 @@ #include #include -namespace shader_program::geometry +namespace zgl::shading::model_geometry { enum class types : std::uint8_t @@ -13,6 +13,8 @@ enum class types : std::uint8_t point_cloud = 1 }; +inline constexpr std::size_t count = 2; + inline constexpr auto names = std::array{ "mesh", "point_cloud" }; diff --git a/include/opengl/shading/requirements/shader_program_requirements.hpp b/include/opengl/shading/requirements/shader_program_requirements.hpp new file mode 100644 index 0000000..9b41502 --- /dev/null +++ b/include/opengl/shading/requirements/shader_program_requirements.hpp @@ -0,0 +1,86 @@ +#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" + +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; +}; + +/* +struct shader_program_metadata +{ + using generic_feature_type = std::common_type_t< + std::underlying_type_t, + std::underlying_type_t + >; + + static constexpr auto geometry_bits = static_cast(std::bit_width(geometry::names.size())); + static constexpr auto feature_bits = sizeof(generic_feature_type) * 8 - geometry_bits; + + explicit shader_program_metadata(const features::mesh::flags static_enabled, const features::mesh::flags dynamic_enable) : + shader_program_metadata( + geometry::types::mesh, + static_cast(static_enabled), + static_cast(dynamic_enable) + ) {} + + explicit shader_program_metadata(const features::point_cloud::flags static_enabled, const features::point_cloud::flags dynamic_enable) : + shader_program_metadata( + geometry::types::point_cloud, + static_cast(static_enabled), + static_cast(dynamic_enable) + ) {} + + shader_program_metadata(const geometry::types geometry_type, const generic_feature_type static_enabled, generic_feature_type dynamic_enable) : + m_geometry_type{ geometry_type }, m_static_enabled{ static_enabled }, m_dynamic_enable{ dynamic_enable } {} + + + [[nodiscard]] auto operator<=>(const shader_program_metadata& other) const noexcept + { + return ( + std::tie(this->m_geometry_type, std::popcount(this->m_static_enabled), std::popcount(this->m_dynamic_enable)) <=> + std::tie(other.m_geometry_type, std::popcount(other.m_static_enabled), std::popcount(other.m_dynamic_enable)) + ); + } + + [[nodiscard]] bool operator==(const shader_program_metadata& other) const noexcept = default; + + geometry::types m_geometry_type : geometry_bits; + generic_feature_type m_static_enabled : feature_bits; + generic_feature_type m_dynamic_enable; +};*/ + +}; diff --git a/include/opengl/shading/requirements/shader_requirements.hpp b/include/opengl/shading/requirements/shader_requirements.hpp new file mode 100644 index 0000000..fe9a586 --- /dev/null +++ b/include/opengl/shading/requirements/shader_requirements.hpp @@ -0,0 +1,8 @@ +#pragma once + +#include "shader_source_requirements.hpp" + +namespace zgl::shading +{ +using shader_requirements = shader_source_requirements; +} diff --git a/include/opengl/shading/requirements/shader_set_requirements.hpp b/include/opengl/shading/requirements/shader_set_requirements.hpp new file mode 100644 index 0000000..e85794c --- /dev/null +++ b/include/opengl/shading/requirements/shader_set_requirements.hpp @@ -0,0 +1,13 @@ +#pragma once +#include "opengl/shading/features/generic_features.hpp" + +namespace zgl::shading +{ + +struct shader_set_requirements +{ + model_geometry::types geometry; + features::generic::type features; +}; + +} diff --git a/include/opengl/shading/requirements/shader_source_requirements.hpp b/include/opengl/shading/requirements/shader_source_requirements.hpp new file mode 100644 index 0000000..187ed14 --- /dev/null +++ b/include/opengl/shading/requirements/shader_source_requirements.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "opengl/shading/model_geometry.hpp" +#include "opengl/shading/shader_stage.hpp" +#include "opengl/shading/features/generic_features.hpp" + + +namespace zgl::shading +{ + struct shader_source_requirements + { + model_geometry::types geometry; + stage::types stage; + features::generic::type features; + }; +} diff --git a/include/opengl/shading/shader_metadata_language.hpp b/include/opengl/shading/shader_metadata_language.hpp new file mode 100644 index 0000000..32fd679 --- /dev/null +++ b/include/opengl/shading/shader_metadata_language.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include +#include +#include "util/string_lookup.hpp" + +#include "model_geometry.hpp" +#include "shader_stage.hpp" +#include "features/mesh_features.hpp" +#include "features/point_cloud_features.hpp" + +namespace zgl::shading::shader_metadata_language +{ + enum class declaration_type : std::size_t + { + stage = 0, + geometry = 1, + features = 2, + static_enable = 3, + dynamic_enable = 4, + invalid = std::numeric_limits::max() + }; + + inline constexpr auto declaration_prefix = std::string_view("\n#pragma "); + inline constexpr auto title_separator = ':'; + inline constexpr auto value_separator = ' '; + + inline auto declaration_lookup = ztu::string_lookup{ + { "STAGE", declaration_type::stage }, + { "GEOMETRY", declaration_type::geometry }, + { "FEATURES", declaration_type::features }, + { "STATIC_ENABLE", declaration_type::static_enable }, + { "DYNAMIC_ENABLE", declaration_type::dynamic_enable } + }; + + inline auto stage_lookup = ztu::string_lookup{ + { "VERTEX", stage::types::vertex }, + { "TESSELATION_CONTROL", stage::types::tesselation_control }, + { "TESSELATION_EVALUATION", stage::types::tesselation_evaluation }, + { "GEOMETRY", stage::types::geometry }, + { "FRAGMENT", stage::types::fragment }, + }; + + inline auto geometry_lookup = ztu::string_lookup{ + { "MESH", model_geometry::types::mesh }, + { "POINT_CLOUD", model_geometry::types::point_cloud } + }; + + inline auto mesh_feature_lookup = ztu::string_lookup{ + { "FACE", features::mesh::flags::face }, + { "LINE", features::mesh::flags::line }, + { "POINT", features::mesh::flags::point }, + { "V_L", features::mesh::flags::luminance }, + { "V_RGB", features::mesh::flags::color }, + { "V_A", features::mesh::flags::alpha }, + { "LIGHTING", features::mesh::flags::lighting }, + { "TEXTURE", features::mesh::flags::texture }, + { "U_RGBA", features::mesh::flags::uniform_color } + }; + + inline auto point_cloud_feature_lookup = ztu::string_lookup{ + { "SQUARE", features::point_cloud::flags::square }, + { "LIGHTING", features::point_cloud::flags::lighting }, + { "V_L", features::point_cloud::flags::luminance }, + { "V_RGB", features::point_cloud::flags::color }, + { "V_A", features::point_cloud::flags::alpha }, + { "U_RGBA", features::point_cloud::flags::uniform_color }, + { "RAINBOW", features::point_cloud::flags::rainbow } + }; +}; \ No newline at end of file diff --git a/include/opengl/shading/shader_set.hpp b/include/opengl/shading/shader_set.hpp new file mode 100644 index 0000000..0c2fa5e --- /dev/null +++ b/include/opengl/shading/shader_set.hpp @@ -0,0 +1,15 @@ +#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_source_set.hpp b/include/opengl/shading/shader_source_set.hpp new file mode 100644 index 0000000..c65142f --- /dev/null +++ b/include/opengl/shading/shader_source_set.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include "features/generic_features.hpp" + +namespace zgl::shading +{ + +struct shader_source_set +{ + + struct compiled_shader_features_set + { + features::generic::type static_enabled; + features::generic::type dynamic_enable; + }; + + std::array compiled_features{}; + std::array string_counts{}; +}; + +} diff --git a/include/opengl/shading/shader_stage.hpp b/include/opengl/shading/shader_stage.hpp new file mode 100644 index 0000000..5e41bfc --- /dev/null +++ b/include/opengl/shading/shader_stage.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include + +namespace zgl::shading::stage +{ + +enum class types : std::uint8_t +{ + vertex = 0, + tesselation_control = 1, + tesselation_evaluation = 2, + geometry = 3, + fragment = 4 +}; + +inline constexpr std::size_t count = 5; + + +inline constexpr auto names = std::array{ + "vertex", + "tesselation_control", + "tesselation_evaluation", + "geometry", + "fragment" +}; + +} diff --git a/include/opengl/shading/uniforms/mesh_uniforms.hpp b/include/opengl/shading/uniforms/mesh_uniforms.hpp new file mode 100644 index 0000000..2d9a966 --- /dev/null +++ b/include/opengl/shading/uniforms/mesh_uniforms.hpp @@ -0,0 +1,75 @@ +#pragma once + +#include "opengl/shader_program_variable.hpp" +#include +#include "util/enum_bitfield_operators.hpp" + +namespace zgl::shading::uniforms::mesh +{ + +enum class flags : std::uint16_t +{ + none = 0, + mvp_matrix = 1 << 0, + model_matrix = 1 << 1, + point_size = 1 << 2, + color = 1 << 3, + tex = 1 << 4, + view_pos = 1 << 5, + point_light_direction = 1 << 6, + point_light_color = 1 << 7, + ambient_light_color = 1 << 8, + ambient_filter = 1 << 9, + diffuse_filter = 1 << 10, + specular_filter = 1 << 11, + shininess = 1 << 12 +}; + +constexpr inline auto mvp_matrix = shader_program_variable({ GL_FLOAT_MAT4, 0 }, "mvp_matrix"); +constexpr inline auto model_matrix = shader_program_variable({ GL_FLOAT_MAT4, 1 }, "model_matrix"); +constexpr inline auto point_size = shader_program_variable({ GL_FLOAT, 2 }, "point_size"); +constexpr inline auto tex = shader_program_variable({ GL_SAMPLER_2D, 3 }, "tex"); +constexpr inline auto color = shader_program_variable({ GL_FLOAT_VEC4, 4 }, "color"); +constexpr inline auto view_pos = shader_program_variable({ GL_FLOAT_VEC3, 5 }, "view_pos"); +constexpr inline auto point_light_direction = shader_program_variable({ GL_FLOAT_VEC3, 6 }, "point_light_direction"); +constexpr inline auto point_light_color = shader_program_variable({ GL_FLOAT_VEC3, 7 }, "point_light_color"); +constexpr inline auto ambient_light_color = shader_program_variable({ GL_FLOAT_VEC3, 8 }, "ambient_light_color"); +constexpr inline auto ambient_filter = shader_program_variable({ GL_FLOAT_VEC3, 9 }, "ambient_filter"); +constexpr inline auto diffuse_filter = shader_program_variable({ GL_FLOAT_VEC3, 10 }, "diffuse_filter"); +constexpr inline auto specular_filter = shader_program_variable({ GL_FLOAT_VEC3, 11 }, "specular_filter"); +constexpr inline auto shininess = shader_program_variable({ GL_FLOAT, 12 }, "shininess"); + +constexpr inline auto all = std::array{ + mvp_matrix, + model_matrix, + point_size, + color, + tex, + view_pos, + point_light_direction, + point_light_color, + ambient_light_color, + ambient_filter, + diffuse_filter, + specular_filter, + shininess +}; + +constexpr inline auto names = std::array{ + "mvp_matrix", + "model_matrix", + "point_size", + "color", + "tex", + "view_pos", + "point_light_direction", + "point_light_color", + "ambient_light_color", + "ambient_filter", + "diffuse_filter", + "specular_filter", + "shininess" +}; +} + +DEFINE_ENUM_BITFIELD_OPERATORS(zgl::shading::uniforms::mesh::flags) diff --git a/include/opengl/shading/uniforms/point_cloud_uniforms.hpp b/include/opengl/shading/uniforms/point_cloud_uniforms.hpp new file mode 100644 index 0000000..a41a5f4 --- /dev/null +++ b/include/opengl/shading/uniforms/point_cloud_uniforms.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include "opengl/shader_program_variable.hpp" +#include "util/enum_bitfield_operators.hpp" +#include + +namespace zgl::shading::uniforms::point_cloud +{ + +enum class flags : std::uint8_t +{ + none = 0, + mvp_matrix = 1 << 0, + point_size = 1 << 1, + color = 1 << 2, + model_matrix = 1 << 3, + camera_position = 1 << 4, + rainbow_offset_y = 1 << 5, + rainbow_scale_y = 1 << 6 +}; + +constexpr inline auto mvp_matrix = shader_program_variable({ GL_FLOAT_MAT4, 0 }, "mvp_matrix"); +constexpr inline auto point_size = shader_program_variable({ GL_FLOAT, 1 }, "point_size"); +constexpr inline auto color = shader_program_variable({ GL_FLOAT_VEC4, 2 }, "color"); +constexpr inline auto model_matrix = shader_program_variable({ GL_FLOAT_MAT4, 3 }, "model_matrix"); +constexpr inline auto camera_position = shader_program_variable({ GL_FLOAT_VEC3, 4 }, "camera_position"); +constexpr inline auto rainbow_offset_y = shader_program_variable({ GL_FLOAT, 5 }, "rainbow_offset_y"); +constexpr inline auto rainbow_scale_y = shader_program_variable({ GL_FLOAT, 6 }, "rainbow_scale_y"); + +constexpr inline auto all = std::array{ + mvp_matrix, + point_size, + color, + model_matrix, + camera_position, + rainbow_offset_y, + rainbow_scale_y +}; + +constexpr inline auto names = std::array{ + "mvp_matrix", + "point_size", + "color", + "model_matrix", + "camera_position", + "rainbow_offset_y", + "rainbow_scale_y" +}; + +} + +DEFINE_ENUM_BITFIELD_OPERATORS(zgl::shading::uniforms::point_cloud::flags) diff --git a/include/rendering/requirements/mesh_requirements.hpp b/include/rendering/requirements/mesh_requirements.hpp index 2c4adea..0ae33e1 100644 --- a/include/rendering/requirements/mesh_requirements.hpp +++ b/include/rendering/requirements/mesh_requirements.hpp @@ -2,7 +2,7 @@ #include "assets/components/material_components.hpp" #include "assets/components/mesh_vertex_components.hpp" -#include "shader_program/features/mesh_features.hpp" +#include "shading/features/mesh_features.hpp" #include "util/enum_bitfield_operators.hpp" #include @@ -12,7 +12,7 @@ namespace rendering::requirements::mesh struct type { - shader_program::features::mesh::indices::type shader_program_requirement_index{}; + shading::features::mesh::indices::type shader_program_requirement_index{}; components::mesh_vertex::flags vertex_requirements{ components::mesh_vertex::flags::none }; @@ -33,32 +33,32 @@ enum class flags : std::uint8_t }; constexpr inline auto position = type{ - .shader_program_requirement_index = shader_program::features::mesh::indices::position, + .shader_program_requirement_index = shading::features::mesh::indices::position, .vertex_requirements = components::mesh_vertex::flags::position }; constexpr inline auto lit = type{ - .shader_program_requirement_index = shader_program::features::mesh::indices::lit, + .shader_program_requirement_index = shading::features::mesh::indices::lit, .vertex_requirements = components::mesh_vertex::flags::normal, .material_requirements = components::material::flags::surface_properties }; constexpr inline auto point = type{ - .shader_program_requirement_index = shader_program::features::mesh::indices::point + .shader_program_requirement_index = shading::features::mesh::indices::point }; constexpr inline auto textured = type{ - .shader_program_requirement_index = shader_program::features::mesh::indices::textured, + .shader_program_requirement_index = shading::features::mesh::indices::textured, .vertex_requirements = components::mesh_vertex::flags::tex_coord, .material_requirements = components::material::flags::texture, }; constexpr inline auto uniform_color = type{ - .shader_program_requirement_index = shader_program::features::mesh::indices::uniform_color + .shader_program_requirement_index = shading::features::mesh::indices::uniform_color }; constexpr inline auto uniform_alpha = type{ - .shader_program_requirement_index = shader_program::features::mesh::indices::uniform_alpha, + .shader_program_requirement_index = shading::features::mesh::indices::uniform_alpha, .material_requirements = components::material::flags::transparency }; diff --git a/include/rendering/requirements/point_cloud_requirements.hpp b/include/rendering/requirements/point_cloud_requirements.hpp index aad024e..8578746 100644 --- a/include/rendering/requirements/point_cloud_requirements.hpp +++ b/include/rendering/requirements/point_cloud_requirements.hpp @@ -1,7 +1,7 @@ #pragma once #include "assets/components/point_cloud_vertex_components.hpp" -#include "shader_program/features/point_cloud_features.hpp" +#include "shading/features/point_cloud_features.hpp" #include #include "util/enum_bitfield_operators.hpp" @@ -11,7 +11,7 @@ namespace rendering::requirements::point_cloud struct type { - shader_program::features::point_cloud::indices::type shader_program_requirement_index{}; + shading::features::point_cloud::indices::type shader_program_requirement_index{}; components::point_cloud_vertex::flags vertex_requirements{ components::point_cloud_vertex::flags::none }; @@ -31,30 +31,30 @@ enum class flags : std::uint8_t constexpr inline auto position = type{ - .shader_program_requirement_index = shader_program::features::point_cloud::indices::position, + .shader_program_requirement_index = shading::features::point_cloud::indices::position, .vertex_requirements = components::point_cloud_vertex::flags::position }; constexpr inline auto rainbow = type{ - .shader_program_requirement_index = shader_program::features::point_cloud::indices::rainbow + .shader_program_requirement_index = shading::features::point_cloud::indices::rainbow }; constexpr inline auto vertex_color = type{ - .shader_program_requirement_index = shader_program::features::point_cloud::indices::vertex_color, + .shader_program_requirement_index = shading::features::point_cloud::indices::vertex_color, .vertex_requirements = components::point_cloud_vertex::flags::color }; constexpr inline auto uniform_color = type{ - .shader_program_requirement_index = shader_program::features::point_cloud::indices::uniform_color + .shader_program_requirement_index = shading::features::point_cloud::indices::uniform_color }; constexpr inline auto normal = type{ - .shader_program_requirement_index = shader_program::features::point_cloud::indices::normal, + .shader_program_requirement_index = shading::features::point_cloud::indices::normal, .vertex_requirements = components::point_cloud_vertex::flags::normal }; constexpr inline auto reflectance = type{ - .shader_program_requirement_index = shader_program::features::point_cloud::indices::reflectance, + .shader_program_requirement_index = shading::features::point_cloud::indices::reflectance, .vertex_requirements = components::point_cloud_vertex::flags::reflectance }; diff --git a/include/shader_program/attributes/mesh_attributes.hpp b/include/shader_program/attributes/mesh_attributes.hpp deleted file mode 100644 index b1e1e94..0000000 --- a/include/shader_program/attributes/mesh_attributes.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "opengl/shader_program_variable.hpp" -#include -#include "util/enum_bitfield_operators.hpp" -#include - -namespace shader_program::attributes::mesh -{ - -enum class flags : std::uint8_t -{ - none = 0, - position = 1 << 0, - normal = 1 << 1, - luminance = 1 << 2, - color = 1 << 3, - alpha = 1 << 4, - tex_coord = 1 << 5 -}; - -constexpr inline auto position = zgl::shader_program_variable({ GL_FLOAT_VEC3, 0 }, "model_vertex_position"); -constexpr inline auto normal = zgl::shader_program_variable({ GL_FLOAT_VEC3, 1 }, "model_vertex_normal"); -constexpr inline auto luminance = zgl::shader_program_variable({ GL_FLOAT, 2 }, "model_vertex_l"); -constexpr inline auto color = zgl::shader_program_variable({ GL_FLOAT_VEC3, 2 }, "model_vertex_rgb"); -constexpr inline auto alpha = zgl::shader_program_variable({ GL_FLOAT, 3 }, "model_vertex_a"); -constexpr inline auto tex_coord = zgl::shader_program_variable({ GL_FLOAT_VEC2, 2 }, "model_vertex_tex_coord"); - -constexpr inline auto all = std::array{ - position, normal, luminance, color, alpha, tex_coord -}; - -constexpr inline auto names = std::array{ - "position", - "normal", - "luminance", - "color", - "alpha", - "tex_coord" -}; - -} - -DEFINE_ENUM_BITFIELD_OPERATORS(shader_program::attributes::mesh::flags) diff --git a/include/shader_program/attributes/point_cloud_attributes.hpp b/include/shader_program/attributes/point_cloud_attributes.hpp deleted file mode 100644 index 131de4e..0000000 --- a/include/shader_program/attributes/point_cloud_attributes.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "opengl/shader_program_variable.hpp" -#include -#include "util/enum_bitfield_operators.hpp" -#include - -namespace shader_program::attributes::point_cloud -{ - -enum class flags : std::uint8_t -{ - none = 0, - position = 1 << 0, - normal = 1 << 1, - luminance = 1 << 2, - color = 1 << 2, - alpha = 1 << 3 -}; - -constexpr inline auto position = zgl::shader_program_variable({ GL_FLOAT_VEC3, 0 }, "model_vertex_position"); -constexpr inline auto normal = zgl::shader_program_variable({ GL_FLOAT_VEC3, 1 }, "model_vertex_normal"); -constexpr inline auto luminance = zgl::shader_program_variable({ GL_FLOAT_VEC3, 1 }, "model_vertex_l"); -constexpr inline auto color = zgl::shader_program_variable({ GL_FLOAT_VEC3, 1 }, "model_vertex_rgb"); -constexpr inline auto alpha = zgl::shader_program_variable({ GL_FLOAT_VEC3, 1 }, "model_vertex_a"); - -constexpr inline auto all = std::array{ - position, normal, luminance, color, alpha -}; - -constexpr inline auto names = std::array{ - "position", - "normal", - "luminance", - "color", - "alpha" -}; - - -} - -DEFINE_ENUM_BITFIELD_OPERATORS(shader_program::attributes::point_cloud::flags) diff --git a/include/shader_program/metadata_type.hpp b/include/shader_program/metadata_type.hpp deleted file mode 100644 index ac44e10..0000000 --- a/include/shader_program/metadata_type.hpp +++ /dev/null @@ -1,185 +0,0 @@ -#pragma once - -#include -#include - -#include "geometry.hpp" -#include "stage.hpp" -#include "features/mesh_features.hpp" -#include "features/point_cloud_features.hpp" - -// TODO move implementation to .ipp file -namespace shader_program -{ - -union combined_feature_type -{ - features::mesh::flags mesh; - features::point_cloud::flags point_cloud; - - using generic_type = std::common_type_t< - std::underlying_type_t, - std::underlying_type_t - >; - - [[nodiscard]] generic_type generic(const geometry::types geometry) const noexcept - { - switch (geometry) - { - case geometry::types::mesh: - return static_cast(mesh); - case geometry::types::point_cloud: - return static_cast(point_cloud); - } - std::unreachable(); - } - - void from_generic( - const geometry::types geometry, - generic_type new_features - ) noexcept { - switch (geometry) - { - case geometry::types::mesh: - mesh = static_cast(new_features); - case geometry::types::point_cloud: - point_cloud = static_cast(new_features); - } - std::unreachable(); - } -}; - -template -struct shader_features_set -{ - T features, static_enable, dynamic_enable; - - template - [[nodiscard]] shader_features_set cast() const noexcept - { - return { - .features = static_cast(features), - .static_enable = static_cast(static_enable), - .dynamic_enable = static_cast(dynamic_enable) - }; - } - - [[nodiscard]] auto operator<=>(const shader_features_set& other) const noexcept requires std::unsigned_integral - { - std::array pop_counts; - - std::ranges::transform( - { - this->features, this->static_enable, this->dynamic_enable, - other.features, other.static_enable, other.dynamic_enable - }, - pop_counts.begin(), - std::popcount - ); - - return ( - std::tie(pop_counts[0], pop_counts[1], pop_counts[2]) <=> - std::tie(pop_counts[3], pop_counts[4], pop_counts[5]) - ); - } - - [[nodiscard]] auto operator<=>(const shader_features_set& other) const noexcept requires std::is_enum_v - { - using integer_type = std::underlying_type_t; - return this->cast() <=> other.cast(); - } - - // TODO this may not compile - [[nodiscard]] bool operator==(const shader_features_set& other) const noexcept = default; -}; - - -struct metadata_type -{ - union combined_feature_set_type { - shader_features_set mesh; - shader_features_set point_cloud; - }; - - using generic_feature_type = std::common_type_t< - std::underlying_type_t, - std::underlying_type_t - >; - - using generic_feature_set_type = shader_features_set; - - stage::types stage; - geometry::types geometry; - combined_feature_set_type feature_set; - - [[nodiscard]] generic_feature_set_type generic_feature_set() const noexcept - { - switch (geometry) - { - case geometry::types::mesh: - return feature_set.mesh.cast(); - case geometry::types::point_cloud: - return feature_set.point_cloud.cast(); - default: - std::unreachable(); - } - } - - void from_generic_feature_set(const generic_feature_set_type& generic_feature_set) noexcept - { - switch (geometry) - { - case geometry::types::mesh: - feature_set.mesh = generic_feature_set.cast(); - case geometry::types::point_cloud: - feature_set.point_cloud = generic_feature_set.cast(); - } - std::unreachable(); - } - - auto operator<=>(const metadata_type& other) const noexcept - { - if (this->stage != other.stage) - { - return this->stage <=> other.stage; - } - - if (this->geometry != other.geometry) - { - return this->geometry <=> other.geometry; - } - - return this->generic_feature_set() <=> other.generic_feature_set(); - } - - bool operator==(const metadata_type& other) const noexcept - { - if (this->stage != other.stage) - { - return false; - } - - if (this->geometry != other.geometry) - { - return false; - } - - return this->generic_feature_set() == other.generic_feature_set(); - } - - struct feature_ignorant_less - { - bool operator()(const metadata_type& a, const metadata_type& b) const - { - return ( - std::tie(a.stage, a.geometry) < - std::tie(b.stage, a.geometry) - ); - } - }; -}; - -inline constexpr auto my_size = sizeof(metadata_type); -inline constexpr auto ma_align = alignof(metadata_type); - -} diff --git a/include/shader_program/stage.hpp b/include/shader_program/stage.hpp deleted file mode 100644 index 5bb0c81..0000000 --- a/include/shader_program/stage.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace shader_program::stage -{ - -enum class types : std::uint8_t -{ - vertex = 0, - geometry = 1, - fragment = 2 -}; - -inline constexpr auto names = std::array{ - "vertex", "geometry", "fragment" -}; - -inline constexpr auto gl_enums = std::array{ - GL_VERTEX_SHADER, - GL_GEOMETRY_SHADER, - GL_FRAGMENT_SHADER -}; - -} - diff --git a/include/shader_program/uniforms/mesh_uniforms.hpp b/include/shader_program/uniforms/mesh_uniforms.hpp deleted file mode 100644 index 56f7ec0..0000000 --- a/include/shader_program/uniforms/mesh_uniforms.hpp +++ /dev/null @@ -1,75 +0,0 @@ -#pragma once - -#include "opengl/shader_program_variable.hpp" -#include -#include "util/enum_bitfield_operators.hpp" - -namespace shader_program::uniforms::mesh -{ - -enum class flags : std::uint16_t -{ - none = 0, - mvp_matrix = 1 << 0, - model_matrix = 1 << 1, - point_size = 1 << 2, - color = 1 << 3, - tex = 1 << 4, - view_pos = 1 << 5, - point_light_direction = 1 << 6, - point_light_color = 1 << 7, - ambient_light_color = 1 << 8, - ambient_filter = 1 << 9, - diffuse_filter = 1 << 10, - specular_filter = 1 << 11, - shininess = 1 << 12 -}; - -constexpr inline auto mvp_matrix = zgl::shader_program_variable({ GL_FLOAT_MAT4, 0 }, "mvp_matrix"); -constexpr inline auto model_matrix = zgl::shader_program_variable({ GL_FLOAT_MAT4, 1 }, "model_matrix"); -constexpr inline auto point_size = zgl::shader_program_variable({ GL_FLOAT, 2 }, "point_size"); -constexpr inline auto tex = zgl::shader_program_variable({ GL_SAMPLER_2D, 3 }, "tex"); -constexpr inline auto color = zgl::shader_program_variable({ GL_FLOAT_VEC4, 4 }, "color"); -constexpr inline auto view_pos = zgl::shader_program_variable({ GL_FLOAT_VEC3, 5 }, "view_pos"); -constexpr inline auto point_light_direction = zgl::shader_program_variable({ GL_FLOAT_VEC3, 6 }, "point_light_direction"); -constexpr inline auto point_light_color = zgl::shader_program_variable({ GL_FLOAT_VEC3, 7 }, "point_light_color"); -constexpr inline auto ambient_light_color = zgl::shader_program_variable({ GL_FLOAT_VEC3, 8 }, "ambient_light_color"); -constexpr inline auto ambient_filter = zgl::shader_program_variable({ GL_FLOAT_VEC3, 9 }, "ambient_filter"); -constexpr inline auto diffuse_filter = zgl::shader_program_variable({ GL_FLOAT_VEC3, 10 }, "diffuse_filter"); -constexpr inline auto specular_filter = zgl::shader_program_variable({ GL_FLOAT_VEC3, 11 }, "specular_filter"); -constexpr inline auto shininess = zgl::shader_program_variable({ GL_FLOAT, 12 }, "shininess"); - -constexpr inline auto all = std::array{ - mvp_matrix, - model_matrix, - point_size, - color, - tex, - view_pos, - point_light_direction, - point_light_color, - ambient_light_color, - ambient_filter, - diffuse_filter, - specular_filter, - shininess -}; - -constexpr inline auto names = std::array{ - "mvp_matrix", - "model_matrix", - "point_size", - "color", - "tex", - "view_pos", - "point_light_direction", - "point_light_color", - "ambient_light_color", - "ambient_filter", - "diffuse_filter", - "specular_filter", - "shininess" -}; -} - -DEFINE_ENUM_BITFIELD_OPERATORS(shader_program::uniforms::mesh::flags) diff --git a/include/shader_program/uniforms/point_cloud_uniforms.hpp b/include/shader_program/uniforms/point_cloud_uniforms.hpp deleted file mode 100644 index 9447481..0000000 --- a/include/shader_program/uniforms/point_cloud_uniforms.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include "opengl/shader_program_variable.hpp" -#include - -namespace shader_program::uniforms::point_cloud -{ - -enum class flags : std::uint8_t -{ - none = 0, - mvp_matrix = 1 << 0, - point_size = 1 << 1, - color = 1 << 2, - model_matrix = 1 << 3, - camera_position = 1 << 4, - rainbow_offset_y = 1 << 5, - rainbow_scale_y = 1 << 6 -}; - -constexpr inline auto mvp_matrix = zgl::shader_program_variable({ GL_FLOAT_MAT4, 0 }, "mvp_matrix"); -constexpr inline auto point_size = zgl::shader_program_variable({ GL_FLOAT, 1 }, "point_size"); -constexpr inline auto color = zgl::shader_program_variable({ GL_FLOAT_VEC4, 2 }, "color"); -constexpr inline auto model_matrix = zgl::shader_program_variable({ GL_FLOAT_MAT4, 3 }, "model_matrix"); -constexpr inline auto camera_position = zgl::shader_program_variable({ GL_FLOAT_VEC3, 4 }, "camera_position"); -constexpr inline auto rainbow_offset_y = zgl::shader_program_variable({ GL_FLOAT, 5 }, "rainbow_offset_y"); -constexpr inline auto rainbow_scale_y = zgl::shader_program_variable({ GL_FLOAT, 6 }, "rainbow_scale_y"); - -constexpr inline auto all = std::array{ - mvp_matrix, - point_size, - color, - model_matrix, - camera_position, - rainbow_offset_y, - rainbow_scale_y -}; - -constexpr inline auto names = std::array{ - "mvp_matrix", - "point_size", - "color", - "model_matrix", - "camera_position", - "rainbow_offset_y", - "rainbow_scale_y" -}; - -} - -DEFINE_ENUM_BITFIELD_OPERATORS(shader_program::uniforms::point_cloud::flags) diff --git a/source/opengl/data/shader_data.ipp b/source/opengl/data/shader_data.ipp index d9fb7b6..1228bb2 100644 --- a/source/opengl/data/shader_data.ipp +++ b/source/opengl/data/shader_data.ipp @@ -4,16 +4,14 @@ namespace zgl { -inline shader_data::shader_data(const GLuint shader_id, const GLenum type) - : m_handle{ shader_id }, m_type{ type } {} +inline shader_data::shader_data(const GLuint id) : + handle{ id } {} inline shader_data::shader_data(shader_data&& other) noexcept { - m_handle = other.m_handle; - m_type = other.m_type; - other.m_handle.shader_id = 0; - other.m_type = GL_INVALID_ENUM; + handle = other.handle; + other.handle.id = 0; } inline shader_data& shader_data::operator=(shader_data&& other) noexcept @@ -22,26 +20,18 @@ inline shader_data& shader_data::operator=(shader_data&& other) noexcept { this->~shader_data(); - m_handle = other.m_handle; - m_type = other.m_type; - other.m_handle.shader_id = 0; - other.m_type = GL_INVALID_ENUM; + handle = other.handle; + other.handle.id = 0; } return *this; } inline shader_data::~shader_data() { - if (m_handle.shader_id) + if (handle.id) { - glDeleteShader(m_handle.shader_id); + glDeleteShader(handle.id); } - m_type = GL_INVALID_ENUM; -} - -inline shader_handle shader_data::handle() const -{ - return m_handle; } } diff --git a/source/opengl/data/shader_program_data.cpp b/source/opengl/data/shader_program_data.cpp index 84c4ebb..686e6a1 100755 --- a/source/opengl/data/shader_program_data.cpp +++ b/source/opengl/data/shader_program_data.cpp @@ -43,8 +43,8 @@ std::error_code shader_program_data::build_from( std::tie(geometry_shader, shader_names[1]), std::tie(fragment_shader, shader_names[2]) }) { - if (shader.shader_id) { - glAttachShader(program_id, shader.shader_id); + if (shader.id) { + glAttachShader(program_id, shader.id); } else { ztu::logger::warn("Using default % shader", name); } diff --git a/source/opengl/data_uploaders/shader_compiler.cpp b/source/opengl/data_uploaders/shader_compiler.cpp index 7e99390..890cede 100644 --- a/source/opengl/data_uploaders/shader_compiler.cpp +++ b/source/opengl/data_uploaders/shader_compiler.cpp @@ -4,431 +4,239 @@ #include #include "util/logger.hpp" -void zgl::shader_program_compiler::tokenize_declarations( - std::string_view source_rest, - std::vector tokens, - std::vector declaration_token_counts, - std::span declaration_type_indices -) { - tokens.clear(); - declaration_token_counts.clear(); - std::ranges::fill(declaration_type_indices, static_cast(metadata_declaration_type::invalid)); - constexpr auto pragma_prefix = std::string_view("\n#pragma "); - constexpr auto title_separator = ':'; - constexpr auto token_separator = ' '; +struct prioritized_metadata_comparator +{ + using type = zgl::shader_metadata; - auto offset = std::string_view::size_type{}; - - auto keyword = pragma_prefix; - - while ((offset = source_rest.find(keyword)) != std::string_view::npos) + bool operator()(const type& a, const type& b) const noexcept { - const auto current_token_count = tokens.size(); - - auto line_end = source_rest.find('\n', offset); - if (line_end == std::string_view::npos) + if (a.geometry != b.geometry) { - line_end = source_rest.length(); + return a.geometry > b.geometry; } - auto declaration = source_rest.substr(offset, line_end - offset); - - if ((offset = declaration.find(title_separator)) == std::string_view::npos) + if (a.stage != b.stage) { - continue; + return a.stage > b.stage; } - const auto title = declaration.substr(0, offset); - if (const auto it = declaration_lookup.find(title); it != declaration_lookup.end()) - { - const auto declaration_type = static_cast(it->second); - declaration_type_indices[declaration_type] = declaration_token_counts.size(); - } - else - { - continue; - } + static constexpr auto more_features = std::popcount; - declaration = declaration.substr(offset); - - if (not declaration.empty() and declaration.front() == token_separator) - { - declaration = declaration.substr(sizeof(token_separator), declaration.length()); - } - - while ((offset = declaration.find(token_separator)) != std::string_view::npos) - { - tokens.emplace_back(declaration.substr(0, offset)); - declaration = declaration.substr(offset + sizeof(token_separator)); - } - - if (not declaration.empty()) - { - tokens.emplace_back(declaration); - } - - declaration_token_counts.emplace_back( - tokens.size() - current_token_count + 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 ); - source_rest = source_rest.substr(line_end + sizeof('\n')); - keyword = pragma_prefix.substr(sizeof('\n')); } -} +}; -bool zgl::shader_program_compiler::parse_stage_declaration( - std::span tokens, - shader_program::metadata_type& metadata + +zgl::shader_handle zgl::shader_program_compiler::find_shader( + const shading::shader_requirements& requirements ) { - if (tokens.size() != 1) - { - ztu::logger::warn("Invalid stage declaration: Expected exactly one token but got %.", tokens.size()); - return false; - } - const auto token = tokens.front(); + auto handle = shader_handle{}; - if (const auto it = stage_lookup.find(token); it != stage_lookup.end()) - { - metadata.stage = it->second; - } - else - { - ztu::logger::warn("Invalid stage declaration: Unknown stage %.", token); - return false; - } - - return true; -} - -bool zgl::shader_program_compiler::parse_geometry_declaration( - std::span tokens, - shader_program::metadata_type& metadata -) { - if (tokens.size() != 1) - { - ztu::logger::warn("Invalid geometry declaration: Expected exactly one token but got %.", tokens.size()); - return false; - } - - const auto token = tokens.front(); - - if (const auto it = geometry_lookup.find(token); it != geometry_lookup.end()) - { - metadata.geometry = it->second; - } - else - { - ztu::logger::warn("Invalid geometry declaration: Unknown geometry %.", token); - return false; - } - - return true; -} - -template -void zgl::shader_program_compiler::parse_feature_tokens( - std::span tokens, - const ztu::string_lookup& feature_lookup, - T& features -) { - features = {}; - - for (const auto token : tokens) - { - if (const auto it = feature_lookup.find(token); it != feature_lookup.end()) + auto shader_it = std::ranges::lower_bound( + m_shader_lookup, + std::pair{ requirements.geometry, requirements.stage }, + std::greater{}, + [](const shader_lookup_entry_type& entry) { - features |= it->second; + const auto& meta = entry.first; + return std::pair{ meta.geometry, meta.stage }; } - else - { - ztu::logger::warn("Ignoring unknown feature token %.", token); - } - } -} - -bool zgl::shader_program_compiler::parse_features_declaration( - std::span tokens, - shader_program::metadata_type& metadata -) { - switch (metadata.geometry) - { - case shader_program::geometry::types::mesh: - parse_feature_tokens(tokens, mesh_feature_lookup, metadata.feature_set.mesh.features); - break; - case shader_program::geometry::types::point_cloud: - parse_feature_tokens(tokens, point_cloud_feature_lookup, metadata.feature_set.point_cloud.features); - break; - default: - ztu::logger::warn("Internal error: Unknown geometry index %.", static_cast(metadata.geometry)); - return false; - } - return true; -} - -bool zgl::shader_program_compiler::parse_static_enable_declaration( - std::span tokens, - shader_program::metadata_type& metadata -) { - switch (metadata.geometry) - { - case shader_program::geometry::types::mesh: - parse_feature_tokens(tokens, mesh_feature_lookup, metadata.feature_set.mesh.static_enable); - break; - case shader_program::geometry::types::point_cloud: - parse_feature_tokens(tokens, point_cloud_feature_lookup, metadata.feature_set.point_cloud.static_enable); - break; - default: - ztu::logger::warn("Internal error: Unknown geometry index %.", static_cast(metadata.geometry)); - return false; - } - return true; -} - -bool zgl::shader_program_compiler::parse_dynamic_enable_declaration( - std::span tokens, - shader_program::metadata_type& metadata -) { - switch (metadata.geometry) - { - case shader_program::geometry::types::mesh: - parse_feature_tokens(tokens, mesh_feature_lookup, metadata.feature_set.mesh.dynamic_enable); - break; - case shader_program::geometry::types::point_cloud: - parse_feature_tokens(tokens, point_cloud_feature_lookup, metadata.feature_set.point_cloud.dynamic_enable); - break; - default: - ztu::logger::warn("Internal error: Unknown geometry index %.", static_cast(metadata.geometry)); - return false; - } - return true; -} - -std::optional zgl::shader_program_compiler::parse_metadata_from_tokens( - std::span tokens, - std::span declaration_token_counts, - std::span declaration_type_indices -) { - using enum metadata_declaration_type; - using namespace std::string_view_literals; - - shader_program::metadata_type data; - - for (const auto [ type, name, parser ] : { - std::make_tuple(stage, "stage"sv, &parse_stage_declaration), - std::make_tuple(geometry, "geometry"sv, &parse_geometry_declaration), - std::make_tuple(features, "features"sv, &parse_features_declaration), - std::make_tuple(static_enable, "static_enable"sv, &parse_static_enable_declaration), - std::make_tuple(dynamic_enable, "dynamic_enable"sv, &parse_dynamic_enable_declaration) - }) { - const auto index = declaration_type_indices[static_cast(type)]; - - if (index == static_cast(invalid)) - { - ztu::logger::warn("Shader metadata error: Missing % declaration.", name); - return std::nullopt; - } - - const auto token_offset = std::accumulate( - declaration_token_counts.begin(), - declaration_token_counts.begin() + index, - std::size_t{} - ); - const auto token_count = declaration_token_counts[index]; - - if (not parser(tokens.subspan(token_offset, token_count), data)) - { - return std::nullopt; - } - } - - return data; -} - -auto zgl::shader_program_compiler::find_compatible_shader_source( - shader_program::metadata_type& requirements -) { - - const auto lower_it = std::ranges::lower_bound( - shader_lookup, - requirements, - shader_program::metadata_type::feature_ignorant_less{}, - &std::pair::first ); - auto generic_requirement_feature_set = requirements.generic_feature_set(); - const auto& required_features = generic_requirement_feature_set.features; + dynamic_shader_source_store::id_type source_id{}; + shading::features::generic::type to_be_enabled{}; while ( - lower_it != shader_lookup.end() and - lower_it->first.geometry == requirements.geometry and - lower_it->first.stage == requirements.stage + shader_it != m_shader_lookup.end() and + shader_it->first.geometry == requirements.geometry and + shader_it->first.stage == requirements.stage ) { - const auto& data = lower_it->first; - const auto& [ features, static_enable, dynamic_enable ] = data.generic_feature_set(); + const auto& [ meta, data ] = *shader_it; - const auto missing_features = required_features & ~features; - const auto unwanted_features = ~required_features & features; - const auto fixed_unwanted_features = unwanted_features & ~static_enable & ~dynamic_enable; + 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 (missing_features == 0 and fixed_unwanted_features == 0) + if (unwanted_static_features == 0 and missing_dynamic_features == 0) { - // Tell caller which features need to be toggled before compilation - // and which features can still be dynamically enabled after compilation. - generic_requirement_feature_set.static_enable = required_features & static_enable; - generic_requirement_feature_set.dynamic_enable = dynamic_enable; - requirements.from_generic_feature_set(generic_requirement_feature_set); + to_be_enabled = req.features & static_enable; + source_id = id; - return lower_it->second; + res.static_enabled = features & ~dynamic_enable & ~unwanted_features; + res.dynamic_enable = dynamic_enable; + + break; } + + ++shader_it; } - return std::nullopt; -} - -template -void add_required_feature_defines( - T toggle_flags, - std::span defines, - std::vector& shader_strings -) { - auto index = std::size_t{}; - while (toggle_flags != T{}) + if (source_id) { - if ((toggle_flags & T{ 1 }) != T{}) + const auto [ shader_source_it, source_found ] = shader_sources.find(source_id); + if (source_found) { - shader_strings.push_back(defines[index].c_str()); + get_define_strings( + req.geometry, + to_be_enabled, + res.string_count, + shader_strings + ); } - toggle_flags >>= 1; - ++index; } + + return handle; } void zgl::shader_program_compiler::compile_shaders( const dynamic_shader_source_store& shader_sources, - std::span requirements_list, - std::vector& shader_handles + std::span requirements, + std::span metadata, + std::span shader_sets ) { + for (auto [ req, shader_set_meta, shader_set ] : std::ranges::views::zip( + requirements, + metadata, + shader_sets + )) { + shader_set = {}; + shader_set_meta = {}; - static constexpr auto max_shader_strings = std::max( - mesh_feature_defines.size(), - point_cloud_feature_defines.size() - ) + 1; + auto shader_req = shading::shader_requirements{ + .geometry = req.geometry, + .stage = {}, + .features = req.features + }; - std::vector shader_strings; - shader_strings.reserve(max_shader_strings); - - - for (auto requirements : requirements_list) - { - auto shader_id = GLuint{}; - - const auto source_id = find_compatible_shader_source(requirements); - if (not source_id) + for (auto [ stage_index, handle ] : std::ranges::views::enumerate(shader_set.stages)) { - continue; + shader_req.stage = static_cast(stage_index); + handle = find_shader(shader_req); + if (not handle.valid()) + { + m_source_requirement_buffer.push_back(shader_req); + } } - - const auto [ shader_source_it, source_found ] = shader_sources.find(*source_id); - if (not source_found) - { - ztu::logger::warn("Missing shader source with id %.", *source_id); - continue; - } - - const auto& shader_source = *shader_source_it; - - if (shader_source.source.empty() and requirements.stage == shader_program::stage::types::geometry) - { - continue; - } - - shader_strings.clear(); - - switch (requirements.geometry) { - case shader_program::geometry::types::mesh: - add_required_feature_defines(requirements.feature_set.mesh.static_enable, mesh_feature_defines, shader_strings); - break; - case shader_program::geometry::types::point_cloud: - add_required_feature_defines(requirements.feature_set.point_cloud.static_enable, point_cloud_feature_defines, shader_strings); - break; - default: - std::unreachable(); - } - - shader_strings.push_back(shader_source.source.data()); - - shader_id = glCreateShader(static_cast(requirements.stage)); - - glShaderSource(shader_id, static_cast(shader_strings.size()), shader_strings.data(), nullptr); - glCompileShader(shader_id); - - GLint success; - glGetShaderiv(shader_id, GL_COMPILE_STATUS, &success); - - if (not success) - { - GLint log_length{}; - glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &log_length); - - auto log = std::string(log_length, ' '); - glGetShaderInfoLog(shader_id, log_length, nullptr, log.data()); - - ztu::logger::error("Error while compiling shader:\n%", log); - - glDeleteShader(shader_id); - shader_id = GLuint{}; - } - - shader_handles.emplace_back(shader_id); } + + + m_preprocessed_shader_source_metadata_buffer.clear(); + m_preprocessed_shader_source_metadata_buffer.resize(m_source_requirement_buffer.size()); + m_source_strings_buffer.clear(); + + m_preprocessor.fetch_shader_sources( + shader_sources, + m_source_requirement_buffer, + m_preprocessed_shader_source_metadata_buffer, + m_source_strings_buffer + ); + + auto source_strings_it = m_source_strings_buffer.begin(); + auto source_req_it = m_source_requirement_buffer.begin(); + auto source_meta_it = m_preprocessed_shader_source_metadata_buffer.begin(); + + const auto prev_shader_count = m_shader_lookup.size(); + + for (auto [ shader_set_meta, shader_set ] : std::ranges::views::zip( metadata, shader_sets)) + { + for (auto [ stage_index, handle ] : std::ranges::views::enumerate(shader_set.stages)) + { + if (not handle.valid()) + { + 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 + }; + + 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)); + } + } + + source_strings_it += source_meta_it->string_count; + ++source_meta_it; + ++source_req_it; + } + } + } + + const auto new_shaders = std::span(m_shader_lookup).subspan(prev_shader_count); + + std::ranges::sort( + new_shaders, + prioritized_metadata_comparator{}, + &shader_lookup_entry_type::first + ); + + std::ranges::inplace_merge( + m_shader_lookup, + m_shader_lookup.begin() + prev_shader_count, + prioritized_metadata_comparator{}, + &shader_lookup_entry_type::first + ); + } -void zgl::shader_program_compiler::register_shader_sources( +bool zgl::shader_program_compiler::compile_shader( + GLenum shader_type, + std::span source_strings, + shader_data& shader +) { + + shader = shader_data(glCreateShader(shader_type)); + + glShaderSource( + shader.handle.id, + static_cast(source_strings.size()), + source_strings.data(), + nullptr + ); + + glCompileShader(shader.handle.id); + + GLint success; + glGetShaderiv(shader.handle.id, GL_COMPILE_STATUS, &success); + + if (not success) + { + GLint log_length{}; + glGetShaderiv(shader.handle.id, GL_INFO_LOG_LENGTH, &log_length); + + auto log = std::string(log_length, ' '); + glGetShaderInfoLog(shader.handle.id, log_length, nullptr, log.data()); + + ztu::logger::error("Error while compiling shader:\n%", log); + + return false; + } + + return true; +} + +void zgl::shader_program_compiler::preprocess( const dynamic_shader_source_store& shader_sources ) { - std::vector tokens; - std::vector declaration_token_counts; - std::array declaration_type_indices; - - tokens.reserve(32); - declaration_token_counts.reserve(4); - - for (const auto& [ id, shader_source ] : shader_sources) - { - tokenize_declarations( - shader_source, - tokens, - declaration_token_counts, - declaration_type_indices - ); - - const auto metadata = parse_metadata_from_tokens( - tokens, - declaration_token_counts, - declaration_type_indices - ); - - if (not metadata) - { - ztu::logger::warn("Ignoring shader % as it contains malformed metadata.", id); - continue; - } - - // Sorted insert should be faster than std::sort and std::unique - // for small numbers of elements and high numbers of duplicates. - const auto it = std::ranges::upper_bound( - shader_lookup, - *metadata, - std::less{}, - &std::pair::first - ); - - if (it != shader_lookup.end() and it->first == *metadata) - { - continue; - } - - shader_lookup.emplace(it, *metadata, id); - } + m_preprocessor.preprocess(shader_sources); } \ No newline at end of file diff --git a/source/opengl/data_uploaders/shader_preprocessor.cpp b/source/opengl/data_uploaders/shader_preprocessor.cpp new file mode 100644 index 0000000..9602dc4 --- /dev/null +++ b/source/opengl/data_uploaders/shader_preprocessor.cpp @@ -0,0 +1,453 @@ +#include "opengl/data_uploaders/shader_preprocessor.hpp" + +#include "util/logger.hpp" +#include +#include +#include + +#include "opengl/shading/shader_metadata_language.hpp" + +struct prioritized_feature_set_comparator +{ + using type = zgl::shader_features_set; + + bool operator()(const type& a, const type& b) const noexcept + { + static constexpr auto more_features = std::popcount; + + return std::ranges::lexicographical_compare( + std::array{ a.dynamic_enable, a.features, a.static_enable }, + std::array{ b.dynamic_enable, b.features, b.static_enable }, + std::greater{}, + more_features, + more_features + ); + } +}; + +struct prioritized_metadata_comparator +{ + using type = zgl::shader_source_metadata; + + bool operator()(const type& a, const type& b) const noexcept + { + if (a.geometry != b.geometry) + { + return a.geometry > b.geometry; + } + + if (a.stage != b.stage) + { + return a.stage > b.stage; + } + + const auto features_a = a.generic_feature_set(); + const auto features_b = b.generic_feature_set(); + + return feature_set_comparator(features_a, features_b); + } + +private: + prioritized_feature_set_comparator feature_set_comparator{}; +}; + + + +void zgl::shader_preprocessor::preprocess( + const dynamic_shader_source_store& shader_sources +) { + namespace language = shading::shader_metadata_language; + + for (const auto& [ id, shader_source ] : shader_sources) + { + m_value_token_buffer.clear(); + m_declaration_token_count_buffer.clear(); + std::ranges::fill( + m_declaration_type_index_buffer, + static_cast(language::declaration_type::invalid) + ); + + tokenize_declarations(shader_source); + + const auto metadata = parse_metadata_from_tokens(); + + if (not metadata) + { + ztu::logger::warn("Ignoring shader % as it contains malformed metadata.", id); + continue; + } + + // Sorted insert should be faster than std::sort and std::unique + // for small numbers of elements and high numbers of duplicates. + const auto it = std::ranges::upper_bound( + m_shader_source_lookup, + *metadata, + prioritized_metadata_comparator{}, + &std::pair::first + ); + + if (it != m_shader_source_lookup.end() and it->first == *metadata) + { + continue; + } + + m_shader_source_lookup.emplace(it, *metadata, id); + } +} + +void zgl::shader_preprocessor::fetch_shader_sources( + const dynamic_shader_source_store& shader_sources, + std::span requirements, + std::span metadata, + std::vector& shader_strings +) { + + assert(requirements.size() == metadata.size()); + + static constexpr auto max_shader_strings = std::max( + mesh_feature_defines.size(), + point_cloud_feature_defines.size() + ) + 1; + + shader_strings.reserve(max_shader_strings); + + std::ranges::transform( + requirements, + metadata.begin(), + [&](const shading::shader_source_requirements& req) + { + auto res = preprocessed_shader_source_metadata{}; + + auto source_it = std::ranges::lower_bound( + m_shader_source_lookup, + std::pair{ req.geometry, req.stage }, + std::greater{}, + [](const source_lookup_entry_type& entry) + { + const auto& meta = entry.first; + return std::pair{ meta.geometry, meta.stage }; + } + ); + + dynamic_shader_source_store::id_type source_id{}; + shading::features::generic::type to_be_enabled{}; + + while ( + source_it != m_shader_source_lookup.end() and + source_it->first.geometry == req.geometry and + source_it->first.stage == req.stage + ) { + const auto& [ meta, id ] = *source_it; + const auto& [ features, static_enable, dynamic_enable ] = meta.generic_feature_set(); + + const auto missing_features = req.features & ~features; + const auto unwanted_features = ~req.features & features; + const auto fixed_unwanted_features = unwanted_features & ~static_enable & ~dynamic_enable; + + if (missing_features == 0 and fixed_unwanted_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; + } + + ++source_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 res; + } + ); +} + +void zgl::shader_preprocessor::get_define_strings( + const shading::model_geometry::types geometry, + shading::features::generic::type features, + shading::features::generic::type& feature_count, + std::vector& defines +) { + std::span all_defines; + + switch (geometry) + { + case shading::model_geometry::types::mesh: + all_defines = mesh_feature_defines; + break; + case shading::model_geometry::types::point_cloud: + all_defines = point_cloud_feature_defines; + break; + default: + std::unreachable(); + } + + auto index = std::size_t{}; + while (features != 0) + { + if ((features & 1) != 0) + { + defines.push_back(all_defines[index]); + ++feature_count; + } + features >>= 1; + ++index; + } +} + + +void zgl::shader_preprocessor::tokenize_declarations( + std::string_view source_rest +) { + namespace language = shading::shader_metadata_language; + + auto offset = std::string_view::size_type{}; + + auto keyword = language::declaration_prefix; + + while ((offset = source_rest.find(keyword)) != std::string_view::npos) + { + const auto current_token_count = m_value_token_buffer.size(); + + auto line_end = source_rest.find('\n', offset); + if (line_end == std::string_view::npos) + { + line_end = source_rest.length(); + } + + auto declaration = source_rest.substr(offset, line_end - offset); + + if ((offset = declaration.find(language::title_separator)) == std::string_view::npos) + { + continue; + } + + const auto title = declaration.substr(0, offset); + if (const auto it = language::declaration_lookup.find(title); it != language::declaration_lookup.end()) + { + const auto declaration_type = static_cast(it->second); + m_declaration_type_index_buffer[declaration_type] = m_declaration_token_count_buffer.size(); + } + else + { + continue; + } + + declaration = declaration.substr(offset); + + if (not declaration.empty() and declaration.front() == language::value_separator) + { + declaration = declaration.substr(sizeof(language::value_separator), declaration.length()); + } + + while ((offset = declaration.find(language::value_separator)) != std::string_view::npos) + { + m_value_token_buffer.emplace_back(declaration.substr(0, offset)); + declaration = declaration.substr(offset + sizeof(language::value_separator)); + } + + if (not declaration.empty()) + { + m_value_token_buffer.emplace_back(declaration); + } + + m_declaration_token_count_buffer.emplace_back( + m_value_token_buffer.size() - current_token_count + ); + source_rest = source_rest.substr(line_end + sizeof('\n')); + keyword = language::declaration_prefix.substr(sizeof('\n')); + } +} + +bool zgl::shader_preprocessor::parse_stage_declaration( + std::span values, + shader_source_metadata& metadata +) { + namespace language = shading::shader_metadata_language; + + if (values.size() != 1) + { + ztu::logger::warn("Invalid stage declaration: Expected exactly one token but got %.", values.size()); + return false; + } + + const auto value = values.front(); + + if (const auto it = language::stage_lookup.find(value); it != language::stage_lookup.end()) + { + metadata.stage = it->second; + } + else + { + ztu::logger::warn("Invalid stage declaration: Unknown stage %.", value); + return false; + } + + return true; +} + +bool zgl::shader_preprocessor::parse_geometry_declaration( + std::span values, + shader_source_metadata& metadata +) { + namespace language = shading::shader_metadata_language; + + if (values.size() != 1) + { + ztu::logger::warn("Invalid geometry declaration: Expected exactly one token but got %.", values.size()); + return false; + } + + const auto value = values.front(); + + if (const auto it = language::geometry_lookup.find(value); it != language::geometry_lookup.end()) + { + metadata.geometry = it->second; + } + else + { + ztu::logger::warn("Invalid geometry declaration: Unknown geometry %.", value); + return false; + } + + return true; +} + +template +void zgl::shader_preprocessor::parse_feature_tokens( + std::span values, + const ztu::string_lookup& feature_lookup, + T& features +) { + features = {}; + + for (const auto value : values) + { + if (const auto it = feature_lookup.find(value); it != feature_lookup.end()) + { + features |= it->second; + } + else + { + ztu::logger::warn("Ignoring unknown feature token %.", value); + } + } +} + +bool zgl::shader_preprocessor::parse_features_declaration( + std::span values, + shader_source_metadata& metadata +) { + namespace language = shading::shader_metadata_language; + + switch (metadata.geometry) + { + case shading::model_geometry::types::mesh: + parse_feature_tokens(values, language::mesh_feature_lookup, metadata.feature_set.mesh.features); + break; + case shading::model_geometry::types::point_cloud: + parse_feature_tokens(values, language::point_cloud_feature_lookup, metadata.feature_set.point_cloud.features); + break; + default: + ztu::logger::warn("Internal error: Unknown geometry index %.", static_cast(metadata.geometry)); + return false; + } + return true; +} + +bool zgl::shader_preprocessor::parse_static_enable_declaration( + std::span values, + shader_source_metadata& metadata +) { + namespace language = shading::shader_metadata_language; + + switch (metadata.geometry) + { + case shading::model_geometry::types::mesh: + parse_feature_tokens(values, language::mesh_feature_lookup, metadata.feature_set.mesh.static_enable); + break; + case shading::model_geometry::types::point_cloud: + parse_feature_tokens(values, language::point_cloud_feature_lookup, metadata.feature_set.point_cloud.static_enable); + break; + default: + ztu::logger::warn("Internal error: Unknown geometry index %.", static_cast(metadata.geometry)); + return false; + } + return true; +} + +bool zgl::shader_preprocessor::parse_dynamic_enable_declaration( + std::span values, + shader_source_metadata& metadata +) { + namespace language = shading::shader_metadata_language; + + switch (metadata.geometry) + { + case shading::model_geometry::types::mesh: + parse_feature_tokens(values, language::mesh_feature_lookup, metadata.feature_set.mesh.dynamic_enable); + break; + case shading::model_geometry::types::point_cloud: + parse_feature_tokens(values, language::point_cloud_feature_lookup, metadata.feature_set.point_cloud.dynamic_enable); + break; + default: + ztu::logger::warn("Internal error: Unknown geometry index %.", static_cast(metadata.geometry)); + return false; + } + return true; +} + +std::optional zgl::shader_preprocessor::parse_metadata_from_tokens() +{ + namespace language = shading::shader_metadata_language; + using namespace std::string_view_literals; + + shader_source_metadata data; + + for (const auto [ type, name, parser ] : + { + std::make_tuple(language::declaration_type::stage, "stage"sv, &parse_stage_declaration), + std::make_tuple(language::declaration_type::geometry, "geometry"sv, &parse_geometry_declaration), + std::make_tuple(language::declaration_type::features, "features"sv, &parse_features_declaration), + std::make_tuple(language::declaration_type::static_enable, "static_enable"sv, &parse_static_enable_declaration), + std::make_tuple(language::declaration_type::dynamic_enable, "dynamic_enable"sv, &parse_dynamic_enable_declaration) + } + ) { + const auto index = m_declaration_type_index_buffer[static_cast(type)]; + + if (index == static_cast(language::declaration_type::invalid)) + { + ztu::logger::warn("Shader metadata error: Missing % declaration.", name); + return std::nullopt; + } + + const auto value_token_offset = std::accumulate( + m_declaration_token_count_buffer.begin(), + m_declaration_token_count_buffer.begin() + index, + std::size_t{} + ); + const auto value_token_count = m_declaration_token_count_buffer[index]; + + if (not parser(std::span(m_value_token_buffer).subspan(value_token_offset, value_token_count), data)) + { + return std::nullopt; + } + } + + return data; +} diff --git a/source/rendering/batch_renderers/mesh_batch_renderer.cpp b/source/rendering/batch_renderers/mesh_batch_renderer.cpp index 4ab5542..426cd92 100644 --- a/source/rendering/batch_renderers/mesh_batch_renderer.cpp +++ b/source/rendering/batch_renderers/mesh_batch_renderer.cpp @@ -1,6 +1,6 @@ #include "rendering/batch_renderers/mesh_batch_renderer.hpp" -#include "shader_program/uniforms/mesh_uniforms.hpp" +#include "shading/uniforms/mesh_uniforms.hpp" #include "util/unroll_bool_template.hpp" #include "util/logger.hpp" // TODO remove #include // TODOE remove @@ -65,7 +65,7 @@ std::optional mesh_batch_renderer::add( ztu::logger::debug("vertex_comps: %", std::bitset<32>{ static_cast(static_cast(vertex_comps)) }); ztu::logger::debug("material_comps: %", std::bitset<32>{ static_cast(static_cast(material_comps)) }); - ztu::logger::debug("lit reqs: %", std::bitset<32>{ static_cast(static_cast(shader_program::features::mesh::lit.uniforms)) }); + ztu::logger::debug("lit reqs: %", std::bitset<32>{ static_cast(static_cast(shading::features::mesh::lit.uniforms)) }); for (std::size_t i{}; i != requirements::mesh::all.size(); ++i) @@ -198,7 +198,7 @@ void render_mesh_batch( ztu::logger::debug("textured: % alpha: % lit: %", Textured, Alpha, Lit);*/ - namespace uniforms = shader_program::uniforms::mesh; + namespace uniforms = shading::uniforms::mesh; for (std::size_t i{}; i != meshes.size(); ++i) { @@ -254,7 +254,7 @@ void mesh_batch_renderer::render( const lighting_setup& lights ) { - namespace uniforms = shader_program::uniforms::mesh; + namespace uniforms = shading::uniforms::mesh; const auto render_mode_index = static_cast(render_mode); diff --git a/source/rendering/batch_renderers/point_cloud_batch_renderer.cpp b/source/rendering/batch_renderers/point_cloud_batch_renderer.cpp index f5b4c6f..f20a2a3 100644 --- a/source/rendering/batch_renderers/point_cloud_batch_renderer.cpp +++ b/source/rendering/batch_renderers/point_cloud_batch_renderer.cpp @@ -3,7 +3,7 @@ #include #include "rendering/requirements/point_cloud_requirements.hpp" -#include "shader_program/uniforms/point_cloud_uniforms.hpp" +#include "shading/uniforms/point_cloud_uniforms.hpp" #include "util/unroll_bool_template.hpp" namespace rendering @@ -149,7 +149,7 @@ void render_point_cloud_batch( const auto point_clouds = batch.point_clouds(); const auto transforms = batch.transforms(); - namespace uniforms = shader_program::uniforms::point_cloud; + namespace uniforms = shading::uniforms::point_cloud; for (std::size_t i{}; i != point_clouds.size(); ++i) { @@ -194,7 +194,7 @@ void point_cloud_batch_renderer::render( const lighting_setup& ) { - namespace uniforms = shader_program::uniforms::point_cloud; + namespace uniforms = shading::uniforms::point_cloud; const auto render_mode_index = static_cast(render_mode); diff --git a/source/rendering/shader_program_lookups/mesh_lookup.cpp b/source/rendering/shader_program_lookups/mesh_lookup.cpp index 2b64a6a..f745a10 100644 --- a/source/rendering/shader_program_lookups/mesh_lookup.cpp +++ b/source/rendering/shader_program_lookups/mesh_lookup.cpp @@ -11,15 +11,15 @@ void mesh_lookup::add( ) { m_shader_program_lookup.add( shader_program_handle, - shader_program::attributes::mesh::all, - shader_program::uniforms::mesh::all + shading::attributes::mesh::all, + shading::uniforms::mesh::all ); } std::optional mesh_lookup::find( requirements::mesh::flags requirements ) const { - auto capability = shader_program::features::mesh::type{}; + auto capability = shading::features::mesh::type{}; auto index = std::size_t{}; @@ -30,7 +30,7 @@ std::optional mesh_lookup::find( if (requirement_flags & 1) { const auto shader_requirements_index = requirements::mesh::all[index].shader_program_requirement_index; - const auto& [ attributes, uniforms ] = shader_program::features::mesh::all[shader_requirements_index]; + const auto& [ attributes, uniforms ] = shading::features::mesh::all[shader_requirements_index]; capability.attributes |= attributes; capability.uniforms |= uniforms; } @@ -47,7 +47,7 @@ std::optional mesh_lookup::find( return m_shader_program_lookup.find( static_cast(capability.attributes), static_cast(capability.uniforms), - shader_program::attributes::mesh::all + shading::attributes::mesh::all ); } diff --git a/source/rendering/shader_program_lookups/point_cloud_lookup.cpp b/source/rendering/shader_program_lookups/point_cloud_lookup.cpp index 27e5050..5817b29 100644 --- a/source/rendering/shader_program_lookups/point_cloud_lookup.cpp +++ b/source/rendering/shader_program_lookups/point_cloud_lookup.cpp @@ -8,8 +8,8 @@ void point_cloud_lookup::add( ) { m_program_lookup.add( shader_program_handle, - shader_program::attributes::point_cloud::all, - shader_program::uniforms::point_cloud::all + shading::attributes::point_cloud::all, + shading::uniforms::point_cloud::all ); } @@ -17,7 +17,7 @@ void point_cloud_lookup::add( std::optional point_cloud_lookup::find( requirements::point_cloud::flags requirements ) const { - auto capability = shader_program::features::point_cloud::type{}; + auto capability = shading::features::point_cloud::type{}; auto index = std::size_t{}; @@ -28,7 +28,7 @@ std::optional point_cloud_lookup::find( if (requirement_flags & 1) { const auto shader_requirements_index = requirements::point_cloud::all[index].shader_program_requirement_index; - const auto& [ attributes, uniforms ] = shader_program::features::point_cloud::all[shader_requirements_index]; + const auto& [ attributes, uniforms ] = shading::features::point_cloud::all[shader_requirements_index]; capability.attributes |= attributes; capability.uniforms |= uniforms; } @@ -40,7 +40,7 @@ std::optional point_cloud_lookup::find( return m_program_lookup.find( static_cast(capability.attributes), static_cast(capability.uniforms), - shader_program::attributes::point_cloud::all + shading::attributes::point_cloud::all ); } diff --git a/source/viewer/dynamic_shader_program_loading.cpp b/source/viewer/dynamic_shader_program_loading.cpp index c686fd2..2bb314a 100644 --- a/source/viewer/dynamic_shader_program_loading.cpp +++ b/source/viewer/dynamic_shader_program_loading.cpp @@ -124,7 +124,7 @@ void viewer::dynamic_shader_program_loading::load_directory( continue; } - ztu::logger::debug("% -> %", filename, shader_handle.shader_id); + ztu::logger::debug("% -> %", filename, shader_handle.id); capabilities.clear(); capabilities.push_back(0); @@ -234,11 +234,11 @@ void viewer::dynamic_shader_program_loading::load_directory( // create shader_program for (const auto& [vertex, geometry, fragment] : programs) { - if (vertex.shader_id == 0 or fragment.shader_id == 0) + if (vertex.id == 0 or fragment.id == 0) { ztu::logger::warn( "Skipping program as the combination is unlikely to be used (vertex: % geometry: % fragment: %).", - vertex.shader_id, geometry.shader_id, fragment.shader_id + vertex.id, geometry.id, fragment.id ); continue; } @@ -256,7 +256,7 @@ void viewer::dynamic_shader_program_loading::load_directory( ztu::logger::debug( "Linked (vertex: % geometry: % fragment: %) -> %", - vertex.shader_id, geometry.shader_id, fragment.shader_id, + vertex.id, geometry.id, fragment.id, program_handle.program_id );