#pragma once #include #include #include #include #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 "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" namespace zgl { class shader_program_compiler { public: void register_shader_sources( 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 ); protected: void tokenize_declarations( std::string_view source, std::vector tokens, std::vector declaration_token_counts, std::span declaration_type_indices ); 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 ); 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() }; 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; }; }