ImFusion SDK 4.3
Program Class Reference

#include <ImFusion/Core/GL/Program.h>

OpenGL GLSL program with a fragment and optional vertex and geometry shader. More...

+ Inheritance diagram for Program:

Detailed Description

OpenGL GLSL program with a fragment and optional vertex and geometry shader.

The source code for the shaders is resolved by GL::Program in conjunction with the Resource System infrastructure. It will use Resource::query() to check whether any registered resource repository can provide the source code corresponding to the identifier (i.e. file name) passed during construction of the GL::Program. An optional path prefix will be interpreted as repository name to allow for more specific source code queries and resolve potential ambiguities, for instance the identifier MyPlugin/MyShader.frag will first search to find the resource MyShader.frag in a repository with the name MyPlugin. Only if this can not be resolved, it will continue searching for a resource with the name MyPlugin/MyShader.frag in any registered repository. If none of the resource repositories can resolve the given shader name, initialization of the GL::Program will fail.

When you're using OpenGL shaders in your own module, you should create a dedicated Resource::Repository in order to control the loading behavior for your shaders.

Similar to C++ headers, a GLSL program can include other GLSL headers. By convention, a GLSL header has the extension .glh and must not contain a main function. Otherwise, it can contain other function, struct, variable or uniform definitions like any normal shader. A GLSL header can be included in a shader using:

#pragma include "<headername>.glh"

The code from the include file will be inserted (as in copied) right after the #pragma.

To allow for using the same include in different shaders, the GL::Program shader preprocessor will define one of the following defines in the corresponding shader stages: IMFUSION_VERTEX_SHADER, IMFUSION_GEOMETRY_SHADER, IMFUSION_FRAGMENT_SHADER, IMFUSION_COMPUTE_SHADER, IMFUSION_TESSELATION_EVALUATION_SHADER, or IMFUSION_TESSELATION_CONTROL_SHADER.

In the case of an error, the resulting log will be reformatted and the line number is replaced with the line number and the filename where the line originates. Include file names are resolved the same way as normal shader file names (i.e. querying the Resource System infrastructure).

GL::Program will parse the version directive of each loaded shader/shader include. If there is no version directive present in a shader, it will assume GLSL 3.3. If a shader and its includes require different GLSL versions, GL::Program will use the maximum version.

Warning
If there are conflicting versions (i.e. one part < 3.3 and one part >= 3.3), GL::Program will enable the GLSL compatibility mode and convert certain legacy GLSL constructs (e.g. varying) to their modern GLSL counterpart. This compatibility mode may be dropped at future versions to only allow GLSL >= 3.3

Example:

// loads shader sources from a ImFusion::Resource repository called `MyModule`,
// resource names are `MyShader.vert` and `MyShader.frag`
{GL::Program::Stage::Vertex, "MyModule/MyShader.vert"},
{GL::Program::Stage::Fragment, "MyModule/MyShader.frag"},
});
prog.enable();
prog.setArgument("u_color", vec4f(1.f, .5f, 0.f, 1.f));
prog.setArgument("u_texture", texture, sampler);
// draw...
prog.unbindImages();
prog.disable();
OpenGL GLSL program with a fragment and optional vertex and geometry shader.
Definition Program.h:99
void enable()
Enable the shader program now.
See also

Classes

struct  AbstractIncludeStruct
 Struct for representing an abstract include object. More...
 
struct  BufferBinding
 Struct to keep track of GlBuffers bound shaders as SSBOs. More...
 
struct  ImageBinding
 
struct  ShaderInfo
 Encapsulates information about each shader stage. More...
 
struct  TextureBinding
 

Public Types

enum class  ImageAccess { ReadOnly = 0x88B8 , WriteOnly = 0x88B9 , ReadWrite = 0x88BA }
 Type of access that will be performed on a bound image. More...
 
enum class  Stage {
  Vertex = 0x8B31 , Geometry = 0x8DD9 , Fragment = 0x8B30 , Compute = 0x91B9 ,
  TesselationEvaluation = 0x8E87 , TesselationControl = 0x8E88
}
 Enumeration of supported shader stages. More...
 
enum class  Cloning { Everything = 0 , NoDecorators = 1 << 0 , NoAbstractIncludes = 1 << 1 }
 Bitflag enumeration to configure Program::clone() More...
 
enum class  Compilation { Defer , Immediate , ImmediateThrowOnFailure }
 Describes how to deal with necessary (re-) compilation of the shader. More...
 

Public Member Functions

 Program (std::vector< std::pair< Stage, const char * > > shaders, const std::string &defines="", Compilation compileBehavior=Compilation::ImmediateThrowOnFailure)
 Instantiates a new OpenGL program consisting of one or multiple GLSL shaders.
 
virtual ~Program ()
 Destructor, deletes all allocated resources.
 
std::unique_ptr< Programclone (Flags< Cloning > cloneOptions, Compilation compileBehavior) const
 Performs a deep copy of the shader with its sources, defines, and optionally also decorators and abstract includes.
 
virtual bool setDefines (const std::string &defines, Compilation compileBehavior=Compilation::Immediate)
 Sets the optional string of definitions that is pasted at the beginning of all shaders.
 
const std::stringdefines () const
 Returns the optional string of definitions that is pasted at the beginning of all shaders.
 
bool setExpandDefines (bool expandDefines, Compilation compileBehavior=Compilation::Immediate)
 Sets the flag to optionally also expand (abstract) includes recursively found in defines.
 
bool expandsDefines () const
 Returns the flag whether to also expand (abstract) includes recursively found in defines.
 
bool addRequiredExtension (const std::string &extensionName, Compilation compileBehavior=Compilation::Immediate)
 Registers a GLSL extension as required so that the preprocessor adds the corresponding #extension directives.
 
const std::vector< std::string > & requiredExtensions () const
 Returns all GLSL extensions that were registered as required through addRequiredExtension().
 
template<typename T>
void setArgument (const char *name, const T &val)
 Sets a shader argument (i.e., uniform), including images, matrices, vectors.
 
template<typename T>
void setArgument (const std::string &name, const T &val)
 Sets a shader argument (i.e., uniform), including images, matrices, vectors.
 
void setArgument (const char *name, const Texture &val, const Sampler &sampling)
 Sets a shader sampler with additional sampling parameters (temporarily overrides the parameters of the texture).
 
void setArgument (const char *name, const std::vector< const Texture * > &val, const Sampler &sampling)
 Sets multiple shader samplers with additional sampling parameters (temporarily overrides the parameters of the texture).
 
bool bindBuffer (const char *name, ShaderStorageBuffer &buffer)
 Binds the given SSBO to the interface block of the given name in the shader.
 
void unbindBuffers ()
 Unbinds all buffers from this shader.
 
bool bindImage (const char *name, Texture &image, ImageAccess access)
 Binds the given texture as GLSL image variable to the given uniform name.
 
void addDecorator (ProgramDecorator *dec)
 Add a decorator to apply upon enabling.
 
void removeDecorator (ProgramDecorator *dec)
 Remove a decorator.
 
bool addAbstractIncludeDefinition (const AbstractInclude *include, Compilation compileBehavior=Compilation::Immediate)
 Adds an abstract include to the shader source.
 
bool removeAbstractIncludeDefinition (AbstractInclude *include, Compilation compileBehavior=Compilation::Immediate)
 Removes an abstract include definition.
 
bool removeAbstractIncludeDefinition (const std::string &defineName, Compilation compileBehavior=Compilation::Immediate)
 Removes an abstract include definition.
 
void enable ()
 Enable the shader program now.
 
void disable ()
 Disable the shader program and set no active shader.
 
void dispatchCompute (const vec3i &numWorkGroups)
 Launch a compute shader with the given number of work groups.
 
void dispatchCompute (int numWorkGroupsX, int numWorkGroupsY=1, int numWorkGroupsZ=1)
 Launch a compute shader with the given number of work groups.
 
void unbindImages (bool manipGlState=true)
 Unbind texture arguments that had been set before.
 
int numImages () const
 Returns an upper bound of the number of images that have been set as arguments.
 
int loc (const char *name)
 Returns GLSL uniform location.
 
uint32_t id () const
 Returns the internal OpenGL id for this program.
 
bool overrideShaderSource (Stage shaderStage, const std::string &shaderSource, Compilation compileBehavior)
 Set custom shader source to override source code from Resource infrastructure for the given shader stage.
 
bool compile (Compilation compileBehavior=Compilation::Immediate)
 Immediately compiles the GLSL shaders and links them to the final program.
 
bool isCompiled () const
 Returns whether the shader has been successfully compiled and is up-to-date or whether there are pending changes.
 

Static Public Member Functions

static std::unique_ptr< ProgramcreateVertexFragment (const std::string &vertexShaderName, const std::string &framentShaderName, const std::string &defines="", Compilation compileBehavior=Compilation::Immediate)
 Convenience function to instantiate a new OpenGL program consisting of a vertex and a fragment shader.
 
static std::unique_ptr< ProgramcreateVertexGeometryFragment (const std::string &vertexShaderName, const std::string &geometryShaderName, const std::string &framentShaderName, const std::string &defines="", Compilation compileBehavior=Compilation::Immediate)
 Convenience function to instantiate a new OpenGL program consisting of a vertex, geometry, and a fragment shader.
 
static std::unique_ptr< ProgramcreateCompute (const std::string &computeShaderName, const std::string &defines="", Compilation compileBehavior=Compilation::Immediate)
 Convenience function to instantiate a new OpenGL program consisting of a compute shader.
 
static std::string determineVersion (int minVersion, int maxVersion, const std::string &filename)
 Returns a GLSL version string that accommodates the given version range.
 

Protected Member Functions

virtual ProgramcloneImpl () const
 Virtual helper function to actually clone this type, may throw on error.
 
int checkForUnititializedUniforms () const
 Only in _DEBUG builds: Checks for active uniforms (GL_ACTIVE_UNIFORMS) that were not initializes using GL::Program::setArgument().
 
bool initProgram (Compilation compileBehavior)
 Initializes or Reinitializes the program.
 
void initShader (const ShaderInfo &si)
 Initialize a single shader.
 
int bindSampler (const char *uniformName, const Texture &texture, const Sampler *sampler, bool setUniformAndRecycleUnit)
 
void unbindSamplers (const char *uniformName)
 
std::string joinShaderNames () const
 

Static Protected Member Functions

static std::string loadShaderSource (const ShaderInfo &si, bool expandDefines, const std::map< std::string, AbstractIncludeStruct > &abstractIncludes, const std::string &additionalDefines, const std::vector< std::string > &requiredExtensions={})
 
static std::string expandInclude (const std::string &line, std::string &defines, int &minVersion, int &maxVersion, std::vector< std::string > &includeFilenames, const std::string &shaderName, const std::map< std::string, AbstractIncludeStruct > &abstractIncludes, const std::string &additionalDefines, const std::string &dependentIncludesPrefix="")
 Searches for #pragma include defines and returns the source of the include file expandInclude is called recursively by the include to expand includes inside the include.
 
static void convertLegacyCodeToModernGlsl (std::string &lines, Stage shaderType)
 Converts selected legacy GLSL constructs to their modern GLSL > 3.3 counterpart using simple text replacement.
 
static void gatherAbstractIncludesRecursively (const AbstractInclude *include, const std::map< std::string, AbstractIncludeStruct > &abstractIncludes, std::vector< AbstractIncludeStruct > &outIncludes, const std::string &dependentIncludesPrefix="")
 

Protected Attributes

uint32_t m_progID = 0
 OpenGL program ID.
 
std::vector< ShaderInfom_shaders
 List of all shader stages part of the program.
 
std::string m_defines
 Optional string of definitions pasted to the beginning of each shader.
 
std::vector< TextureBindingm_textures
 All textures bound to the shader, index defines binding location.
 
std::vector< BufferBindingm_buffers
 All buffers bound to the shader, index defines binding location.
 
std::vector< ImageBindingm_images
 All images bound to the shader as images, index defines image unit.
 
std::vector< ProgramDecorator * > m_dec
 The optional decorator instances.
 
bool m_expandDefines = false
 Flag whether to optionally also expand includes found in defines.
 
std::unordered_set< std::stringm_assignedUniforms
 Names of all uniforms that were set using setArgument()
 
std::map< std::string, AbstractIncludeStructm_abstractIncludes
 Abstract include by define name.
 
std::vector< std::stringm_requiredExtensions
 GLSL extensions that must be enabled.
 

Member Enumeration Documentation

◆ ImageAccess

enum class ImageAccess
strong

Type of access that will be performed on a bound image.

See also
https://www.khronos.org/opengl/wiki/Image_Load_Store

◆ Stage

enum class Stage
strong

Enumeration of supported shader stages.

See also
https://www.khronos.org/opengl/wiki/Shader#Stages

◆ Cloning

enum class Cloning
strong

Bitflag enumeration to configure Program::clone()

Enumerator
Everything 

Clone everything.

NoDecorators 

Do not copy GL::ProgramDecorator instances.

NoAbstractIncludes 

Do not copy AbstractInclude instances.

◆ Compilation

enum class Compilation
strong

Describes how to deal with necessary (re-) compilation of the shader.

Enumerator
Defer 

Defer shader compilation until it is explicitly requested in the future.

Immediate 

Immediately attempt compilation, indicate failure through the return value.

ImmediateThrowOnFailure 

Immediately attempt compilation, indicate failure through throwing an exception.

Constructor & Destructor Documentation

◆ Program()

Program ( std::vector< std::pair< Stage, const char * > > shaders,
const std::string & defines = "",
Compilation compileBehavior = Compilation::ImmediateThrowOnFailure )

Instantiates a new OpenGL program consisting of one or multiple GLSL shaders.

Parameters
shadersList of pairs {shader stage, source code resource name} of all shaders that shall form the OpenGL program. The shaders' source code is resolved using the ImFusion::Resource infrastructure as described above.
definesList of optional definitions that are to be pasted at the beginning of the source code of each participating shader.
compileBehaviorFlag whether the copied shader should be compiled immediately and how to handle compilation failure.
Exceptions
std::runtime_errorWill always throw if the underlying OpenGL objects could not be created. Depending on compileBehavior this function may also throw if compilation of the shader fails (e.g. shader source could not be resolved, shader source contains invalid GLSL, ...).
See also
createVertexFragment(), createVertexGeometryFragment(), createCompute()

Member Function Documentation

◆ createVertexFragment()

static std::unique_ptr< Program > createVertexFragment ( const std::string & vertexShaderName,
const std::string & framentShaderName,
const std::string & defines = "",
Compilation compileBehavior = Compilation::Immediate )
static

Convenience function to instantiate a new OpenGL program consisting of a vertex and a fragment shader.

Depending on compileBehavior failure will be indicated either by returning a nullptr or by throwing. Failure can happen if the underlying OpenGL objects could not be created or if immediate compilation of the shader fails (e.g. shader source could not be resolved, shader source contains invalid GLSL, ...).

Exceptions
std::runtime_erroron failure if compileBehavior is ImmediateThrowOnFailure.

◆ createVertexGeometryFragment()

static std::unique_ptr< Program > createVertexGeometryFragment ( const std::string & vertexShaderName,
const std::string & geometryShaderName,
const std::string & framentShaderName,
const std::string & defines = "",
Compilation compileBehavior = Compilation::Immediate )
static

Convenience function to instantiate a new OpenGL program consisting of a vertex, geometry, and a fragment shader.

Depending on compileBehavior failure will be indicated either by returning a nullptr or by throwing. Failure can happen if the underlying OpenGL objects could not be created or if immediate compilation of the shader fails (e.g. shader source could not be resolved, shader source contains invalid GLSL, ...).

Exceptions
std::runtime_erroron failure if compileBehavior is ImmediateThrowOnFailure.

◆ createCompute()

static std::unique_ptr< Program > createCompute ( const std::string & computeShaderName,
const std::string & defines = "",
Compilation compileBehavior = Compilation::Immediate )
static

Convenience function to instantiate a new OpenGL program consisting of a compute shader.

Depending on compileBehavior failure will be indicated either by returning a nullptr or by throwing. Failure can happen if the underlying OpenGL objects could not be created or if immediate compilation of the shader fails (e.g. shader source could not be resolved, shader source contains invalid GLSL, ...).

Exceptions
std::runtime_erroron failure if compileBehavior is ImmediateThrowOnFailure.

◆ clone()

std::unique_ptr< Program > clone ( Flags< Cloning > cloneOptions,
Compilation compileBehavior ) const

Performs a deep copy of the shader with its sources, defines, and optionally also decorators and abstract includes.

GL::ProgramDecorator instances are not deep-copied, thus you must make sure that they remain valid throughout the lifetime of all clones. In contrast, GL::AbstractInclude instances are deep-copied.

Parameters
cloneOptionsBitflag mask describing what aspects of the program are to be cloned.
compileBehaviorFlag whether the copied shader should be compiled immediately and how to handle compilation failure.
Note
This function does not copy any OpenGL state such as assigned uniform arguments/images/etc.

◆ setDefines()

virtual bool setDefines ( const std::string & defines,
Compilation compileBehavior = Compilation::Immediate )
virtual

Sets the optional string of definitions that is pasted at the beginning of all shaders.

Changing the defines will require recompilation of the shader and invalidate all configured uniforms, buffers, and images.

Reimplemented in ImageProgram.

◆ setExpandDefines()

bool setExpandDefines ( bool expandDefines,
Compilation compileBehavior = Compilation::Immediate )

Sets the flag to optionally also expand (abstract) includes recursively found in defines.

Changing this flag will require recompilation of the shader and invalidate all configured uniforms, buffers, and images.

◆ addRequiredExtension()

bool addRequiredExtension ( const std::string & extensionName,
Compilation compileBehavior = Compilation::Immediate )

Registers a GLSL extension as required so that the preprocessor adds the corresponding #extension directives.

For every registered extensionName the preprocessor will put #extension <extensionName> : require to the top of the source code.

◆ setArgument() [1/2]

template<typename T>
void setArgument ( const char * name,
const T & val )

Sets a shader argument (i.e., uniform), including images, matrices, vectors.

This template member function is implemented for the following types T:

Furthermore, we implement the following convenience overloads for double-precision floating point values. Be advised that they are not supported by GLSL and a narrowing conversion to single-precision will take place:

  • double, vec2, vec3, vec4, mat2, mat3, mat4

◆ setArgument() [2/2]

template<typename T>
void setArgument ( const std::string & name,
const T & val )
inline

Sets a shader argument (i.e., uniform), including images, matrices, vectors.

This template member function is implemented for the following types T:

Furthermore, we implement the following convenience overloads for double-precision floating point values. Be advised that they are not supported by GLSL and a narrowing conversion to single-precision will take place:

  • double, vec2, vec3, vec4, mat2, mat3, mat4

◆ bindBuffer()

bool bindBuffer ( const char * name,
ShaderStorageBuffer & buffer )

Binds the given SSBO to the interface block of the given name in the shader.

The return value indicates whether the binding was successful

◆ bindImage()

bool bindImage ( const char * name,
Texture & image,
ImageAccess access )

Binds the given texture as GLSL image variable to the given uniform name.

Note
This function is only for GLSL image load/store and requires at least OpenGL 4.2. If you want to bind a texture to a sampler use setArgument() instead.
See also
https://www.khronos.org/opengl/wiki/Image_Load_Store
Note
This function is only for GLSL image load/store. If you want to bind a texture to a sampler use setArgument() instead.

◆ addAbstractIncludeDefinition()

bool addAbstractIncludeDefinition ( const AbstractInclude * include,
Compilation compileBehavior = Compilation::Immediate )

Adds an abstract include to the shader source.

This method only extracts the define name and include path from the AbstractInclude, the pointer itself is not stored and only used in this method. Only one AbstractInclude can be set per define name. If an AbstractInclude with the same defineName is already set, it will be overridden in the case of non-matching fingerprints. Changing the defines will require recompilation of the shader and invalidate all configured uniforms, buffers, and images.

◆ removeAbstractIncludeDefinition() [1/2]

bool removeAbstractIncludeDefinition ( AbstractInclude * include,
Compilation compileBehavior = Compilation::Immediate )

Removes an abstract include definition.

Changing the defines will require recompilation of the shader and invalidate all configured uniforms, buffers, and images.

◆ removeAbstractIncludeDefinition() [2/2]

bool removeAbstractIncludeDefinition ( const std::string & defineName,
Compilation compileBehavior = Compilation::Immediate )

Removes an abstract include definition.

Changing the defines will require recompilation of the shader and invalidate all configured uniforms, buffers, and images.

◆ dispatchCompute() [1/2]

void dispatchCompute ( const vec3i & numWorkGroups)

Launch a compute shader with the given number of work groups.

This function must only be called if this shader is a compute shader.

See also
https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDispatchCompute.xhtml

◆ dispatchCompute() [2/2]

void dispatchCompute ( int numWorkGroupsX,
int numWorkGroupsY = 1,
int numWorkGroupsZ = 1 )

Launch a compute shader with the given number of work groups.

This function must only be called if this shader is a compute shader.

See also
https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glDispatchCompute.xhtml

◆ unbindImages()

void unbindImages ( bool manipGlState = true)

Unbind texture arguments that had been set before.

Parameters
manipGlStateFlag whether to also manipulate OpenGL state. If false, will only update internal bookkeeping.

◆ numImages()

int numImages ( ) const

Returns an upper bound of the number of images that have been set as arguments.

Note
Due to some internal bookkeeping caveats the actual number of active images may be less.

◆ overrideShaderSource()

bool overrideShaderSource ( Stage shaderStage,
const std::string & shaderSource,
Compilation compileBehavior )

Set custom shader source to override source code from Resource infrastructure for the given shader stage.

Warning
Providing bad source code may crash the application or lead to undefined behavior. Use at your own risk.

◆ compile()

bool compile ( Compilation compileBehavior = Compilation::Immediate)

Immediately compiles the GLSL shaders and links them to the final program.

You do not need to call this function explicitly unless you used Compilation::Defer previously.

Parameters
compileBehaviorDefines how to indicate errors, must not be Defer.
Returns
false if compileBehavior is Compilation::Immediate and compilation failed. true in all other cases.

◆ determineVersion()

static std::string determineVersion ( int minVersion,
int maxVersion,
const std::string & filename )
static

Returns a GLSL version string that accommodates the given version range.

E.g. determineVersion(330, 450, "") would return "#version 450". The given filename is only used for logging purposes. This usually returns a version string containing maxVersion, except when IMFUSION_GLES is defined which always returns "#version 300 es". Returns an empty string if maxVersion is 0.

◆ cloneImpl()

virtual Program * cloneImpl ( ) const
protectedvirtual

Virtual helper function to actually clone this type, may throw on error.

Reimplemented in ImageProgram.

◆ checkForUnititializedUniforms()

int checkForUnititializedUniforms ( ) const
protected

Only in _DEBUG builds: Checks for active uniforms (GL_ACTIVE_UNIFORMS) that were not initializes using GL::Program::setArgument().

Logs a warning for each uninitialized uniform and returns the count of those.

Note
Does nothing in Release builds.

◆ expandInclude()

static std::string expandInclude ( const std::string & line,
std::string & defines,
int & minVersion,
int & maxVersion,
std::vector< std::string > & includeFilenames,
const std::string & shaderName,
const std::map< std::string, AbstractIncludeStruct > & abstractIncludes,
const std::string & additionalDefines,
const std::string & dependentIncludesPrefix = "" )
staticprotected

Searches for #pragma include defines and returns the source of the include file expandInclude is called recursively by the include to expand includes inside the include.

Parameters
linethe line to search for the pragma
[in,out]definesthe current active defines, if the include is an abstract include its define will be appended
[in,out]minVersionthe current minimum GLSL version in the program, will be updated if the include has a lower version
[in,out]maxVersionthe current maximum GLSL version in the program, will be updated if the include has a higher version
[in,out]includeFilenameslist of all current includes, if an include is found it will be appended
shaderNamem_shaderNames[num] for logging only
abstractIncludesthis is generally taken to be m_abstractIncludes
additionalDefinesthis is generally taken to be m_defines
Returns
Include source code or empty if line does not contain an include

The documentation for this class was generated from the following file:
Search Tab / S to search, Esc to close