How to Use subgroupBroadcast in GLSL

This article provides an overview of the subgroupBroadcast function in GLSL, explaining its role in cross-lane communication within compute and graphics pipelines. It covers the core functionality of reading data from a designated lane and replicating it across all active invocations in a subgroup, the syntax required, performance benefits over shared memory, and important execution constraints to consider when implementing it.

Core Functionality

In GLSL, subgroupBroadcast enables threads (invocations) within the same subgroup (warp or wavefront) to share data without using local shared memory (shared) or explicit barrier synchronizations. Its primary function is to sample an expression evaluated by a single specified invocation lane and distribute that resulting value to all other invocations within that subgroup.

Syntax and Parameters

The function signature is defined as:

type subgroupBroadcast(type value, uint id);
  • value: The data expression to be broadcast. While all invocations execute this expression, the function only returns the evaluation from the lane specified by id. The type can be any basic scalar, vector, or matrix type supported by subgroup operations.
  • id: An unsigned integer representing the invocation index (gl_SubgroupInvocationID) of the source lane. This parameter must typically be a compile-time constant or dynamically uniform across the subgroup, depending on the target GLSL extension and Vulkan environment specifications.

Operational Mechanics

When subgroupBroadcast executes:

  1. The hardware identifies the lane matching the id index.
  2. The value present on that specific lane is read directly from register space or cross-lane data paths (such as shuffle instructions on modern GPUs).
  3. That identical value is returned to every active invocation in the subgroup, effectively copying the designated lane's data across the entire warp or wavefront in a single execution step.

Advantages Over Shared Memory

Before subgroup operations were standardized, sharing a value from one thread to its neighbors required:

  1. Writing the value to a workgroup shared variable.
  2. Executing a memoryBarrierShared() and a barrier().
  3. Having the remaining threads read the value from shared memory.

subgroupBroadcast bypasses memory and cache hierarchies entirely. It compiles directly into hardware-level lane-swizzle or shuffle instructions, reducing latency to a few clock cycles and eliminating the need for barriers.

Execution Constraints

  • Active Lane Requirement: The invocation identified by id must be an active invocation. If lane id has diverged or exited execution due to conditional branching, the returned value is undefined.
  • Valid Range: The id must be strictly less than gl_SubgroupSize. Passing an out-of-bounds index results in undefined behavior.
  • Uniformity: For dynamic indices where id varies across lanes, the alternate function subgroupShuffle should be used instead of subgroupBroadcast.