-
-
Notifications
You must be signed in to change notification settings - Fork 29
Compute shaders
Romain Milbert edited this page Apr 21, 2024
·
6 revisions
Compute shaders are their own kind of shaders; they can be given code as usual from a file path or inline code, and are operated through a ComputeShaderProgram
object:
Raz::ComputeShaderProgram computeProgram(Raz::ComputeShader::loadFromSource(R"(
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout(rgba8, binding = 0) uniform readonly restrict image2D uniInput;
layout(r16f, binding = 0) uniform writeonly restrict image3D uniOutput;
void main() {
// As we run the shader with 32x32x32 invocations (see below), each of the gl_GlobalInvocationID's
// 3 components will be between [0; 31] and will represent the integer coordinates within our textures
// See https://www.khronos.org/opengl/wiki/Compute_Shader#Inputs
ivec3 pixelCoords = ivec3(gl_GlobalInvocationID.xyz);
vec3 inputValue = imageLoad(uniInput, pixelCoords.xy).rgb;
// Even though we have a single-channel output texture, it presumably doesn't hurt to set the first 3 (RGB)
// ones, as they should be discarded since we *need* to give it 4 anyway (https://docs.gl/sl4/imageStore)
// Incidentally, it allows to have a grayscale color when setting an RGB texture without any change
// here. Most likely not useful, but could help spotting an incorrect setup?
imageStore(uniOutput, pixelCoords, vec4(vec3(dot(inputValue, inputValue)), 1.0));
}
)"));
// Setup necessary stuff (attributes, textures (see relevant section below), ...)
// Executing the compute shader requires from 1 to 3 arguments, which will be the number of work groups
// on each dimension (https://docs.gl/gl4/glDispatchCompute)
// Note that at the time of writing, this sets a memory barrier for *all* types
// (https://docs.gl/gl4/glMemoryBarrier); this may be more fine-grained later
computeProgram.execute(32, 32, 32);
Textures can be used in compute shaders only as image textures. The textures themselves are declared as usual, but added differently to the shader program:
// "Simple" RGB layouts do not exist; if you need 3 channels, use an RGBA colorspace. Double-check that
// it's the case in the shader too
// The R11G11B10 layout should be supported later
const auto inputTexture = Raz::Texture2D::create(32, 32,
Raz::TextureColorspace::RGBA,
Raz::TextureDataType::BYTE);
const auto outputTexture = Raz::Texture3D::create(32, 32, 32,
Raz::TextureColorspace::GRAY,
Raz::TextureDataType::FLOAT16);
// Texture images can be set as either read only, write only, or both
// This must match the potential specification in the shader
computeProgram.setImageTexture(inputTexture, "uniInput", Raz::ImageTextureUsage::READ);
computeProgram.setImageTexture(outputTexture, "uniOutput", Raz::ImageTextureUsage::WRITE);
computeProgram.initImageTextures();
- Home
- How to build RaZ
- Getting started
- General usage knowledge
- Some examples...
- Playground
- Tutorials
- File formats
- Modules
- Debug