Chromium Experimental Primitive ID

The chromium_experimental_primitive_id is an experimental extension that allows the use of the primitive_id builtin in fragment shaders in WGSL.

Status

This extension is experimental and the syntax is being discussed. No official WebGPU specification has been written yet.

Availability

The usage is restricted to fragment shaders.

PlatformTypeNotes
SPIR-V32-bit integerRequires geometry shaders, mesh shaders, or raytracing. Available as the PrimitiveID builtin
HLSLu32Requires D3D10. Available as the SV_PrimitiveID semantic
GLSLi32Requires GLSL 1.50 and later, ESSL 3.2. (ESSL 3.1 with GL_EXT_geometry_shader). Available as the gl_primitiveID builtin
Metalu32Requires Metal 2.2 on MacOS or Metal 2.3 on iOS. Available as [[primitive_id]]

Due to the limited availability, this will need a enable statement to be used. For this experimental extension it would be enable chromium_experimental_primitive_id.

All of the topologies in GPUPrimitiveTopology are supported. (Generally, adjacency topologies would not be supported but WebGPU does not have any adjacency topologies).

TopologyPrimitive
point-listEach vertex is a primitive
line-listEach vertex pair is a primitive
line-stripEach adjacent vertex pair is a primitive
triangle-listEach vertex triplet is a primitive
triangle-stripEach group of 3 adjacent vertices is a primitive

Specification

This extension adds a new builtin_value_name entry for primitive_id.

An entry is added to the Built-in input and output values table:

  • Name: primitive_id

  • Stage: fragment

  • Direction: input

  • Type: u32

  • Extension: chromium_experimental_primitive_id

  • The index of the first primitive is zero, incrementing by one for each subsequent primitive.

  • primitive_id resets to zero between each instance drawn.

  • If the primitive id overflows (exceeds 2^32 – 1), it wraps to 0. (This is from HLSL, is it true for other backends?)

  • There is no support for automatically generating a primitive id for adjacent primitives.

    • For an adjacent primitive, the id is only maintained for the internal non-adjacent primitives.
  • The primitive_id value is uniform across the primitive.

  • Primitive restart has no effect on the value of variables decorated with primitive_id.

    • Is this true for HLSL and MSL? I can see it in the spec for GLSL and SPIR-V but haven't found reference for HLSL or MSL.

Example usage

@vertex fn vs_main(@builtin(primitive_id) my_id: u32) -> @builtin(position) vec4f {
    return vec4f(f32(my_id));
}

References