Skip to content

My attempt to write a decent enough C++-based GLSL preprocessor (Especially to resolve includes).

License

Notifications You must be signed in to change notification settings

johannes-braun/GLshader

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

67 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GLShader Processor

This is my attempt to create a preprocessor for GLSL code in C++, as well as a platform-dependant GLSL compiler with glGetProgramBinary based on GL_ARB_separate_shader_objects.

How to use?

Build libraries

You can use cmake to build the binaries to later link against. Please use a recent compiler which supports c++17 and experimental::filesystem.

Load file

Include <glsp/glsp.hpp> and that's it. To load and process a file, you'd call glsp::processed_file proc = glsp::preprocess_file("path/to/file.glsl", {}, {});.

Include Paths

The second parameter of the preprocess_file function determines the include search paths for when processing a file. Example: auto file = glsp::preprocess_file("path/to/file.glsl", {"my/shaders/"}, {});.

Predefined definitions

In the third function parameter, you can add predefined definitions.

Examples:

// Simple valueless definition
glsp::definition def_no_val("NO_VAL");

// Parameterless macro
glsp::definition def_my_val("MY_VAL", 2);

// Parameterized macro with parameters a, b and c.
glsp::definition def_add_mul("AddMul", { {"a", "b", "c"}, "(a + b * c)" });

// Two kinds of formatted definitions.
auto fmt_def1 = glsp::definition::from_format("MY_MACRO(a, b, fun) (fun(a, b)-1)");
auto fmt_def2 = "OTHER_MACRO(x) (x * 2.f - 1.f)"_gdef;

// Pass definitions to preprocessor.
auto file = glsp::preprocess_file("file", {}, { def_my_val, def_no_val, def_add_mul, fmt_def1, fmt_def2 });

A formatted definition must have one of the following formats:

  • Valueless definition: MACRO
  • Parameterless macro with value: MACRO val
  • Parameterized with n parameters and empty or non-empty replacement: MACRO(p0, p1, ..., pn) rep

State

You can use glsp::state as follows to allow for persistent predefined definitions and include directories.

// Once
glsp::state preproc_state;
preproc_state.add_definition("my_def(a, b, c) (-a + b * c)"_gdef);
preproc_state.add_definition({ "MY_VAL", 2 });
preproc_state.add_definition({ "NO_VAL" });
preproc_state.add_definition({ "AddMul",{ { "a", "b", "c" }, "a + b * c" } });
preproc_state.add_include_dir("../shaders/");
// ...
// Somewhere else
auto file = preproc_state.preprocess_file("my_file.glsl");

Binary Compiler

The glsp::compiler class derives from glsp::state and provides the functionality to compile and cache your GLSL text files to the system's proprietary binary format and load them from there. The resulting compiled program binary can only be used for separable programs with opengl pipeline objects. Shader files compiled with the glsp::compiler need to have proper extensions declaring their shader stage:

Extension Type
.vert GL_VERTEX_SHADER
.geom GL_GEOMETRY_SHADER
.tesc GL_TESS_CONTROL_SHADER
.tese GL_TESS_EVALUATION_SHADER
.frag GL_FRAGMENT_SHADER
.comp GL_COMPUTE_SHADER

Compiler usage example:

glsp::compiler compiler(".bin", "path/to/cache/");
compiler.set_default_prefix(opengl_prefix); // optional prefix string, e.g. containing the #version tag or default extensions.
compiler.set_default_postfix(opengl_postfix); // optional postfix, e.g. bindless uniform layout declarations.

// Definitions and includes like with glsp::state
compiler.add_definition(...);
compiler.add_include_dir("my/include/dir/")

glsp::shader_binary binary = compiler.compile("path/to/shader.vert", glsp::format::gl_binary, false, more_includes, more_defines);

// Data is empty if there was a syntax-, compiler- or linker-error
if(!binary.data.empty())
{
    my_program_id = glCreateProgram();
    glProgramParameteri(_id, GL_PROGRAM_SEPARABLE, GL_TRUE); // Only a single program 
    glProgramBinary(_id, GLenum(bin.format), bin.data.data(), int(bin.data.size()));
}
else
{
    // Error handling...
}

About

My attempt to write a decent enough C++-based GLSL preprocessor (Especially to resolve includes).

Resources

License

Stars

Watchers

Forks

Packages

No packages published