#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: // compile shader programs for given requirements // cache shader programs with their capabilities // store sstream for creating defines // register shader source code // store define types for these shaders as bitmap void register_shader_sources( const dynamic_shader_source_store& shader_sources ); void compile_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_feature_toggles_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, feature_toggles = 3, 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 }, { "FEATURE_TOGGLES", metadata_declaration_type::feature_toggles } }; inline static auto stage_lookup = ztu::string_lookup{ { "VERTEX", shader_program::stages::vertex }, { "GEOMETRY", shader_program::stages::geometry }, { "FRAGMENT", shader_program::stages::fragment }, }; inline static auto geometry_lookup = ztu::string_lookup{ { "MESH", shader_program::geometries::mesh }, { "POINT_CLOUD", shader_program::geometries::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; }; }