ludic migrate state packages <every example program> packages/ludic.lab/example/plate.ludic
1804 vars into 126 states, 64 into lets; 23498 edits in 460 files
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The typed buffers are slices: words/floats/fixeds/doubles/pointers(n) make
zeroed, bounds-checked []int/[]float/... and the type names mean them. buffer(n)
is a []byte, with text_of, Fs.read_bytes/write_bytes and view(xs, start, n).
bytes(), indexing a raw pointer or bytes, free, resize, Memory.*, raw file calls,
data_of and C externs are refused outside unsafe { } / unsafe function, and a
project's own files may write unsafe only with --unsafe; the runtime and packages
are the platform. A slice passed to an extern goes as its data.
What the change found: Sync's atomics on a slice header, words(n) uninitialised,
input's fixed axes in ints, truetype's fixed outlines as ints, skin matrices
typed int, gl_shader's source table made from raw bytes. render3d gets safe
entry points (safe_api.ludic). Rendering is byte-identical; a frame costs the same.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Three things the first Vulkan frames on the RTX 3070 Ti showed against OpenGL on the same PC:
- Exposure: the adaptation pass reads the HDR scene's smallest mip, and a render target made
without pixels had one level, so exposure came from a single texel. A target asked for mipmaps
now grows a full chain (level 0 kept), and passes draw through level-0 views keyed by the
image's generation.
- Foliage: the depth prepass and the lit pass (depth EQUAL) are different variants. Vulkan vertex
stages now declare an invariant gl_Position so both land on the same depth.
- Alpha to coverage is enabled only on a multisampled pass. OpenGL ignores it without MSAA; Vulkan
with one sample dropped every fragment under half alpha.
vk_resources also checks a big-endian 16-bit RGB upload (a normal map). VKRES OK; ludic-dev test
140 passed; the PC's Vulkan frame is validation-clean; OpenGL frames byte-identical at the five
viewpoints with 59 self-tests passing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gpu_vk_res.ludic gains what gpu.ludic's texture and buffer handles stand for on Vulkan:
- gvk_tex_storage / _upload / _mips / _read / _release: an image and view per handle, a full mip
chain when pixels come with it (the renderer asks for mipmaps after the upload) and one level
for a target, every level in SHADER_READ_ONLY between uses. Uploads are converted to what the
image stores: a missing alpha filled opaque (three-channel formats are stored with four), 16-bit
PNG samples byte-swapped when the unpack state says so, 32-bit float HDR halved into half
floats. Mips are blitted down level by level; a read-back brings level 0 home.
- gvk_sampler: one VkSampler per filter / wrap / compare / anisotropy combination, made when first
asked for, with GL's defaults where the renderer set nothing.
- gvk_buf_*: vertex, index and instance buffers behind one handle, kept when an upload fits.
Host-visible while the backend comes up.
gpu_vk.ludic switches on anisotropic sampling where the device has it and reads its limit.
examples/rendering/vk_resources.ludic checks it all: VKRES OK, validation-clean, every allocation
freed, on the RTX 3070 Ti (16x anisotropy) and on MoltenVK. One run on the Mac crashed while a
headless game run was using the GPU and did not come back in two reruns. OpenGL frames
byte-identical at the five viewpoints; 59 self-tests pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>