Compute Shaders

Overview

The compute shader API provides two classes for dispatching GPU compute work:

  • ComputeShaderElement – low-level compute shader element with full control over parameter binding, dispatch modes, and GPU pipeline selection.

  • ComputeShader – lightweight RAII wrapper for the common case of creating a shader by name and dispatching work.

Warning

Avoid using ComputeShaderElement directly. It returns a raw pointer from new_compute_shader() that must be manually deleted, making it easy to leak memory. Prefer ComputeShader which manages lifetime automatically via eastl::unique_ptr.

Usage

Creating a compute shader

Use the ComputeShader RAII wrapper:

#include <shaders/dag_computeShaders.h>

ComputeShader cs("my_compute_shader");
if (cs)
  cs.dispatchThreads(width, height, 1);

Setting parameters

Shader parameters are set via variable IDs obtained from get_shader_variable_id():

int varId = get_shader_variable_id("some_param");
cs->set_color4_param(varId, Color4(1, 0, 0, 1));
cs->set_texture_param(texVarId, textureId);

Dispatching work

There are three dispatch modes:

  • By thread groupsComputeShaderElement::dispatch() dispatches the specified number of thread groups directly.

  • By total threadsComputeShaderElement::dispatchThreads() takes the desired total thread count and automatically divides by the shader’s thread group sizes (rounding up).

  • IndirectComputeShaderElement::dispatch_indirect() reads dispatch arguments from a GPU buffer. The buffer must contain 3 uint32_t values (groupCountX, groupCountY, groupCountZ) at the given byte offset. The buffer must be created with SBCF_BIND_UNORDERED and SBCF_MISC_DRAWINDIRECT flags (e.g. via d3d::buffers::create_ua_indirect with Indirect::Dispatch). When storing multiple dispatch entries in a single buffer, the byte offset should be a multiple of DISPATCH_INDIRECT_BUFFER_SIZE (12 bytes).

// Dispatch by thread groups
cs->dispatch(groupsX, groupsY, groupsZ);

// Dispatch by total thread count (auto-divides by thread group size)
cs->dispatchThreads(totalX, totalY, totalZ);

// Indirect dispatch from a GPU buffer
cs->dispatch_indirect(argsBuffer, byteOffset);

API Reference

Functions

ComputeShaderElement *new_compute_shader(const char *shader_name, bool optional = false)

Creates a ComputeShaderElement from a DSHL shader class name.

Parameters:
  • shader_name – Name of the compute shader class defined in DSHL.

  • optional – If true, returns nullptr instead of asserting when the shader is not found.

Returns:

Pointer to a new ComputeShaderElement, or nullptr if optional is true and the shader was not found.

class ComputeShaderElement : public DObject
#include <dag_computeShaders.h>

Compute shader element with full control over parameter binding and dispatch.

Created via new_compute_shader(). Wraps a ScriptedShaderMaterial and provides methods to set shader parameters, query thread group sizes, and dispatch compute work on the GPU.

Subclassed by MeshShaderElement

Parameter setters

Set shader parameters by variable ID (obtained from get_shader_variable_id()).

return:

true if the variable was found and set successfully.

bool set_int_param(const int variable_id, const int v)
bool set_real_param(const int variable_id, const real v)
bool set_color4_param(const int variable_id, const struct Color4&)
bool set_texture_param(const int variable_id, const TEXTUREID v)
bool set_sampler_param(const int variable_id, d3d::SamplerHandle v)

Parameter getters

Query current parameter values.

return:

true if the variable exists.

bool hasVariable(const int variable_id) const
bool getColor4Variable(const int variable_id, Color4 &value) const
bool getRealVariable(const int variable_id, real &value) const
bool getIntVariable(const int variable_id, int &value) const
bool getTextureVariable(const int variable_id, TEXTUREID &value) const
bool getSamplerVariable(const int variable_id, d3d::SamplerHandle &value) const

Dispatch

eastl::array<uint16_t, 3> getThreadGroupSizes() const

Returns the thread group sizes (X, Y, Z) declared in the shader.

bool dispatch(int tgx, int tgy, int tgz, GpuPipeline gpu_pipeline = GpuPipeline::GRAPHICS, bool set_states = true) const

Dispatches the specified number of thread groups.

Parameters:
  • tgx – Number of thread groups in X.

  • tgy – Number of thread groups in Y.

  • tgz – Number of thread groups in Z.

  • gpu_pipeline – GPU pipeline to dispatch on.

  • set_states – If true, binds shader states before dispatch.

Returns:

true on success.

bool dispatchThreads(int threads_x, int threads_y, int threads_z, GpuPipeline gpu_pipeline = GpuPipeline::GRAPHICS, bool set_states = true) const

Dispatches by total thread count, automatically dividing by thread group sizes (rounding up).

Parameters:
  • threads_x – Total threads in X.

  • threads_y – Total threads in Y.

  • threads_z – Total threads in Z.

  • gpu_pipeline – GPU pipeline to dispatch on.

  • set_states – If true, binds shader states before dispatch.

Returns:

true on success.

uint32_t getWaveSize() const

Returns the wave/warp size for this shader.

inline bool dispatch(GpuPipeline gpu_pipeline = GpuPipeline::GRAPHICS, bool set_states = true) const

Dispatches a single thread group (1, 1, 1).

bool dispatch_indirect(Sbuffer *args, int ofs, GpuPipeline gpu_pipeline = GpuPipeline::GRAPHICS, bool set_states = true) const

Dispatches using indirect arguments read from a GPU buffer.

Parameters:
  • args – Buffer containing dispatch arguments (3 uint32_t values: groupCountX, groupCountY, groupCountZ). Must be created with SBCF_BIND_UNORDERED and SBCF_MISC_DRAWINDIRECT flags (e.g. via d3d::buffers::create_ua_indirect with Indirect::Dispatch).

  • ofs – Byte offset into args where the arguments start. Must be a multiple of DISPATCH_INDIRECT_BUFFER_SIZE (12 bytes) when accessing sequential dispatch entries in the buffer.

  • gpu_pipeline – GPU pipeline to dispatch on.

  • set_states – If true, binds shader states before dispatch.

Returns:

true on success.

Public Functions

ComputeShaderElement(ScriptedShaderMaterial *ssm, ShaderElement *selem = nullptr)
Parameters:
  • ssm – Scripted shader material that defines this compute shader.

  • selem – Optional shader element override; if null, created from ssm.

~ComputeShaderElement()
const char *getShaderClassName() const

Returns the DSHL shader class name.

bool setStates() const

Binds shader states without dispatching.

PROGRAM getComputeProgram() const

Returns the underlying compute program handle.

Protected Attributes

ScriptedShaderMaterial *mat
ScriptedShaderElement *elem
class ComputeShader
#include <dag_computeShaders.h>

Lightweight RAII wrapper around ComputeShaderElement for common dispatch patterns.

Manages the lifetime of the underlying ComputeShaderElement and provides a simplified dispatch interface that always uses GpuPipeline::GRAPHICS.

Public Functions

ComputeShader() = default
inline ComputeShader(const char *shader_name, bool optional = false)

Constructs a compute shader from a DSHL shader class name.

Parameters:
  • shader_name – Name of the compute shader class. If nullptr, creates an empty (invalid) shader.

  • optional – If true, silently handles missing shaders instead of asserting.

inline bool dispatchThreads(int threads_x, int threads_y, int threads_z) const

Dispatches by total thread count, auto-dividing by thread group sizes.

inline bool dispatchGroups(int groups_x, int groups_y, int groups_z) const

Dispatches the specified number of thread groups.

inline bool dispatchIndirect(Sbuffer *args, int ofs) const

Dispatches using indirect arguments from a GPU buffer.

inline PROGRAM getComputeProgram() const

Returns the underlying compute program handle.

inline explicit operator bool() const

Returns true if the shader was loaded successfully.

Private Members

eastl::unique_ptr<ComputeShaderElement> elem