(data …)
Defines embedded data for buffer initialization. Supports compile-time shape generators, inline float arrays, WASM (WebAssembly) generated data, and external image files.
Syntax
Section titled “Syntax”; Shape generator (compile-time mesh generation)(data :name cubeVerts (cube :format [position4 color4 uv2]))
; Inline float array(data :name weights :float32 [1.0 2.0 3.0])
; WASM-generated data(data :name curve (wasm-data :file "gen.wasm" :func make :returns "array<f32,360>"))
; External image file(data :name logoFile :file "path/to/file.png" :mime "image/png")| Key | Type | Required | Default | Description |
|---|---|---|---|---|
:name |
symbol | Yes | - | Unique data name |
| generator sub-form | positional form | No* | - | (cube …), (plane …), … or (wasm-data …) |
:float32 |
array | No* | - | Inline float array data |
:file |
string | No* | - | Image file path, relative to the source document |
:mime |
string | No | application/octet-stream |
MIME type stored with the :file bytes |
*One byte source, three spellings. A (data …) carries at most one
positional generator sub-form; a second one is a positional_too_many error
rather than a silently ignored form. If more than one spelling is present the
generator wins, then :file, then :float32; a (data …) with none of them
is an empty entry of zero bytes.
Shape Generators
Section titled “Shape Generators”Generate vertex data at compile time instead of writing arrays manually. A shape
is a positional sub-form inside (data …). Shape generators produce triangle
lists with the specified vertex attributes.
Available shapes: cube, plane, sphere, torus, truncated-cone,
cylinder, teapot, dragon. Each accepts a :format list, plus
generator-specific parameters:
| Key | Type | Default | Applies to |
|---|---|---|---|
:segments |
number | 24 |
sphere (longitude) |
:rings |
number | 12 |
sphere (latitude) |
:radius |
number | 1.0 |
sphere, torus (major radius), cylinder |
:thickness |
number | 0.24 |
torus (minor radius) |
:radial-subdivisions |
number | 24 |
torus, truncated-cone, cylinder |
:body-subdivisions |
number | 12 |
torus |
:vertical-subdivisions |
number | 1 |
truncated-cone, cylinder |
:bottom-radius |
number | 1.0 |
truncated-cone (a cylinder takes :radius for both ends) |
:top-radius |
number | 0.0 |
truncated-cone |
:height |
number | 1.0 |
truncated-cone, cylinder |
:top-cap / :bottom-cap |
boolean | true |
truncated-cone, cylinder |
:faceted |
boolean | false |
flat normals, one per triangle |
A subdivision count outside its generatable range is a compile error naming the key and the range: no generated mesh may exceed 65536 indices.
Generates a cube centred at the origin, vertices at ±1. Produces 36 vertices (6 faces × 2 triangles × 3 vertices), deindexed.
(data :name cubeVertices (cube :format [position4 color4 uv2]))Generates a single 1×1 quad on the XY plane, facing +Z. Produces 6 vertices (2 triangles), deindexed.
(data :name planeVertices (plane :format [position3 uv2]))sphere
Section titled “sphere”Generates a UV sphere. Extra parameters (:segments, :rings) tune the
tessellation:
(data :name sphereVertices (sphere :format [position3 normal3] :segments 24 :rings 12))Indexed Meshes
Section titled “Indexed Meshes”The teapot and dragon generators produce an indexed mesh: vertex data plus an
index companion. Source a vertex buffer from the shape and an index buffer with
:index-of:
(data :name teapotMesh (teapot :format [position3 normal3]))
(buffer :name vertexBuffer :usage [vertex] :data teapotMesh)(buffer :name indexBuffer :index-of teapotMesh :usage [index])Format Specifiers
Section titled “Format Specifiers”The :format array specifies which attributes to generate for each vertex:
| Specifier | Type | Size | Description |
|---|---|---|---|
position3 |
vec3f | 12 bytes | XYZ position |
position4 |
vec4f | 16 bytes | XYZW position (w=1) |
normal3 |
vec3f | 12 bytes | Surface normal |
color3 |
vec3f | 12 bytes | RGB vertex colour |
color4 |
vec4f | 16 bytes | RGBA vertex colour |
uv2 |
vec2f | 8 bytes | Texture coordinates |
Vertex stride is the sum of all attribute sizes. For [position4 color4 uv2]:
- position4: 16 bytes
- color4: 16 bytes
- uv2: 8 bytes
- Total stride: 40 bytes
:float32
Section titled “:float32”Type: array of numbers
Inline float values, written directly:
(data :name vertices :float32 [ 0.0 0.5 1.0 0.0 0.0 -0.5 -0.5 0.0 1.0 0.0 0.5 -0.5 0.0 0.0 1.0])
:float32takes a literal list only; there is no repeat-or-fill generator. For computed values, use a(wasm-data …)generator (below) to produce the bytes at compile time, or a compute init pass (see(init …)) to fill the buffer on the GPU.
WASM-Generated Data
Section titled “WASM-Generated Data”A (wasm-data …) sub-form calls a WASM function once at buffer-create time; its
returned bytes fill the buffer.
(data :name curve (wasm-data :file "gen.wasm" :func makeCurve :returns "array<f32,360>"))| Key | Type | Required | Description |
|---|---|---|---|
:file |
string | Yes | WASM file path, relative to the source document |
:func |
symbol | Yes | Exported function to call |
:returns |
string | Yes | Return type, turned into a byte count (array<f32,360> is 1440, mat4x4 is 64, vec4 is 16, f32 is 4) |
Modules are deduplicated by path, and are read at compile time, so an
unreadable :file is an error that names the path.
Type: string
Path to an image file, relative to the source document. It is embedded in the
PNGB payload (the compiled bytecode) at compile time as
[mime_len][mime][bytes], and decoded at runtime by an (image-bitmap …):
(data :name imageFile :file "textures/diffuse.png" :mime "image/png")Examples
Section titled “Examples”Cube with Shape Generator
Section titled “Cube with Shape Generator”(data :name cubeVertices (cube :format [position4 color4 uv2]))
(buffer :name vertexBuffer :usage [vertex] :data cubeVertices)
(render-pipeline :name cubeRenderer :layout auto (vertex :module shader :entry vs (vertex-buffer :array-stride 40 (attribute :shader-location 0 :offset 0 :format float32x4) (attribute :shader-location 1 :offset 16 :format float32x4) (attribute :shader-location 2 :offset 32 :format float32x2))) (fragment :module shader :entry fs (target :format preferred-canvas-format)))Simple Triangle (Manual Data)
Section titled “Simple Triangle (Manual Data)”(data :name triangleVerts :float32 [ 0.0 0.5 1 0 0 -0.5 -0.5 0 1 0 0.5 -0.5 0 0 1])
(buffer :name vertexBuffer :usage [vertex] :data triangleVerts)External Image
Section titled “External Image”(data :name textureData :file "assets/logo.png" :mime "image/png")
(image-bitmap :name logo :data textureData)Data Size
Section titled “Data Size”A buffer with :data takes its size from the data, so no byte count is written
beside it:
(data :name vertexData (cube :format [position4 color4 uv2]))
(buffer :name verts ; sized by the data it is filled from :usage [vertex] :data vertexData)Size calculation:
- Shape generators: vertex_count × stride (e.g. a cube with position4+color4+uv2 = 36 × 40 = 1440 bytes)
- Inline
:float32arrays: element_count × 4 bytes (wasm-data …): the byte count its:returnstype spells
A numeric :size beside :data is legal and over-allocates on purpose; a
:size smaller than the data is a compile error. A (data …) name is not
accepted in :size itself, which takes a number, an expression, or a
(define …) constant.
Validation Rules
Section titled “Validation Rules”| Rule | Error |
|---|---|
| A name is declared once, across every form kind | duplicate_cross_ref_target, or duplicate name 'x': already declared as a (data …) at line N |
| At most one generator sub-form | positional_too_many |
| The sub-form head is one of the nine generators | not_head_member |
:format entries are position3, position4, normal3, color3, color4 or uv2 |
not_member |
| A generator’s subdivision counts are in range | (sphere …) :segments 0 is outside the generatable range 3..4096 |
:file must be readable at compile time |
cannot read 'assets/logo.png': FileNotFound (located on the (data …) form; the path is resolved against the document’s directory) |
The rows with a code are schema checks; the rows with a message are compiler checks, and they report the line the form is written on.
Where these words come from
Section titled “Where these words come from”Every key and value on this page traced to the WebGPU name it stands for, with a link to the definition. How the tracing is made, and what keeps it from rotting, is the subject of Where the Words Come From.
(data …) is PNGine’s own. WebGPU has no data form: bytes arrive through writeBuffer() or a mapped buffer, and where they come from is the page’s business. Here they come from the document (a float list), a file, or a shape generator, and the compiler bakes them into the payload.
| Key | WebGPU | Note |
|---|---|---|
:name |
PNGine’s own | the name a (buffer …) or (image-bitmap …) refers to |
:float32 |
PNGine’s own | literal floats, packed little-endian |
:file |
PNGine’s own | a file embedded at compile time |
:mime |
PNGine’s own | the type of an embedded image file |
(cube …) is PNGine’s own. A compile-time shape generator; it produces the vertex bytes a (buffer …) takes as :data.
| Key | WebGPU | Note |
|---|---|---|
:format |
PNGine’s own | the vertex layout to generate: position4, normal3, uv2, … |
(plane …) is PNGine’s own. A compile-time shape generator; it produces the vertex bytes a (buffer …) takes as :data.
| Key | WebGPU | Note |
|---|---|---|
:format |
PNGine’s own | the vertex layout to generate: position4, normal3, uv2, … |
(sphere …) is PNGine’s own. A compile-time shape generator; it produces the vertex bytes a (buffer …) takes as :data.
| Key | WebGPU | Note |
|---|---|---|
:format |
PNGine’s own | the vertex layout to generate: position4, normal3, uv2, … |
(torus …) is PNGine’s own. A compile-time shape generator; it produces the vertex bytes a (buffer …) takes as :data.
| Key | WebGPU | Note |
|---|---|---|
:format |
PNGine’s own | the vertex layout to generate: position4, normal3, uv2, … |
(truncated-cone …) is PNGine’s own. A compile-time shape generator; it produces the vertex bytes a (buffer …) takes as :data.
| Key | WebGPU | Note |
|---|---|---|
:format |
PNGine’s own | the vertex layout to generate: position4, normal3, uv2, … |
(cylinder …) is PNGine’s own. A compile-time shape generator; it produces the vertex bytes a (buffer …) takes as :data.
| Key | WebGPU | Note |
|---|---|---|
:format |
PNGine’s own | the vertex layout to generate: position4, normal3, uv2, … |
(teapot …) is PNGine’s own. A compile-time shape generator; it produces the vertex bytes a (buffer …) takes as :data.
| Key | WebGPU | Note |
|---|---|---|
:format |
PNGine’s own | the vertex layout to generate: position4, normal3, uv2, … |
(dragon …) is PNGine’s own. A compile-time shape generator; it produces the vertex bytes a (buffer …) takes as :data.
| Key | WebGPU | Note |
|---|---|---|
:format |
PNGine’s own | the vertex layout to generate: position4, normal3, uv2, … |
(wasm-data …) is PNGine’s own. A WASM module run at load time to produce the bytes.
| Key | WebGPU | Note |
|---|---|---|
:file |
PNGine’s own | the module |
:func |
PNGine’s own | the export to call |
:returns |
PNGine’s own | the shape of what it returns |
Checked against the WebGPU specification at revision b8c0fa9; the links go to the current draft.
Related
Section titled “Related”(buffer …)- Use data for buffer initialization(image-bitmap …)- Create images from blob data(queue …)- Write data to buffers at runtime