Started refactor to lazily compilable shaders.
This commit is contained in:
204
include/opengl/data_uploaders/shader_compiler.hpp
Normal file
204
include/opengl/data_uploaders/shader_compiler.hpp
Normal file
@@ -0,0 +1,204 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <bit>
|
||||
#include <format>
|
||||
#include <ranges>
|
||||
#include <bits/ranges_algo.h>
|
||||
|
||||
#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<const shader_program::metadata_type> required_capabilities,
|
||||
std::vector<shader_handle>& shader_handles
|
||||
);
|
||||
|
||||
|
||||
protected:
|
||||
void tokenize_declarations(
|
||||
std::string_view source,
|
||||
std::vector<std::string_view> tokens,
|
||||
std::vector<std::size_t> declaration_token_counts,
|
||||
std::span<std::size_t> declaration_type_indices
|
||||
);
|
||||
|
||||
std::optional<shader_program::metadata_type> parse_metadata_from_tokens(
|
||||
std::span<const std::string_view> tokens,
|
||||
std::span<const std::size_t> declaration_token_counts,
|
||||
std::span<const std::size_t> declaration_type_indices
|
||||
);
|
||||
|
||||
[[nodiscard]] static bool parse_stage_declaration(
|
||||
std::span<const std::string_view> tokens,
|
||||
shader_program::metadata_type& metadata
|
||||
);
|
||||
|
||||
[[nodiscard]] static bool parse_geometry_declaration(
|
||||
std::span<const std::string_view> tokens,
|
||||
shader_program::metadata_type& metadata
|
||||
);
|
||||
|
||||
[[nodiscard]] static bool parse_features_declaration(
|
||||
std::span<const std::string_view> tokens,
|
||||
shader_program::metadata_type& metadata
|
||||
);
|
||||
|
||||
[[nodiscard]] static bool parse_feature_toggles_declaration(
|
||||
std::span<const std::string_view> tokens,
|
||||
shader_program::metadata_type& metadata
|
||||
);
|
||||
|
||||
template<typename T>
|
||||
static void parse_feature_tokens(
|
||||
std::span<const std::string_view> tokens,
|
||||
const ztu::string_lookup<T>& feature_lookup,
|
||||
T& features
|
||||
);
|
||||
|
||||
std::optional<dynamic_shader_source_store::id_type> zgl::shader_program_compiler::find_compatible_shader_source(
|
||||
shader_program::metadata_type& requirements
|
||||
);
|
||||
|
||||
template<typename T>
|
||||
void add_required_feature_defines(
|
||||
T toggle_flags,
|
||||
std::span<const std::string> defines,
|
||||
std::vector<const char*>& shader_strings
|
||||
);
|
||||
|
||||
private:
|
||||
enum class metadata_declaration_type : std::size_t
|
||||
{
|
||||
stage = 0,
|
||||
geometry = 1,
|
||||
features = 2,
|
||||
feature_toggles = 3,
|
||||
invalid = std::numeric_limits<std::size_t>::max()
|
||||
};
|
||||
|
||||
inline static auto declaration_lookup = ztu::string_lookup<metadata_declaration_type>{
|
||||
{ "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<shader_program::stages>{
|
||||
{ "VERTEX", shader_program::stages::vertex },
|
||||
{ "GEOMETRY", shader_program::stages::geometry },
|
||||
{ "FRAGMENT", shader_program::stages::fragment },
|
||||
};
|
||||
|
||||
inline static auto geometry_lookup = ztu::string_lookup<shader_program::geometries>{
|
||||
{ "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<flags>{};
|
||||
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<flags>{};
|
||||
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::string, all.size()>{};
|
||||
|
||||
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::string, all.size()>{};
|
||||
|
||||
std::ranges::transform(
|
||||
defines,
|
||||
statements.begin(),
|
||||
[](const auto& name) {
|
||||
return std::format("#define {}\n", name);
|
||||
}
|
||||
);
|
||||
|
||||
return statements;
|
||||
}();
|
||||
|
||||
|
||||
std::vector<std::pair<shader_program::metadata_type, dynamic_shader_source_store::id_type>> shader_lookup;
|
||||
};
|
||||
}
|
||||
42
include/opengl/data_uploaders/shader_program_compiler.hpp
Normal file
42
include/opengl/data_uploaders/shader_program_compiler.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include "assets/dynamic_data_stores/dynamic_shader_source_store.hpp"
|
||||
#include "opengl/shader_program_lookup.hpp"
|
||||
#include "opengl/handles/shader_program_handle.hpp"
|
||||
|
||||
template<typename Capabilities>
|
||||
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 find_or_compile_shader_programs(
|
||||
std::span<const Capabilities> required_capabilities,
|
||||
zgl::shader_program_lookup& shader_program_lookup
|
||||
);
|
||||
|
||||
|
||||
// create metadata for all sources
|
||||
|
||||
// get
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
|
||||
private:
|
||||
std::unordered_map<dynamic_shader_source_store::id_type, Capabilities> shader_capabilities;
|
||||
|
||||
};
|
||||
@@ -16,52 +16,42 @@ class texture_data_uploader
|
||||
) {
|
||||
|
||||
std::vector<GLuint> texture_ids;
|
||||
std::vector<GLuint> invalid_texture_ids;
|
||||
|
||||
texture_ids.resize(dynamic_data.size());
|
||||
|
||||
glGenTextures(texture_ids.size(), texture_ids.data());
|
||||
|
||||
auto texture_id_it = texture_ids.begin();
|
||||
|
||||
for (std::size_t i{}; i != dynamic_data.size(); ++i)
|
||||
{
|
||||
const auto& texture_id = *texture_id_it;
|
||||
const auto& texture = dynamic_data[i];
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
GLenum format;
|
||||
switch (texture.components()) {
|
||||
using enum components::texture::flags;
|
||||
case luminance:
|
||||
format = GL_LUMINANCE;
|
||||
break;
|
||||
case luminance | alpha:
|
||||
format = GL_LUMINANCE_ALPHA;
|
||||
break;
|
||||
case red | green | blue:
|
||||
format = GL_RGB;
|
||||
break;
|
||||
case red | green | blue | alpha:
|
||||
format = GL_RGBA;
|
||||
break;
|
||||
default:
|
||||
format = GL_INVALID_ENUM;
|
||||
break;
|
||||
}
|
||||
|
||||
if (format == GL_INVALID_ENUM)
|
||||
{
|
||||
invalid_texture_ids.push_back(texture_id);
|
||||
}
|
||||
else
|
||||
const auto invalid_texture_ids = std::ranges::partition(
|
||||
texture_ids,
|
||||
[](GLuint texture_id)
|
||||
{
|
||||
GLenum format;
|
||||
switch (texture.components()) {
|
||||
using enum components::texture::flags;
|
||||
case luminance:
|
||||
format = GL_LUMINANCE;
|
||||
break;
|
||||
case luminance | alpha:
|
||||
format = GL_LUMINANCE_ALPHA;
|
||||
break;
|
||||
case red | green | blue:
|
||||
format = GL_RGB;
|
||||
break;
|
||||
case red | green | blue | alpha:
|
||||
format = GL_RGBA;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D, 0,
|
||||
GL_RGBA8,
|
||||
@@ -73,12 +63,16 @@ class texture_data_uploader
|
||||
texture.data()
|
||||
);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glDeleteTextures(invalid_texture_ids.size(), invalid_texture_ids.data());
|
||||
|
||||
invalid_texture_ids.resize(texture_ids.size() - invalid_texture_ids.size());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user