mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-26 11:23:08 +01:00
174 lines
7.2 KiB
C++
174 lines
7.2 KiB
C++
/*
|
|
This Source Code Form is subject to the
|
|
terms of the Mozilla Public License, v.
|
|
2.0. If a copy of the MPL was not
|
|
distributed with this file, You can
|
|
obtain one at
|
|
http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
// the shader files of the renderers, whichever api compiles them: where they are, how a file is made ready to compile (its
|
|
// includes, the directives of the materials, what the renderer puts before the source), and the SPIR-V binaries compiled from
|
|
// them ahead of time, which the renderers load before they compile the source.
|
|
//
|
|
// each api has a directory of sources and one of binaries: shaders/ogl46/ and shaders/ogl46bin/ for opengl 4.6,
|
|
// shaders/vk14/ and shaders/vk14bin/ for vulkan 1.4. a binary is named after its source, <file>.spv, and a variant of the
|
|
// shader (the defines of the renderer, e.g. MODEL_DRAWS) <file>.<DEFINE>.spv. the sources can be compiled by glslc as they are
|
|
// (shaders/compile_spirv.py), which also writes the manifest of the binaries: the sources each binary was compiled from, so a
|
|
// binary older than its sources isn't taken.
|
|
//
|
|
// no graphics api here: the file is also built into the shader validator (ci_shadervalidator)
|
|
|
|
#pragma once
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <unordered_map>
|
|
#include <vector>
|
|
|
|
namespace gfx
|
|
{
|
|
|
|
class shader_exception : public std::runtime_error
|
|
{
|
|
using runtime_error::runtime_error;
|
|
};
|
|
|
|
enum class shader_api
|
|
{
|
|
opengl46,
|
|
vulkan14
|
|
};
|
|
|
|
enum class shader_stage
|
|
{
|
|
vertex,
|
|
fragment,
|
|
geometry,
|
|
compute
|
|
};
|
|
|
|
// textures and parameters a material shader can take, the same as gl::MAX_TEXTURES and gl::MAX_PARAMS
|
|
constexpr std::size_t MAX_SHADER_TEXTURES = 8;
|
|
constexpr std::size_t MAX_SHADER_PARAMS = 3;
|
|
|
|
// what the texture of a unit holds, as #pragma texture(name, unit, components) gives it. the values are those of opengl
|
|
// (GL_RED ... GL_SRGB_ALPHA), which the textures take as the hint of their format
|
|
enum class shader_components : int
|
|
{
|
|
R = 0x1903,
|
|
RG = 0x8227,
|
|
RGB = 0x1907,
|
|
RGBA = 0x1908,
|
|
sRGB = 0x8C40,
|
|
sRGB_A = 0x8C42
|
|
};
|
|
|
|
struct shader_texture_entry
|
|
{
|
|
std::size_t id;
|
|
shader_components components;
|
|
};
|
|
|
|
enum class shader_param_default
|
|
{
|
|
required,
|
|
nan,
|
|
zero,
|
|
one,
|
|
ambient,
|
|
diffuse,
|
|
specular,
|
|
glossiness
|
|
};
|
|
|
|
// #pragma param(name, location, offset, size, default): a part of one of the vec4 parameters of the model block
|
|
struct shader_param_entry
|
|
{
|
|
std::size_t location;
|
|
std::size_t offset;
|
|
std::size_t size;
|
|
shader_param_default defaultparam;
|
|
};
|
|
|
|
using shader_texture_conf = std::unordered_map<std::string, shader_texture_entry>;
|
|
using shader_param_conf = std::unordered_map<std::string, shader_param_entry>;
|
|
|
|
// a program of a material as the materials see it, whichever api draws it: the textures and the parameters it takes, the
|
|
// name it was fetched by (gfx_renderer::Fetch_Shader)
|
|
class shader_program
|
|
{
|
|
public:
|
|
virtual ~shader_program() = default;
|
|
|
|
shader_texture_conf texture_conf;
|
|
shader_param_conf param_conf;
|
|
std::string name;
|
|
};
|
|
|
|
// a shader file made ready to compile
|
|
struct shader_source
|
|
{
|
|
shader_api api{shader_api::opengl46};
|
|
shader_stage stage{shader_stage::vertex};
|
|
// the file as asked for, e.g. mat_default.frag
|
|
std::string name;
|
|
// the names of the defines of the variant joined with dots (MODEL_DRAWS), empty for the shader itself. a variant whose
|
|
// defines aren't all plain flags (#define NAME or #define NAME 1) has no binary: invalid_variant
|
|
std::string variant;
|
|
bool has_binary_name{true};
|
|
// whether the source file is there; a binary can be loaded without it, but the material directives come from the source
|
|
bool has_source{false};
|
|
// the source with the preamble put after #version and the includes expanded, for a compiler of the source. the files are
|
|
// told apart in the messages of the compiler by their numbers in files (#line <line> <number>)
|
|
std::string text;
|
|
// the file and its includes, relative to the directory of the sources, by their numbers
|
|
std::vector<std::string> files;
|
|
shader_texture_conf texture_conf;
|
|
shader_param_conf param_conf;
|
|
};
|
|
|
|
// "opengl 4.6", "vulkan 1.4"
|
|
char const *shader_api_name(shader_api Api);
|
|
// the directories of the sources and of the binaries of an api: shaders/ogl46/, shaders/ogl46bin/ ...
|
|
std::string shader_source_dir(shader_api Api);
|
|
std::string shader_binary_dir(shader_api Api);
|
|
// the stage of a file by its extension (.vert, .frag, .geom, .comp). throws shader_exception for another one
|
|
shader_stage shader_stage_of(std::string const &Name);
|
|
// the define the files set for their stage: STAGE_VERTEX ...
|
|
char const *shader_stage_define(shader_stage Stage);
|
|
// the file name of the binary of a shader: mat_default.frag.spv, vertex.vert.MODEL_DRAWS.spv
|
|
std::string shader_binary_name(std::string const &Name, std::string const &Variant);
|
|
// the variant named by the defines of a renderer ("#define MODEL_DRAWS 1\n" -> MODEL_DRAWS). Plain: false when a define isn't
|
|
// a plain flag (the variant can't have a binary then)
|
|
std::string shader_variant_of(std::string const &Defines, bool &Plain);
|
|
// the hash the manifest of the binaries keeps of a source file: fnv-1a 64 of the text with the line ends made \n
|
|
std::uint64_t shader_file_hash(std::string_view Text);
|
|
|
|
// reads the shader Name of Api and makes it ready to compile: the includes expanded (#include "file", #include <file>; <common>
|
|
// stands for common.glsl), #pragma texture(...) and #pragma param(...) read and taken out of the text, and after the #version
|
|
// line (#version 460 core put first when the file has none) the defines of the variant, the preamble of the renderer and,
|
|
// where the file doesn't set it, the define of its stage. Basedir: the directory of the sources, shader_source_dir() when empty.
|
|
// a missing file is an error unless Allowmissing (the source then comes back with has_source false). throws shader_exception
|
|
shader_source preprocess_shader(shader_api Api, std::string const &Name, std::string const &Defines, std::string const &Preamble, bool const Allowmissing = false,
|
|
std::string const &Basedir = {});
|
|
|
|
// the SPIR-V binary of a shader from the directory of the binaries of its api. empty when there's none, when the manifest of the
|
|
// binaries says the binary was compiled from other sources than those there now, or when the file isn't SPIR-V; Reason says
|
|
// which (empty when there's simply no binary)
|
|
std::vector<std::uint32_t> load_shader_binary(shader_source const &Source, std::string &Reason);
|
|
|
|
// the ids of the specialization constants of a SPIR-V module (OpDecorate ... SpecId)
|
|
std::vector<std::uint32_t> spirv_specialization_ids(std::vector<std::uint32_t> const &Words);
|
|
|
|
// the #define lines of a source, NAME -> value as written, for the checks of the constants the binaries were compiled with
|
|
std::unordered_map<std::string, std::string> shader_file_defines(shader_api Api, std::string const &Name, std::string const &Basedir = {});
|
|
// whether the constants a renderer puts before the sources (the #define lines of Preamble) are those the file Name of Api writes
|
|
// for itself (the binaries are compiled by glslc with the values of the file). Differences: what isn't the same
|
|
bool shader_constants_match(shader_api Api, std::string const &Name, std::string const &Preamble, std::string const &Basedir, std::vector<std::string> &Differences);
|
|
|
|
} // namespace gfx
|