![]() |
ImFusion SDK 4.3
|
#include <ImFusion/Core/GL/ImageProgram.h>
Convenience class to execute a GLSL fragment shader on an image or volume. More...
Convenience class to execute a GLSL fragment shader on an image or volume.
The fragment shader gets the voxel or pixel position of the fragment as input:
The output can be defined arbitrary, e.g.:
The layout location corresponds to the list of texture passed to ImageProgram::compute, e.g. the location 0 will write to the first texture, the location 1 to the second texture and so on. The out type does not need to exactly match the corresponding texture because OpenGL automatically converts the values (check the OpenGL Specification for details).
A FBO is automatically created but can be replaced by a custom one.
Optionally, a geometry shader can be used to improve performance when computing 3D volumes. The performance gain depends on the use-case and the driver. In general the geometry shader overhead is too large for 2D processing (but works nonetheless). In 3D, using the geometry shader seems to be always faster on Nvidia and AMD. The geometry shader will only be used if all output volumes combined have less than GL_MAX_FRAMEBUFFER_LAYERS slices. Otherwise, the geometry shader stage will be active, but will add a slight overhead instead of improving the performance. Also consider that the geometry shader cannot be removed/added once a ImageProgram has been created.
Classes | |
class | Cuboid |
Utility class to specify the (sub-) region of the textures to execute the shader on. More... | |
Public Types | |
enum class | TexCoordMode { Image , Box } |
Applies if compute() is called with a Cuboid defining a ROI of the textures. More... | |
![]() | |
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 | |
ImageProgram (const std::string &fragmentShaderName, const std::string &defines="", bool useGeometryShader=false, TexCoordMode texCoordMode=TexCoordMode::Image, Compilation compileBehavior=Compilation::ImmediateThrowOnFailure) | |
Creates a new ImageProgram for the given GLSL shader. | |
std::unique_ptr< ImageProgram > | 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. | |
void | setFBO (Framebuffer *fbo) |
Makes ImageProgram use fbo during computation instead of using an internal one. | |
Framebuffer * | fbo () const |
Returns the currently used FBO. | |
void | setClearOutputEnabled (bool enabled, const vec4f &clearColor=vec4f::Zero()) |
Sets whether the output images are cleared before rendering to them (disabled by default). | |
const std::optional< vec4f > | isClearOutputEnabled () const |
Returns whether the output images are cleared before rendering to them, and if yes with which color. | |
void | compute (const std::vector< Texture * > &output, const Cuboid &box={}) |
Executes the program on each pixel or voxel and writes the result in the given output textures. | |
void | compute (Texture &output, const Cuboid &box={}) |
Convenience overload to execute the program on a single texture. | |
void | computeReduceZ (const std::vector< Texture * > &output, int numSlices=-1, int targetSlice=0, const Cuboid &box={}) |
Executes the program on each pixel or voxel inside the box but writes only to a single slice. | |
void | computeReduceZ (Texture &output, int numSlices=-1, int targetSlice=0, const Cuboid &box={}) |
Convenience overload to execute a reduction the program on a single texture. | |
void | setAvoidDriverTimeout (bool value) |
Sets the flag whether execute the shader in batches to avoid driver timeouts. | |
bool | isAvoidingDriverTimeout () const |
Returns the flag whether execute the shader in batches to avoid driver timeouts. | |
bool | setDefines (const std::string &defines, Compilation compileBehavior=Compilation::Immediate) override |
Sets the optional string of definitions that is pasted at the beginning of all shaders. | |
![]() | |
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< 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. | |
const std::string & | defines () 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::string | genericSamplerDefine (bool for3D) |
Returns a string with 3 GLSL defines to help writing shaders that support both 2D and 3D samplers. | |
![]() | |
static std::unique_ptr< Program > | createVertexFragment (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< Program > | createVertexGeometryFragment (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< Program > | createCompute (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 | |
ImageProgram * | cloneImpl () const override |
Virtual helper function to actually clone this type, may throw on error. | |
void | ensureFboIsBound () |
![]() | |
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 |
Protected Attributes | |
std::unique_ptr< VertexBuffer > | m_quad |
Full-screen quad used for rendering during compute() | |
Framebuffer * | m_fbo = nullptr |
FBO used rendering to texture, ownership based on m_ownFbo | |
const TexCoordMode | m_texCoordMode |
std::optional< vec4f > | m_clearColor |
Clear color for the output textures if enabled. | |
const bool | m_useGS = false |
Flag whether to use a Geometry Shader for layered output textures. | |
bool | m_externalFbo = false |
Flag whether m_fbo points to an externally providided FBO. | |
bool | m_avoidTimeout = false |
Flag whether execute the shader in batches to avoid driver timeouts. | |
std::unique_ptr< Pimpl > | m_pimpl |
![]() | |
uint32_t | m_progID = 0 |
OpenGL program ID. | |
std::vector< ShaderInfo > | m_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< TextureBinding > | m_textures |
All textures bound to the shader, index defines binding location. | |
std::vector< BufferBinding > | m_buffers |
All buffers bound to the shader, index defines binding location. | |
std::vector< ImageBinding > | m_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::string > | m_assignedUniforms |
Names of all uniforms that were set using setArgument() | |
std::map< std::string, AbstractIncludeStruct > | m_abstractIncludes |
Abstract include by define name. | |
std::vector< std::string > | m_requiredExtensions |
GLSL extensions that must be enabled. | |
Additional Inherited Members | |
![]() | |
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="") |
|
strong |
Applies if compute() is called with a Cuboid defining a ROI of the textures.
|
explicit |
Creates a new ImageProgram for the given GLSL shader.
fragmentShaderName | Name of the GLSL fragment shader. The shader's source code is resolved using the ImFusion::Resource infrastructure as described in GL::Program. |
defines | List of optional definitions that are to be pasted at the beginning of the source code of each participating shader. |
useGeometryShader | Whether to utilize the geometry shader. This can be faster on 3D volumes with Nvidia or AMD cards, but this depends on the workload. Settings this option to true does not require any changes to the fragment shader. |
texCoordMode | See TexCoordMode |
std::runtime_error | if the OpenGL program could not be created, either due to an OpenGL error or due to the Resource system not being able to resolve all of the shader sources. |
std::unique_ptr< ImageProgram > 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.
cloneOptions | Bitflag mask describing what aspects of the program are to be cloned. |
std::runtime_error | if the new OpenGL program could not be created |
void setFBO | ( | Framebuffer * | fbo | ) |
Makes ImageProgram use fbo during computation instead of using an internal one.
When a custom FBO is set the compute method will not automatically bind or unbind the FBO, however, it will still change the attachments and draw buffers. This may provide a performance benefit in hot sections of the code where you need to minimize the amount of GL state changes.
Framebuffer * fbo | ( | ) | const |
Returns the currently used FBO.
If no FBO was set explicitly, this returns the internal FBO generated by ImageProgram or nullptr in case no internal FBO was requested yet.
void compute | ( | const std::vector< Texture * > & | output, |
const Cuboid & | box = {} ) |
Executes the program on each pixel or voxel and writes the result in the given output textures.
The viewport size (and the number of slices if 3D) is set to the size of the first non-zero texture.
output | The outputs are bound to the locations depending on their position in the vector. If an entry is null, nothing is bound to that attachment. |
box | Optional ROI in terms of pixels to restrict the shader execution to. |
Convenience overload to execute the program on a single texture.
Executes the program on each pixel or voxel and writes the result in the given output textures.
The viewport size (and the number of slices if 3D) is set to the size of the first non-zero texture.
output | The outputs are bound to the locations depending on their position in the vector. If an entry is null, nothing is bound to that attachment. |
box | Optional ROI in terms of pixels to restrict the shader execution to. |
void computeReduceZ | ( | const std::vector< Texture * > & | output, |
int | numSlices = -1, | ||
int | targetSlice = 0, | ||
const Cuboid & | box = {} ) |
Executes the program on each pixel or voxel inside the box but writes only to a single slice.
The viewport size is set to the size of the first non-zero textures. The user has to setup the OpenGL state accordingly so that intended reduction takes place, e.g.
output | The outputs are bound to the locations depending on their position in the vector. If an entry is null, nothing is bound to that attachment. |
numSlices | Number of slices of the output textures. If negative, slices of the first non-zero output will be used. If output is a 2D textures, numSlices can be set to the number of slices of an input volume. This way, the computation will be performed on all voxel of the input volume but the results will be accumulated in the 2D textures. |
targetSlice | Index of the slice to write to if output is a volume. |
box | Optional ROI in terms of pixels to restrict the shader execution to. |
void computeReduceZ | ( | Texture & | output, |
int | numSlices = -1, | ||
int | targetSlice = 0, | ||
const Cuboid & | box = {} ) |
Convenience overload to execute a reduction the program on a single texture.
Executes the program on each pixel or voxel inside the box but writes only to a single slice.
The viewport size is set to the size of the first non-zero textures. The user has to setup the OpenGL state accordingly so that intended reduction takes place, e.g.
output | The outputs are bound to the locations depending on their position in the vector. If an entry is null, nothing is bound to that attachment. |
numSlices | Number of slices of the output textures. If negative, slices of the first non-zero output will be used. If output is a 2D textures, numSlices can be set to the number of slices of an input volume. This way, the computation will be performed on all voxel of the input volume but the results will be accumulated in the 2D textures. |
targetSlice | Index of the slice to write to if output is a volume. |
box | Optional ROI in terms of pixels to restrict the shader execution to. |
void setAvoidDriverTimeout | ( | bool | value | ) |
Sets the flag whether execute the shader in batches to avoid driver timeouts.
If true, ImageProgram will perform a micro-benchmark and estimate the full computation time. If this would exceed the common hard limit on how long a single OpenGL call can take depending on the platform (e.g. TDR on Windows or the nVidia Linux OpenGL driver watchdog), the computation will be split into chunks.
|
overridevirtual |
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 from Program.
|
static |
Returns a string with 3 GLSL defines to help writing shaders that support both 2D and 3D samplers.
For 2D returns:
And for 3D returns:
In a shader it can be used like this:
|
overrideprotectedvirtual |
Virtual helper function to actually clone this type, may throw on error.
Reimplemented from Program.
|
protected |