hostBlock
On this page

hostBlock()

Function in Layout

Declare a host-owned uniform block: a whole struct of values the host supplies, from one declaration that works on both targets.

import { hostBlock } from 'typeshade'

The signature, the description and the examples come from the compiler's own source at commit 26de7be8.

Syntax

function hostBlock<F extends Record<string, UniformFieldSpec>>(
typeName: string,
at: { group: number; binding: number; as: string },
fields: F,
opts?: { glsl?: 'std140-block' | 'loose'; precision?: 'highp' | 'mediump' | 'lowp' },
): UniformStruct<F>

Parameters

typeName string

the struct’s type name, as the host spells it.

at { group: number; binding: number; as: string }

the WGSL group and binding slot, and as, the block variable’s name.

fields F extends Record<string, UniformFieldSpec>

the members, in the host’s declaration order.

optsoptional { glsl?: 'std140-block' | 'loose'; precision?: 'highp' | 'mediump' | 'lowp' }

glsl picks the GLSL spelling; precision is a GLSL-only qualifier applied to each member of a 'loose' block (a std140 block takes the stage default).

Return value

UniformStruct<F>

the UniformStruct handle; camera.field.u_matrix is typed against the declared shape.

Exceptions

SD0016

SD0016 when glsl: 'loose' is asked for a member the default block cannot spell.

UnsupportedFeatureError

Their names must also be unique across every loose block in the module, since flattening puts them all in one namespace; a collision throws UnsupportedFeatureError at GLSL emit.

Description

On WGSL a host-owned bind group is one unit: the host hands the module @group(0) and its layout is the authority. That is why a block is its own declaration and cannot be written as several hostUniform calls, which would describe a different program.

On WGSL it is an ordinary @group(N) @binding(M) var<uniform> block, which the shader still declares in order to read it, and reflect marks every entry owner: 'host' so a consumer knows not to build a layout for it.

On GLSL ES 3.00 the spelling is the caller’s choice, because a GLSL host prelude provides one or the other and only the matching one links:

  • glsl: 'std140-block' (the default) emits layout(std140) uniform CameraUniforms { ... } u_camera;.
  • glsl: 'loose' emits one uniform mat4 u_matrix; per member and rewrites every u_camera.u_matrix read to the bare u_matrix. The rewrite happens on the module’s node graph before emit, so it cannot touch an unrelated substring, it survives minify(), and reflect still describes what was emitted.

A loose block’s members must be scalars, vectors or matrices, because the default block has no spelling for a nested struct; this call checks it and throws SD0016. Their names must also be unique across every loose block in the module, since flattening puts them all in one namespace; a collision throws UnsupportedFeatureError at GLSL emit.

Examples

Example

import { hostBlock, mat4x4fT, vec2fT } from 'typeshade'
const camera = hostBlock('CameraUniforms', { group: 0, binding: 0, as: 'u_camera' }, {
u_matrix: mat4x4fT,
u_viewport_px: vec2fT,
}, { glsl: 'loose' })
camera.field.u_matrix // typed against the declared shape

In the guide

See also

Source

src/core/sot.ts, line 972, at commit 26de7be8

Edit this page Report a problem