Engine API Reference - v2.24.0-beta.13
    Preparing search index...

    Class Compute

    A representation of a compute shader with the associated resources, that can be executed on the GPU. Only supported on WebGPU platform.

    Every uniform and resource the compute shader declares has to be given a value on the compute instance, using Compute#setParameter. Values set globally on the scope of the graphics device are not used. The scene depth and color maps of a camera are made available to the shader using Compute#setSceneDepthMap and Compute#setSceneColorMap.

    A compute instance is dispatched at most once in a frame. To dispatch a compute shader more than once in a frame, use a separate compute instance for each dispatch. The instances can share the shader, which is compiled only once.

    Call Compute#destroy when no longer needed. The graphics device retains compute instances for device recovery until they are explicitly destroyed.

    Index
    • Create a compute instance. Note that this is supported on WebGPU only and is a no-op on other platforms.

      Parameters

      • graphicsDevice: GraphicsDevice

        The graphics device.

      • shader: Shader

        The compute shader.

      • Optionalname: string = 'Unnamed'

        The name of the compute instance, used for debugging only.

      Returns Compute

    name: string

    The non-unique name of an instance of the class. Defaults to 'Unnamed'.

    • Deletes a shader parameter from the compute instance.

      Parameters

      • name: string

        The name of the parameter to delete.

      Returns void

    • Attaches the scene color map of a camera to this compute instance, making it available to the compute shader, which accesses it using the functions of the sceneColorCS chunk it includes:

      • sceneColorSize(lod: i32) -> vec2u: the dimensions of a mip level of the color map.
      • sceneColorLoad(texel: vec2i, lod: i32) -> vec4f: the color of a texel.
      • sceneColorSample(uv: vec2f, lod: f32) -> vec4f: the color sampled with filtering. When the format of the color map cannot be filtered on the device, the nearest texel is returned.
      • sceneColorToLinear(color: vec3f) -> vec3f: converts a color to linear.
      • sceneColorToDisplay(color: vec3f) -> vec3f: converts a color to gamma encoded.

      The colors are returned the way the camera stored them - linear when it renders without gamma correction, as it does when using CameraFrame, and gamma encoded otherwise. SCENE_COLORMAP_GAMMA is defined in the shader when they are gamma encoded, and the conversion functions do nothing when the color is already in the requested space.

      The handle is kept, and the color map it identifies is read each time the compute is dispatched, so this only needs to be called once. A dispatch uses the color map the camera rendered most recently - when dispatched before the camera renders, for example from an update event, that is the color map of the previous frame.

      The camera only renders the color map when requested, see CameraComponent#requestSceneColorMap, or when its CameraFrame is configured to.

      Parameters

      Returns void

      // the compute shader includes the chunk, for example:
      // #include "sceneColorCS"
      // let color = sceneColorToLinear(sceneColorLoad(vec2i(id.xy), 0).rgb);
      cameraEntity.camera.requestSceneColorMap(true);
      compute.setSceneColorMap(cameraEntity.camera.sceneColorMapHandle);
    • Attaches the scene depth map of a camera to this compute instance, making it available to the compute shader, which accesses it using the functions of the sceneDepthCS chunk it includes:

      • sceneDepthSize() -> vec2u: the dimensions of the depth map.
      • sceneDepthViewport() -> vec4u: the viewport the camera rendered the depth map with, in texels: the x and y of its first texel, and its width and height. A camera rendering to only a part of its target, see CameraComponent#rect, covers only this part of the depth map.
      • sceneDepthNearClip() -> f32, sceneDepthFarClip() -> f32: the clip planes the depth map was rendered with.
      • sceneDepthLinear(texel: vec2i) -> f32: the linear camera depth, in world units.
      • sceneDepthWorldPosition(texel: vec2i) -> vec3f: the world position of the surface at the texel, which needs to be within the viewport.

      The handle is kept, and the depth map it identifies is read each time the compute is dispatched, so this only needs to be called once. A dispatch uses the depth map the camera rendered most recently - when dispatched before the camera renders, for example from an update event, that is the depth map of the previous frame. However the camera stored the depth, it is decoded with the camera parameters it was rendered with.

      The camera only renders the depth map when requested, see CameraComponent#requestSceneDepthMap, or when its CameraFrame is configured to.

      Parameters

      Returns void

      // the compute shader includes the chunk, for example:
      // #include "sceneDepthCS"
      // let position = sceneDepthWorldPosition(vec2i(id.xy));
      cameraEntity.camera.requestSceneDepthMap(true);
      compute.setSceneDepthMap(cameraEntity.camera.sceneDepthMapHandle);
    • Prepare the compute work dispatch, for a grid of workgroups. To dispatch for a number of threads instead, with the workgroups derived from them, use Compute#setupDispatchThreads.

      Parameters

      • x: number

        X dimension of the grid of work-groups to dispatch.

      • Optionaly: number

        Y dimension of the grid of work-groups to dispatch.

      • Optionalz: number

        Z dimension of the grid of work-groups to dispatch.

      Returns void

    • Prepare the compute work dispatch, for a number of threads in each dimension, a thread being one invocation of the compute shader, as identified by its global_invocation_id. The workgroups to dispatch are derived from the workgroup size the entry point of the shader declares using @workgroup_size with integer literals, which can be the values of defines injected into the shader. The dispatch is rounded up to whole workgroups, so the shader skips the threads beyond the requested number. To do that, and to index the threads, it uses the functions of the dispatchThreadsCS chunk it includes:

      • dispatchThreadCount() -> vec3u: the number of threads the dispatch was set up for.
      • dispatchThreadInRange(globalId: vec3u) -> bool: true when the thread is one of those threads.
      • dispatchThreadIndex(globalId: vec3u) -> u32: the linear index of the thread, x varying fastest.

      A dispatch of threads in one dimension, which needs more workgroups than the device supports in a single dimension, is spread over rows of workgroups. The shader then needs to include the chunk, as the functions account for that.

      A compute shader using the chunk, dispatched for a thread for each particle:

      #include "dispatchThreadsCS"

      @compute @workgroup_size(64)
      fn main(@builtin(global_invocation_id) id: vec3u) {
      if (!dispatchThreadInRange(id)) { return; }
      let index = dispatchThreadIndex(id);
      }

      Parameters

      • x: number

        The number of threads in the X dimension.

      • Optionaly: number = 1

        The number of threads in the Y dimension. Defaults to 1.

      • Optionalz: number = 1

        The number of threads in the Z dimension. Defaults to 1.

      Returns void

      compute.setupDispatchThreads(particleCount);
      
    • Prepare the compute work dispatch to use indirect parameters from a buffer. The dispatch parameters (x, y, z workgroup counts) are read from the buffer at the specified slot index.

      When using the device's built-in buffer (buffer parameter is null), this method must be called each frame as slots are only valid for the current frame.

      Parameters

      • slotIndex: number

        Slot index in the indirect dispatch buffer. When using the device's built-in buffer, obtain this by calling GraphicsDevice#getIndirectDispatchSlot.

      • Optionalbuffer: StorageBuffer | null = null

        Optional custom storage buffer containing dispatch parameters. If not provided, uses the device's built-in GraphicsDevice#indirectDispatchBuffer. When providing a custom buffer, the user is responsible for its lifetime and contents.

      Returns void

      // Reserve a slot in the indirect dispatch buffer
      const slot = device.getIndirectDispatchSlot();

      // First compute shader writes dispatch parameters to the buffer
      prepareCompute.setParameter('indirectBuffer', device.indirectDispatchBuffer);
      prepareCompute.setParameter('slot', slot);
      prepareCompute.setupDispatch(1, 1, 1);
      device.computeDispatch([prepareCompute]);

      // Second compute shader uses indirect dispatch
      processCompute.setupIndirectDispatch(slot);
      device.computeDispatch([processCompute]);