From fde6a2fd7bb1c870752b7941e81c80351499d709 Mon Sep 17 00:00:00 2001 From: zy4n Date: Mon, 3 Mar 2025 20:45:30 +0100 Subject: [PATCH] Fixed bugs in lazy shader compilation. --- CMakeLists.txt | 2 + .../components/mesh_vertex_components.hpp | 3 +- .../point_cloud_vertex_components.hpp | 3 +- .../assets/components/texture_components.hpp | 3 +- .../requirements/mesh_requirements.hpp | 86 ++----- .../requirements/point_cloud_requirements.hpp | 76 +----- .../attributes/mesh_attributes.hpp | 3 +- .../attributes/point_cloud_attributes.hpp | 3 +- .../shader_program/features/mesh_features.hpp | 4 +- .../features/point_cloud_features.hpp | 2 +- include/shader_program/geometry.hpp | 21 ++ include/shader_program/metadata_type.hpp | 233 ++++++++---------- include/shader_program/stage.hpp | 29 +++ .../shader_program/uniforms/mesh_uniforms.hpp | 2 +- .../uniforms/point_cloud_uniforms.hpp | 2 +- include/util/enum_bitfield_operators.hpp | 4 +- shaders/fragment_mesh_face.glsl | 3 +- shaders/fragment_mesh_point.glsl | 3 +- shaders/fragment_point_cloud.glsl | 4 +- shaders/vertex_mesh_face.glsl | 4 +- shaders/vertex_mesh_point.glsl | 4 +- shaders/vertex_point_cloud.glsl | 4 +- .../opengl/data_uploaders/shader_compiler.cpp | 47 ++-- .../batch_renderers/mesh_batch_renderer.cpp | 2 +- .../shader_program_lookups/mesh_lookup.cpp | 4 +- .../point_cloud_lookup.cpp | 4 +- 26 files changed, 234 insertions(+), 321 deletions(-) create mode 100644 include/shader_program/geometry.hpp create mode 100644 include/shader_program/stage.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e03bc57..6c8d290 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -181,6 +181,8 @@ add_executable(z3d main.cpp include/opengl/data_uploaders/shader_program_compiler.hpp include/shader_program/metadata_type.hpp source/opengl/data_uploaders/shader_compiler.cpp + include/shader_program/geometry.hpp + include/shader_program/stage.hpp ) target_include_directories(z3d PRIVATE include) diff --git a/include/assets/components/mesh_vertex_components.hpp b/include/assets/components/mesh_vertex_components.hpp index 42fe50a..0e1d2dd 100755 --- a/include/assets/components/mesh_vertex_components.hpp +++ b/include/assets/components/mesh_vertex_components.hpp @@ -22,7 +22,8 @@ inline constexpr type color = 3; inline constexpr type reflectance = 4; } -enum class flags : std::uint8_t { +enum class flags : std::uint8_t +{ none = 0, position = 1 << indices::position, normal = 1 << indices::normal, diff --git a/include/assets/components/point_cloud_vertex_components.hpp b/include/assets/components/point_cloud_vertex_components.hpp index bcaf1c8..ebec5c5 100755 --- a/include/assets/components/point_cloud_vertex_components.hpp +++ b/include/assets/components/point_cloud_vertex_components.hpp @@ -20,7 +20,8 @@ inline constexpr type color = 2; inline constexpr type reflectance = 3; } // namespace indices -enum class flags : std::uint8_t { +enum class flags : std::uint8_t +{ none = 0, position = 1 << indices::position, normal = 1 << indices::normal, diff --git a/include/assets/components/texture_components.hpp b/include/assets/components/texture_components.hpp index 0ea7f16..496fa46 100644 --- a/include/assets/components/texture_components.hpp +++ b/include/assets/components/texture_components.hpp @@ -11,7 +11,8 @@ using green = std::uint8_t; using blue = std::uint8_t; using luminance = std::uint8_t; -enum class flags : std::uint8_t { +enum class flags : std::uint8_t +{ none = 0, luminance = 1 << 1, red = 1 << 2, diff --git a/include/rendering/requirements/mesh_requirements.hpp b/include/rendering/requirements/mesh_requirements.hpp index 35cab33..2c4adea 100644 --- a/include/rendering/requirements/mesh_requirements.hpp +++ b/include/rendering/requirements/mesh_requirements.hpp @@ -3,6 +3,7 @@ #include "assets/components/material_components.hpp" #include "assets/components/mesh_vertex_components.hpp" #include "shader_program/features/mesh_features.hpp" +#include "util/enum_bitfield_operators.hpp" #include @@ -11,16 +12,16 @@ namespace rendering::requirements::mesh struct type { - shader_program::capabilities::mesh::indices::type shader_program_requirement_index{}; + shader_program::features::mesh::indices::type shader_program_requirement_index{}; components::mesh_vertex::flags vertex_requirements{ components::mesh_vertex::flags::none }; - material_component::flags material_requirements{ - material_component::flags::none + components::material::flags material_requirements{ + components::material::flags::none }; }; -enum class flags : int +enum class flags : std::uint8_t { none = 0, position = 1 << 0, @@ -32,33 +33,33 @@ enum class flags : int }; constexpr inline auto position = type{ - .shader_program_requirement_index = shader_program::capabilities::mesh::indices::position, + .shader_program_requirement_index = shader_program::features::mesh::indices::position, .vertex_requirements = components::mesh_vertex::flags::position }; constexpr inline auto lit = type{ - .shader_program_requirement_index = shader_program::capabilities::mesh::indices::lit, + .shader_program_requirement_index = shader_program::features::mesh::indices::lit, .vertex_requirements = components::mesh_vertex::flags::normal, - .material_requirements = material_component::flags::surface_properties + .material_requirements = components::material::flags::surface_properties }; constexpr inline auto point = type{ - .shader_program_requirement_index = shader_program::capabilities::mesh::indices::point + .shader_program_requirement_index = shader_program::features::mesh::indices::point }; constexpr inline auto textured = type{ - .shader_program_requirement_index = shader_program::capabilities::mesh::indices::textured, + .shader_program_requirement_index = shader_program::features::mesh::indices::textured, .vertex_requirements = components::mesh_vertex::flags::tex_coord, - .material_requirements = material_component::flags::texture, + .material_requirements = components::material::flags::texture, }; constexpr inline auto uniform_color = type{ - .shader_program_requirement_index = shader_program::capabilities::mesh::indices::uniform_color + .shader_program_requirement_index = shader_program::features::mesh::indices::uniform_color }; constexpr inline auto uniform_alpha = type{ - .shader_program_requirement_index = shader_program::capabilities::mesh::indices::uniform_alpha, - .material_requirements = material_component::flags::transparency + .shader_program_requirement_index = shader_program::features::mesh::indices::uniform_alpha, + .material_requirements = components::material::flags::transparency }; constexpr inline auto all = std::array{ @@ -67,61 +68,4 @@ constexpr inline auto all = std::array{ } - -[[nodiscard]] constexpr rendering::requirements::mesh::flags operator|( - const rendering::requirements::mesh::flags& a, const rendering::requirements::mesh::flags& b -) { - return static_cast(static_cast(a) | static_cast(b)); -} - -[[nodiscard]] constexpr rendering::requirements::mesh::flags operator&( - const rendering::requirements::mesh::flags& a, const rendering::requirements::mesh::flags& b -) { - return static_cast(static_cast(a) & static_cast(b)); -} - -[[nodiscard]] constexpr rendering::requirements::mesh::flags operator^( - const rendering::requirements::mesh::flags& a, const rendering::requirements::mesh::flags& b -) { - return static_cast(static_cast(a) ^ static_cast(b)); -} - -[[nodiscard]] constexpr rendering::requirements::mesh::flags operator~(const rendering::requirements::mesh::flags& a) { - return static_cast(~static_cast(a)); -} - -constexpr rendering::requirements::mesh::flags& operator|=(rendering::requirements::mesh::flags& a, const rendering::requirements::mesh::flags& b) { - return a = a | b; -} - -constexpr rendering::requirements::mesh::flags& operator&=(rendering::requirements::mesh::flags& a, const rendering::requirements::mesh::flags& b) { - return a = a & b; -} - -constexpr rendering::requirements::mesh::flags& operator^=(rendering::requirements::mesh::flags& a, const rendering::requirements::mesh::flags& b) { - return a = a ^ b; -} - -[[nodiscard]] constexpr bool operator<( - rendering::requirements::mesh::flags lhs, rendering::requirements::mesh::flags rhs -) { - return static_cast(lhs) < static_cast(rhs); -} - -[[nodiscard]] constexpr bool operator<=( - rendering::requirements::mesh::flags lhs, rendering::requirements::mesh::flags rhs -) { - return static_cast(lhs) <= static_cast(rhs); -} - -[[nodiscard]] constexpr bool operator>( - rendering::requirements::mesh::flags lhs, rendering::requirements::mesh::flags rhs -) { - return static_cast(lhs) > static_cast(rhs); -} - -[[nodiscard]] constexpr bool operator>=( - rendering::requirements::mesh::flags lhs, rendering::requirements::mesh::flags rhs -) { - return static_cast(lhs) >= static_cast(rhs); -} +DEFINE_ENUM_BITFIELD_OPERATORS(rendering::requirements::mesh::flags) diff --git a/include/rendering/requirements/point_cloud_requirements.hpp b/include/rendering/requirements/point_cloud_requirements.hpp index 759ac67..aad024e 100644 --- a/include/rendering/requirements/point_cloud_requirements.hpp +++ b/include/rendering/requirements/point_cloud_requirements.hpp @@ -4,20 +4,21 @@ #include "shader_program/features/point_cloud_features.hpp" #include +#include "util/enum_bitfield_operators.hpp" namespace rendering::requirements::point_cloud { struct type { - shader_program::capabilities::point_cloud::indices::type shader_program_requirement_index{}; + shader_program::features::point_cloud::indices::type shader_program_requirement_index{}; components::point_cloud_vertex::flags vertex_requirements{ components::point_cloud_vertex::flags::none }; }; -enum class flags : int +enum class flags : std::uint8_t { none = 0, position = 1 << 0, @@ -30,30 +31,30 @@ enum class flags : int constexpr inline auto position = type{ - .shader_program_requirement_index = shader_program::capabilities::point_cloud::indices::position, + .shader_program_requirement_index = shader_program::features::point_cloud::indices::position, .vertex_requirements = components::point_cloud_vertex::flags::position }; constexpr inline auto rainbow = type{ - .shader_program_requirement_index = shader_program::capabilities::point_cloud::indices::rainbow + .shader_program_requirement_index = shader_program::features::point_cloud::indices::rainbow }; constexpr inline auto vertex_color = type{ - .shader_program_requirement_index = shader_program::capabilities::point_cloud::indices::vertex_color, + .shader_program_requirement_index = shader_program::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::capabilities::point_cloud::indices::uniform_color + .shader_program_requirement_index = shader_program::features::point_cloud::indices::uniform_color }; constexpr inline auto normal = type{ - .shader_program_requirement_index = shader_program::capabilities::point_cloud::indices::normal, + .shader_program_requirement_index = shader_program::features::point_cloud::indices::normal, .vertex_requirements = components::point_cloud_vertex::flags::normal }; constexpr inline auto reflectance = type{ - .shader_program_requirement_index = shader_program::capabilities::point_cloud::indices::reflectance, + .shader_program_requirement_index = shader_program::features::point_cloud::indices::reflectance, .vertex_requirements = components::point_cloud_vertex::flags::reflectance }; @@ -62,61 +63,4 @@ constexpr inline auto all = std::array{ }; } - -[[nodiscard]] constexpr rendering::requirements::point_cloud::flags operator|( - const rendering::requirements::point_cloud::flags& a, const rendering::requirements::point_cloud::flags& b -) { - return static_cast(static_cast(a) | static_cast(b)); -} - -[[nodiscard]] constexpr rendering::requirements::point_cloud::flags operator&( - const rendering::requirements::point_cloud::flags& a, const rendering::requirements::point_cloud::flags& b -) { - return static_cast(static_cast(a) & static_cast(b)); -} - -[[nodiscard]] constexpr rendering::requirements::point_cloud::flags operator^( - const rendering::requirements::point_cloud::flags& a, const rendering::requirements::point_cloud::flags& b -) { - return static_cast(static_cast(a) ^ static_cast(b)); -} - -[[nodiscard]] constexpr rendering::requirements::point_cloud::flags operator~(const rendering::requirements::point_cloud::flags& a) { - return static_cast(~static_cast(a)); -} - -constexpr rendering::requirements::point_cloud::flags& operator|=(rendering::requirements::point_cloud::flags& a, const rendering::requirements::point_cloud::flags& b) { - return a = a | b; -} - -constexpr rendering::requirements::point_cloud::flags& operator&=(rendering::requirements::point_cloud::flags& a, const rendering::requirements::point_cloud::flags& b) { - return a = a & b; -} - -constexpr rendering::requirements::point_cloud::flags& operator^=(rendering::requirements::point_cloud::flags& a, const rendering::requirements::point_cloud::flags& b) { - return a = a ^ b; -} - -[[nodiscard]] constexpr bool operator<( - rendering::requirements::point_cloud::flags lhs, rendering::requirements::point_cloud::flags rhs -) { - return static_cast(lhs) < static_cast(rhs); -} - -[[nodiscard]] constexpr bool operator<=( - rendering::requirements::point_cloud::flags lhs, rendering::requirements::point_cloud::flags rhs -) { - return static_cast(lhs) <= static_cast(rhs); -} - -[[nodiscard]] constexpr bool operator>( - rendering::requirements::point_cloud::flags lhs, rendering::requirements::point_cloud::flags rhs -) { - return static_cast(lhs) > static_cast(rhs); -} - -[[nodiscard]] constexpr bool operator>=( - rendering::requirements::point_cloud::flags lhs, rendering::requirements::point_cloud::flags rhs -) { - return static_cast(lhs) >= static_cast(rhs); -} +DEFINE_ENUM_BITFIELD_OPERATORS(rendering::requirements::point_cloud::flags) diff --git a/include/shader_program/attributes/mesh_attributes.hpp b/include/shader_program/attributes/mesh_attributes.hpp index 9ebab60..b1e1e94 100644 --- a/include/shader_program/attributes/mesh_attributes.hpp +++ b/include/shader_program/attributes/mesh_attributes.hpp @@ -8,7 +8,8 @@ namespace shader_program::attributes::mesh { -enum class flags : unsigned { +enum class flags : std::uint8_t +{ none = 0, position = 1 << 0, normal = 1 << 1, diff --git a/include/shader_program/attributes/point_cloud_attributes.hpp b/include/shader_program/attributes/point_cloud_attributes.hpp index cebece4..131de4e 100644 --- a/include/shader_program/attributes/point_cloud_attributes.hpp +++ b/include/shader_program/attributes/point_cloud_attributes.hpp @@ -8,7 +8,8 @@ namespace shader_program::attributes::point_cloud { -enum class flags : unsigned { +enum class flags : std::uint8_t +{ none = 0, position = 1 << 0, normal = 1 << 1, diff --git a/include/shader_program/features/mesh_features.hpp b/include/shader_program/features/mesh_features.hpp index e08f888..828b276 100644 --- a/include/shader_program/features/mesh_features.hpp +++ b/include/shader_program/features/mesh_features.hpp @@ -35,7 +35,7 @@ constexpr inline type texture = 7; constexpr inline type uniform_color = 8; } -enum class flags : unsigned +enum class flags : std::uint16_t { none = 0, face = 1 << indices::face, @@ -46,7 +46,7 @@ enum class flags : unsigned alpha = 1 << indices::alpha, lighting = 1 << indices::lighting, texture = 1 << indices::texture, - uniform_color = 1 << indices::uniform_color, + uniform_color = 1 << indices::uniform_color }; constexpr inline auto face = type{ diff --git a/include/shader_program/features/point_cloud_features.hpp b/include/shader_program/features/point_cloud_features.hpp index 8bad731..8fe1019 100644 --- a/include/shader_program/features/point_cloud_features.hpp +++ b/include/shader_program/features/point_cloud_features.hpp @@ -33,7 +33,7 @@ constexpr inline type uniform_color = 5; constexpr inline type rainbow = 6; } -enum class flags : unsigned +enum class flags : std::uint8_t { none = 0, square = 1 << indices::square, diff --git a/include/shader_program/geometry.hpp b/include/shader_program/geometry.hpp new file mode 100644 index 0000000..273bc91 --- /dev/null +++ b/include/shader_program/geometry.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include +#include + +namespace shader_program::geometry +{ + +enum class types : std::uint8_t +{ + mesh = 0, + point_cloud = 1 +}; + +inline constexpr auto names = std::array{ + "mesh", "point_cloud" +}; + +} + diff --git a/include/shader_program/metadata_type.hpp b/include/shader_program/metadata_type.hpp index 5c5cb64..09169ad 100644 --- a/include/shader_program/metadata_type.hpp +++ b/include/shader_program/metadata_type.hpp @@ -3,28 +3,14 @@ #include #include +#include "geometry.hpp" +#include "stage.hpp" #include "features/mesh_features.hpp" #include "features/point_cloud_features.hpp" namespace shader_program { -enum class geometries : int -{ - mesh = 0, - point_cloud = 1 -}; - -enum class stages : GLenum -{ - vertex = GL_VERTEX_SHADER, - geometry = GL_GEOMETRY_SHADER, - fragment = GL_FRAGMENT_SHADER -}; - - - - union combined_feature_type { features::mesh::flags mesh; @@ -35,185 +21,164 @@ union combined_feature_type std::underlying_type_t >; - generic_type generic(const geometries geometry) const noexcept + [[nodiscard]] generic_type generic(const geometry::types geometry) const noexcept { switch (geometry) { - case geometries::mesh: + case geometry::types::mesh: return static_cast(mesh); - case geometries::point_cloud: + case geometry::types::point_cloud: return static_cast(point_cloud); } std::unreachable(); } void from_generic( - const geometries geometry, + const geometry::types geometry, generic_type new_features ) noexcept { switch (geometry) { - case geometries::mesh: + case geometry::types::mesh: mesh = static_cast(new_features); - case geometries::point_cloud: + 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 { - geometries geometry; - stages stage; - combined_feature_type features; - combined_feature_type feature_toggles; + union combined_feature_set_type { + shader_features_set mesh; + shader_features_set point_cloud; + }; - std::pair generic() const noexcept + 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 geometries::mesh: - return { - static_cast(features.mesh), - static_cast(feature_toggles.mesh) - }; - case geometries::point_cloud: - return { - static_cast(features.point_cloud), - static_cast(feature_toggles.point_cloud) - }; + case geometry::types::mesh: + return feature_set.mesh.cast(); + case geometry::types::point_cloud: + return feature_set.point_cloud.cast(); + default: + std::unreachable(); } - std::unreachable(); } - void from_generic( - combined_feature_type::generic_type new_features, - combined_feature_type::generic_type new_feature_toggles - ) noexcept { + void from_generic_feature_set(const generic_feature_set_type& generic_feature_set) noexcept + { switch (geometry) { - case geometries::mesh: - features.mesh = static_cast(new_features); - feature_toggles.mesh = static_cast(new_feature_toggles); - case geometries::point_cloud: - features.point_cloud = static_cast(new_features); - feature_toggles.point_cloud = static_cast(new_feature_toggles); + 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->geometry == other.geometry) + if (this->stage != other.stage) { - switch (this->geometry) - { - case geometries::mesh: - return ( - std::tie(this->stage, this->features.mesh, this->feature_toggles.mesh) <=> - std::tie(other.stage, other.features.mesh, other.feature_toggles.mesh) - ); - case geometries::point_cloud: - return ( - std::tie(this->stage, this->features.point_cloud, this->feature_toggles.point_cloud) <=> - std::tie(other.stage, other.features.point_cloud, other.feature_toggles.point_cloud) - ); - } - std::unreachable(); + return this->stage <=> other.stage; } - else + + 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->geometry == other.geometry) + if (this->stage != other.stage) { - switch (this->geometry) - { - case geometries::mesh: - return ( - std::tie(this->stage, this->features.mesh, this->feature_toggles.mesh) == - std::tie(other.stage, other.features.mesh, other.feature_toggles.mesh) - ); - case geometries::point_cloud: - return ( - std::tie(this->stage, this->features.point_cloud, this->feature_toggles.point_cloud) == - std::tie(other.stage, other.features.point_cloud, other.feature_toggles.point_cloud) - ); - } - std::unreachable(); + return false; } - 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.geometry, a.stage) < - std::tie(a.geometry, b.stage) + std::tie(a.stage, a.geometry) < + std::tie(b.stage, a.geometry) ); } }; - - struct feature_count_less - { - bool operator()(const metadata_type& a, const metadata_type& b) const - { - if (a.geometry == b.geometry) - { - int feature_count{}, feature_toggle_count{}; - int other_feature_count{}, other_feature_toggle_count{}; - - constexpr auto count_features = [](const T features) - { - using int_type = std::underlying_type_t; - using uint_type = std::make_unsigned_t; - return std::popcount(static_cast(static_cast(features))); - }; - - switch (a.geometry) - { - case geometries::mesh: - for (auto& [ count, features ] : { - std::tie(feature_count, a.features.mesh), - std::tie(feature_toggle_count, a.feature_toggles.mesh), - std::tie(other_feature_count, b.features.mesh), - std::tie(other_feature_toggle_count, b.feature_toggles.mesh) - }) { - count = count_features(features); - } - case geometries::point_cloud: - for (auto& [ count, features ] : { - std::tie(feature_count, a.features.point_cloud), - std::tie(feature_toggle_count, a.feature_toggles.point_cloud), - std::tie(other_feature_count, b.features.point_cloud), - std::tie(other_feature_toggle_count, b.feature_toggles.point_cloud) - }) { - count = count_features(features); - } - default: - std::unreachable(); - } - return ( - std::tie(a.stage, feature_count, feature_toggle_count) < - std::tie(b.stage, other_feature_count, other_feature_toggle_count) - ); - } - else - { - return a.geometry < b.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 new file mode 100644 index 0000000..5bb0c81 --- /dev/null +++ b/include/shader_program/stage.hpp @@ -0,0 +1,29 @@ +#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 index c631a81..56f7ec0 100644 --- a/include/shader_program/uniforms/mesh_uniforms.hpp +++ b/include/shader_program/uniforms/mesh_uniforms.hpp @@ -7,7 +7,7 @@ namespace shader_program::uniforms::mesh { -enum class flags : unsigned +enum class flags : std::uint16_t { none = 0, mvp_matrix = 1 << 0, diff --git a/include/shader_program/uniforms/point_cloud_uniforms.hpp b/include/shader_program/uniforms/point_cloud_uniforms.hpp index d6955ee..9447481 100644 --- a/include/shader_program/uniforms/point_cloud_uniforms.hpp +++ b/include/shader_program/uniforms/point_cloud_uniforms.hpp @@ -6,7 +6,7 @@ namespace shader_program::uniforms::point_cloud { -enum class flags : unsigned +enum class flags : std::uint8_t { none = 0, mvp_matrix = 1 << 0, diff --git a/include/util/enum_bitfield_operators.hpp b/include/util/enum_bitfield_operators.hpp index 15e6350..096b35b 100644 --- a/include/util/enum_bitfield_operators.hpp +++ b/include/util/enum_bitfield_operators.hpp @@ -44,12 +44,12 @@ constexpr ENUM_TYPE operator<<( \ ); \ } \ \ -constexpr ENUM_TYPE operator<<( \ +constexpr ENUM_TYPE operator>>( \ ENUM_TYPE& lhs, \ int shift \ ) { \ return static_cast( \ - static_cast>(lhs) << shift \ + static_cast>(lhs) >> shift \ ); \ } \ \ diff --git a/shaders/fragment_mesh_face.glsl b/shaders/fragment_mesh_face.glsl index a80b614..7fcfb99 100644 --- a/shaders/fragment_mesh_face.glsl +++ b/shaders/fragment_mesh_face.glsl @@ -1,7 +1,8 @@ #pragma STAGE: FRAGMENT #pragma GEOMETRY: MESH #pragma FEATURES: FACE LINE V_L V_RGB V_A LIGHTING TEXTURE U_RGBA -#pragma FEATURE_TOGGLES: LIGHTING TEXTURE +#pragma STATIC_ENABLE: LIGHTING TEXTURE +#pragma DYNAMIC_ENABLE: FACE LINE V_L V_RGB V_A U_RGBA //------------[ Uniforms ]------------// diff --git a/shaders/fragment_mesh_point.glsl b/shaders/fragment_mesh_point.glsl index e22e4b6..51154e8 100644 --- a/shaders/fragment_mesh_point.glsl +++ b/shaders/fragment_mesh_point.glsl @@ -1,7 +1,8 @@ #pragma STAGE: FRAGMENT #pragma GEOMETRY: MESH #pragma FEATURES: POINT V_L V_RGB V_A LIGHTING U_RGBA -#pragma FEATURE_TOGGLES: +#pragma STATIC_ENABLE: +#pragma DYNAMIC_ENABLE: V_L V_RGB V_A LIGHTING U_RGBA //------------[ Inputs ]------------// diff --git a/shaders/fragment_point_cloud.glsl b/shaders/fragment_point_cloud.glsl index e7c6440..5804d90 100644 --- a/shaders/fragment_point_cloud.glsl +++ b/shaders/fragment_point_cloud.glsl @@ -1,8 +1,8 @@ #pragma STAGE: FRAGMENT #pragma GEOMETRY: POINT_CLOUD #pragma FEATURES: SQUARE V_L V_RGB V_A LIGHTING U_RGBA RAINBOW -#pragma FEATURE_TOGGLES: - +#pragma STATIC_ENABLE: +#pragma DYNAMIC_ENABLE: V_L V_RGB V_A LIGHTING U_RGBA RAINBOW //------------[ Inputs ]------------// layout (location = 0) in vec4 frag_color; diff --git a/shaders/vertex_mesh_face.glsl b/shaders/vertex_mesh_face.glsl index 197e2e4..b924399 100644 --- a/shaders/vertex_mesh_face.glsl +++ b/shaders/vertex_mesh_face.glsl @@ -1,8 +1,8 @@ #pragma STAGE: VERTEX #pragma GEOMETRY: MESH #pragma FEATURES: FACE LINE V_L V_RGB V_A LIGHTING TEXTURE U_RGBA -#pragma FEATURE_TOGGLES: V_L V_RGB V_A LIGHTING TEXTURE U_RGBA - +#pragma STATIC_ENABLE: V_L V_RGB V_A LIGHTING TEXTURE U_RGBA +#pragma DYNAMIC_ENABLE: FACE LINE #ifdef V_L #ifdef V_RGB diff --git a/shaders/vertex_mesh_point.glsl b/shaders/vertex_mesh_point.glsl index 4045930..9bf04c9 100644 --- a/shaders/vertex_mesh_point.glsl +++ b/shaders/vertex_mesh_point.glsl @@ -1,8 +1,8 @@ #pragma STAGE: VERTEX #pragma GEOMETRY: MESH #pragma FEATURES: POINT V_L V_RGB V_A LIGHTING U_RGBA -#pragma FEATURE_TOGGLES: V_L V_RGB V_A LIGHTING U_RGBA - +#pragma STATIC_ENABLE: V_L V_RGB V_A LIGHTING U_RGBA +#pragma DYNAMIC_ENABLE: #ifdef V_L #ifdef V_RGB diff --git a/shaders/vertex_point_cloud.glsl b/shaders/vertex_point_cloud.glsl index 1b01a18..b6d1444 100644 --- a/shaders/vertex_point_cloud.glsl +++ b/shaders/vertex_point_cloud.glsl @@ -1,8 +1,8 @@ #pragma STAGE: VERTEX #pragma GEOMETRY: POINT_CLOUD #pragma FEATURES: SQUARE V_L V_RGB V_A LIGHTING U_RGBA RAINBOW -#pragma FEATURE_TOGGLES: V_L V_RGB V_A LIGHTING U_RGBA RAINBOW - +#pragma STATIC_ENABLE: V_L V_RGB V_A LIGHTING U_RGBA RAINBOW +#pragma DYNAMIC_ENABLE: #ifdef V_L #ifdef V_RGB diff --git a/source/opengl/data_uploaders/shader_compiler.cpp b/source/opengl/data_uploaders/shader_compiler.cpp index b8ab860..acc7a53 100644 --- a/source/opengl/data_uploaders/shader_compiler.cpp +++ b/source/opengl/data_uploaders/shader_compiler.cpp @@ -153,10 +153,10 @@ bool zgl::shader_program_compiler::parse_features_declaration( ) { switch (metadata.geometry) { - case shader_program::geometries::mesh: + case shader_program::geometry::types::mesh: parse_feature_tokens(tokens, mesh_feature_lookup, metadata.features.mesh); break; - case shader_program::geometries::point_cloud: + case shader_program::geometry::types::point_cloud: parse_feature_tokens(tokens, point_cloud_feature_lookup, metadata.features.point_cloud); break; default: @@ -172,11 +172,11 @@ bool zgl::shader_program_compiler::parse_feature_toggles_declaration( ) { switch (metadata.geometry) { - case shader_program::geometries::mesh: - parse_feature_tokens(tokens, mesh_feature_lookup, metadata.feature_toggles.mesh); + case shader_program::geometry::types::mesh: + parse_feature_tokens(tokens, mesh_feature_lookup, metadata.static_enable.mesh); break; - case shader_program::geometries::point_cloud: - parse_feature_tokens(tokens, point_cloud_feature_lookup, metadata.feature_toggles.point_cloud); + case shader_program::geometry::types::point_cloud: + parse_feature_tokens(tokens, point_cloud_feature_lookup, metadata.static_enable.point_cloud); break; default: ztu::logger::warn("Internal error: Unknown geometry index %.", static_cast(metadata.geometry)); @@ -236,27 +236,28 @@ auto zgl::shader_program_compiler::find_compatible_shader_source( &std::pair::first ); - if (lower_it == shader_lookup.end()) { - return std::nullopt; - } - - const auto required_features = requirements.features.generic(requirements.geometry); + auto generic_requirement_feature_set = requirements.generic_feature_set(); + const auto& required_features = generic_requirement_feature_set.features; while ( + lower_it != shader_lookup.end() and lower_it->first.geometry == requirements.geometry and lower_it->first.stage == requirements.stage ) { const auto& data = lower_it->first; - const auto& [ features, feature_toggles ] = data.generic(); + const auto& [ features, static_enable, dynamic_enable ] = data.generic_feature_set(); const auto missing_features = required_features & ~features; - const auto extra_features = ~required_features & features; - const auto untoggleable_extra_features = extra_features & ~feature_toggles; + const auto unwanted_features = ~required_features & features; + const auto fixed_unwanted_features = unwanted_features & ~static_enable & ~dynamic_enable; - if (missing_features == 0 and untoggleable_extra_features == 0) + if (missing_features == 0 and fixed_unwanted_features == 0) { - const auto to_be_toggled = required_features & feature_toggles; - requirements.feature_toggles.from_generic(requirements.geometry, to_be_toggled); + // 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); return lower_it->second; } @@ -325,11 +326,11 @@ void zgl::shader_program_compiler::compile_shaders( shader_strings.clear(); switch (requirements.geometry) { - case shader_program::geometries::mesh: - add_required_feature_defines(requirements.feature_toggles.mesh, mesh_feature_defines, shader_strings); + 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::geometries::point_cloud: - add_required_feature_defines(requirements.feature_toggles.point_cloud, point_cloud_feature_defines, shader_strings); + 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(); @@ -339,7 +340,7 @@ void zgl::shader_program_compiler::compile_shaders( shader_id = glCreateShader(static_cast(requirements.stage)); - glShaderSource(shader_id, shader_strings.size(), shader_strings.data(), nullptr); + glShaderSource(shader_id, static_cast(shader_strings.size()), shader_strings.data(), nullptr); glCompileShader(shader_id); GLint success; @@ -399,7 +400,7 @@ void zgl::shader_program_compiler::register_shader_sources( const auto it = std::ranges::upper_bound( shader_lookup, *metadata, - shader_program::metadata_type::feature_count_less{}, + std::less{}, &std::pair::first ); diff --git a/source/rendering/batch_renderers/mesh_batch_renderer.cpp b/source/rendering/batch_renderers/mesh_batch_renderer.cpp index aabedd1..4ab5542 100644 --- a/source/rendering/batch_renderers/mesh_batch_renderer.cpp +++ b/source/rendering/batch_renderers/mesh_batch_renderer.cpp @@ -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::capabilities::mesh::lit.uniforms)) }); + ztu::logger::debug("lit reqs: %", std::bitset<32>{ static_cast(static_cast(shader_program::features::mesh::lit.uniforms)) }); for (std::size_t i{}; i != requirements::mesh::all.size(); ++i) diff --git a/source/rendering/shader_program_lookups/mesh_lookup.cpp b/source/rendering/shader_program_lookups/mesh_lookup.cpp index 5566db7..2b64a6a 100644 --- a/source/rendering/shader_program_lookups/mesh_lookup.cpp +++ b/source/rendering/shader_program_lookups/mesh_lookup.cpp @@ -19,7 +19,7 @@ void mesh_lookup::add( std::optional mesh_lookup::find( requirements::mesh::flags requirements ) const { - auto capability = shader_program::capabilities::mesh::type{}; + auto capability = shader_program::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::capabilities::mesh::all[shader_requirements_index]; + const auto& [ attributes, uniforms ] = shader_program::features::mesh::all[shader_requirements_index]; capability.attributes |= attributes; capability.uniforms |= uniforms; } diff --git a/source/rendering/shader_program_lookups/point_cloud_lookup.cpp b/source/rendering/shader_program_lookups/point_cloud_lookup.cpp index d5ebff4..27e5050 100644 --- a/source/rendering/shader_program_lookups/point_cloud_lookup.cpp +++ b/source/rendering/shader_program_lookups/point_cloud_lookup.cpp @@ -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::capabilities::point_cloud::type{}; + auto capability = shader_program::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::capabilities::point_cloud::all[shader_requirements_index]; + const auto& [ attributes, uniforms ] = shader_program::features::point_cloud::all[shader_requirements_index]; capability.attributes |= attributes; capability.uniforms |= uniforms; }