Skip to content

chore: release v0.5.3 - #99

Closed
tycho wants to merge 16 commits into
masterfrom
release/2026-07-27T07-23-33Z
Closed

chore: release v0.5.3#99
tycho wants to merge 16 commits into
masterfrom
release/2026-07-27T07-23-33Z

Conversation

@tycho

@tycho tycho commented Jul 27, 2026

Copy link
Copy Markdown
Owner

🤖 New release

  • gloam: 0.5.2 -> 0.5.3 (✓ API compatible changes)
Changelog

0.5.3 - 2026-07-28

Added

  • (generator) Vulkan Rust loader (phased, scope-aware)
  • (generator) Vulkan type printer for the Rust backend
  • (generator) derive Rust GL base types from registry payloads
  • (parse) structured TypePayload for spec type bodies
  • (parse) typed C declarator IR (TypeRef) for command params and returns
  • (ci) run cargo hack with --feature-powerset flag
  • (regen) add gloam regen subcommand for in-place tree regeneration
  • (generator) add Rust backend implementation

Fixed

  • (resolve) deterministic ordering for dependency-pulled extensions
  • (ci) skip running certain workflows on non-GitHub hosting
  • (cargo) unbreak build on Rust 1.88, hold rusqlite at 0.39

Other

  • (examples) regenerate loader trees via gloam regen
  • (examples) regenerate loader trees via gloam regen
  • (examples) regenerate loader trees via gloam regen
  • (cargo) update base64 and rusqlite
  • document the rust and regen subcommands
  • (examples) regenerate loader trees via gloam regen
  • regenerate example trees in the weekly bundled-update workflow
  • (xtask) make regen a thin wrapper over gloam regen
  • (bundled) embed specs/headers as DEFLATE blobs (~6 MiB smaller binary)


This PR was generated with release-plz.

@tycho tycho added the release label Jul 27, 2026
@tycho
tycho force-pushed the release/2026-07-27T07-23-33Z branch from ca08555 to c00b102 Compare July 27, 2026 14:15
README gains `rust` and `regen` entries in the command reference, a
"Rust output (experimental)" section showing the generated crate's shape
and load API, and a "Regenerating a tree with gloam regen" section under
the provenance material.  docs/manifest.md points at `gloam regen` as
the automated form of the --lock replay it describes.  CONTRIBUTING's
pipeline sketch and module map pick up generator/rust/ and regen.rs, and
CLAUDE.md's design philosophy no longer claims there is no active non-C
backend.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@tycho
tycho force-pushed the release/2026-07-27T07-23-33Z branch from c00b102 to caac949 Compare July 27, 2026 14:27
Signed-off-by: Steven Noonan <steven@uplinklabs.net>
@tycho
tycho force-pushed the release/2026-07-27T07-23-33Z branch from caac949 to 67bb534 Compare July 27, 2026 14:31
Signed-off-by: Steven Noonan <steven@uplinklabs.net>
@tycho
tycho force-pushed the release/2026-07-27T07-23-33Z branch from 67bb534 to fed5afd Compare July 27, 2026 15:37
Signed-off-by: Steven Noonan <steven@uplinklabs.net>
@tycho
tycho force-pushed the release/2026-07-27T07-23-33Z branch from fed5afd to 63549de Compare July 27, 2026 15:40
Signed-off-by: Steven Noonan <steven@uplinklabs.net>
@tycho
tycho force-pushed the release/2026-07-27T07-23-33Z branch from 63549de to 204d94b Compare July 27, 2026 16:11
tycho added 11 commits July 27, 2026 21:53
…eturns

The registries express parameter/return types as fragments of C
declarator syntax. gloam previously carried them as opaque text, and the
Rust backend translated them by string-munging (counting '*'s, applying
one const to every pointer level). Parse them instead into a TypeRef IR
via the closed declarator grammar (const/struct qualifiers, multi-word
scalar bases, per-level pointer constness, array dims, bitfield widths):

- parse/ctype.rs: tokenizer + parser + grammar unit tests. Anything
  outside the grammar is a hard generation error naming the offending
  declarator, and a corpus test parses every command param/return across
  all bundled XMLs (>10k declarators), so a registry update introducing
  a new construct fails loudly at test time instead of flowing through
  as text a non-C backend would mistranslate.
- resolve: Param.ty / Command.return_ty carry the typed view
  (serde-skipped; the C templates keep rendering raw text, so C output
  is byte-identical — all goldens unchanged).
- generator/rust: print types from TypeRef with per-level pointer
  mutability. This corrects `const T **` parameters (glShaderSourceARB,
  the IBM *PointerListIBM family) from `*const *const T` to
  `*mut *const T`. ABI-identical; the rust golden configs do not select
  those extensions, so rust goldens are also unchanged, and the printer
  behavior is pinned by unit tests instead. Also drops the module doc's
  reference to the removed docs/rust-backend.md.

Deliberately not marked as a generated-API break: the Rust backend is
experimental and the affected signatures were semantically wrong.

Signed-off-by: Steven Noonan <steven@uplinklabs.net>
Picks up the TypeRef-based Rust type printer: `const T **` parameters in
examples/rust/gl-triangle (glShaderSourceARB, the IBM *PointerListIBM
family) correct from `*const *const T` to `*mut *const T`. The C trees
change only in generation stamps.

Signed-off-by: Steven Noonan <steven@uplinklabs.net>
Keep the structured view of every <type> body alongside the assembled C
text, instead of discarding it after synthesis:

- struct/union: per-member records (raw C fragment, XML-declared name,
  TypeRef declarator, values= attribute for sType defaults), built in the
  same walk that synthesizes the C text, so the two views cannot drift
- funcpointer: return + parameter signature, from the structured
  <proto>/<param> format and from old inline-text typedefs alike
- typedefs: one arm per preprocessor branch (GLhandleARB's #ifdef
  __APPLE__ split, the synthesized macOS ptrdiff_t guard), plain
  typedefs as a single unconditional arm — detected by text shape since
  the GL-family registries carry no category attribute
- Vulkan handles: dispatchable vs non-dispatchable

Bodies outside the known shapes degrade to Opaque rather than erroring;
a corpus test pins full structured coverage for every struct/union and
funcpointer across all bundled XMLs, so a registry update that falls
outside the grammar fails with a listing. Spot checks pin the cases
hand-maintained type tables get wrong (GLhandleARB is void* on Apple,
unsigned int elsewhere — the Rust backend's hardcoded table says u32
unconditionally; RT-3 fixes that by printing from these payloads).

resolve::TypeDef carries the payload (serde-skipped): the C templates
still render raw_c verbatim, so C output is byte-identical — all goldens
unchanged, gloam-pregen regen audit clean (stamp-only churn).

Signed-off-by: Steven Noonan <steven@uplinklabs.net>
Replace the Rust backend's hand-maintained BASE_TYPES table with
emission derived from the structured TypePayloads (RT-2): type aliases
print from typedef arms, callbacks from funcpointer signatures, and
forward-declared C structs synthesize deduplicated zero-sized opaque
types. The only hand-written layer left is the ABI scalar map
(khronos_*/fixed-width C spellings -> Rust), which encodes platform-ABI
facts no XML records; an unknown scalar or preprocessor condition is now
a hard generation error instead of a silently wrong hand-copied alias.

Rust output changes (goldens re-blessed, diff reviewed):
- GLhandleARB is now cfg-split: *mut c_void on target_vendor="apple",
  u32 elsewhere — matching gl.xml's #ifdef __APPLE__ arms. The old
  hardcoded u32 was wrong on Apple platforms.
- The macOS ptrdiff_t guard arms collapse to a single isize alias
  (identical Rust mapping), as before.
- Aliases follow registry order; GLDEBUGPROCARB/KHR are full signatures
  instead of aliases (identical types); GLclampx is now emitted (the
  hand table had silently omitted it).

Generated crate verified to compile (cargo check, merged gl+gles2
config). C output untouched — all C goldens byte-identical.

Signed-off-by: Steven Noonan <steven@uplinklabs.net>
Picks up the derived GL base types in examples/rust/gl-triangle:
registry-ordered aliases, the GLhandleARB apple/other cfg split, full
DEBUGPROC signatures, and grouped opaque struct types. The C trees
change only in generation stamps.

Signed-off-by: Steven Noonan <steven@uplinklabs.net>
New generator/rust/vk_types.rs prints the resolved Vulkan type surface
as Rust from the structured payloads and enum groups:

- API constants from flat enums via a closed literal grammar ((~0U),
  (~0ULL), floats, extension NAME strings as &CStr) — unknown forms are
  hard errors
- enum groups: non-bitmask groups become #[repr(transparent)] newtypes
  over i32 with free constants (unknown driver values are data, never
  Rust-enum UB); bitmask *FlagBits groups alias their *Flags carrier so
  constants combine with | and assign to fields exactly as in C. The
  bitmask distinction now flows from <enums type="bitmask"> through
  RawEnumGroup/EnumGroup (was parsed away; C-output-neutral, goldens
  unchanged)
- handles: dispatchable = newtype over *mut c_void, non-dispatchable =
  newtype over u64 (the one shape that is ABI-correct on every target)
- structs/unions: #[repr(C)] from member records; consecutive bitfield
  members merge into a u32 carrier field with shift/mask accessor
  methods (the acceleration-structure instance structs)
- funcpointers as Option<unsafe extern "system" fn>, platform protects
  as #[cfg(feature)] guards, #define aliases as type aliases
- a platform-handle table declares the ABI shape of every WSI type that
  C gets from platform headers (windows.h, Xlib, xcb, wayland, Metal,
  OpenHarmony, NvSci, ...); only referenced names are emitted

Corpus test: every type in bundled vk.xml either emits or names a
StdVideo* dependency (vk_video header types are a documented hard error
until they get structured parsing). Spot checks pin handles, sType
shapes, unions, bitfield packing math, and platform collection.

Signed-off-by: Steven Noonan <steven@uplinklabs.net>
The dependency-following pass collected prerequisite extension names into
a HashSet and pushed them into the selection in its iteration order —
random per process. Selection order determines extArray indices and
(via consumer signatures) command ordering, so any build whose
--extensions list pulls in dependencies (e.g. VK_KHR_acceleration_structure
pulling VK_KHR_maintenance3 and VK_KHR_device_group) generated differently
from run to run, violating the deterministic-output guarantee.

Latent until now: no golden or pregen config selects a dependency-pulling
extension list, which is also why all existing goldens are unchanged by
the fix. Surfaced by the new rust_vk_ext golden flaking between bless and
verify. IndexSet preserves discovery order.

Signed-off-by: Steven Noonan <steven@uplinklabs.net>
Un-gate Spec::Vk in the Rust backend. generator/rust/vk_loader.rs emits
a crate mirroring the C backend's phased Vulkan loading contract:

- initialize(gipa): store vkGetInstanceProcAddr, load Global-scope
  commands (vkCreateInstance, vkEnumerateInstance*)
- load_instance(instance, api_version, enabled_extensions): feature
  flags from the requested version, extension flags from the enabled
  list (XXH3 + binary search against the pre-baked table, identical to
  C detection), Global+Instance-scope loading
- load_physical_device_extensions(...): pre-load Instance-scope queries
  of device extensions before a VkDevice exists (flags untouched)
- load_device(device, physical_device, enabled_extensions): resolve
  vkGetDeviceProcAddr, cap features at the device apiVersion
  (variant-masked), reload all scopes so Device-scope commands get the
  direct-dispatch fast path

Scope-aware loading consults a COMMAND_SCOPES table (the C backend's
kCommandScopes equivalent); null results never clobber loaded slots, so
phases are additive. Dispatch methods reuse the shared emit_method with
a Vulkan type mapper (parameter arrays decay as in C); platform-
protected commands and types carry #[cfg(feature = "VK_USE_PLATFORM_*")]
guards with the features declared in the generated Cargo.toml. A prelude
provides VK_MAKE_API_VERSION/VK_API_VERSION_* as const fns and the
PFN_vkGet*ProcAddr types.

New rust_vk_ext golden pins the full surface (including win32_surface
for the cfg paths); the generated crate compile-checks clean with no
features and with --all-features across a platform-rich extension set.
Vulkan constant grammar extended for (~1U)/(~2U) forms; struct members
named `type` sanitize to `type_`; StdVideo-referencing (video-codec)
extensions are a documented hard error pointing at --extensions.

GL output is untouched (all GL goldens byte-identical); --mx-global on
Vulkan is rejected for now.

Signed-off-by: Steven Noonan <steven@uplinklabs.net>
examples/rust/vk-info: headless smoke test of the gloam_vk crate's
phased loading contract. Bootstraps vkGetInstanceProcAddr via
libloading, then initialize -> CreateInstance -> load_instance ->
CreateDevice -> load_device, proving Device-scope dispatch by obtaining
a queue through the vkGetDeviceProcAddr fast path. Prints instance and
device versions, the loader's capped version, and feature/extension
flags. Exit codes 0/1/77 match the C example conventions.

Verified passing on an RTX 5090 (instance 1.4, device api 1.4): all
version features detected, all five enabled extensions flagged, queue
obtained.

The checked-in gloam/ crate regenerates via cargo xtask regen examples
(now 4 recorded trees).

Signed-off-by: Steven Noonan <steven@uplinklabs.net>
Stamp-only refresh across all four trees after the vk-info example
landed; content is identical.

Signed-off-by: Steven Noonan <steven@uplinklabs.net>
@tycho
tycho force-pushed the release/2026-07-27T07-23-33Z branch from 204d94b to fc638c5 Compare July 28, 2026 04:55
@tycho tycho closed this Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant