13-post thread with @bmcnett. Canonical statement of the mmap log
design: 'printf-debugging is a horrible term; if you're debugger-
free might as well be libc-free.' .log file mapped, first half =
lines of fixed 64-char size (cacheline), second half = single 32-bit
atomic counter for write position. Writing = increment atomic +
dump line. No contention, no file IO, lock-free, captures temporal
ordering across threads. Fixed format:
r|sc.milmic|line_|hex_____|0000000000-|string...
(r=reload, sc.milmic=time since launch, line=source line, hex, dec,
msg). Tlk(__LINE__, n, 'msg') API, no printf needed. Examples show
startup timing (cart mapping 0.005-0.008s) + Vulkan instance 2.4s
with PSO hits at 3K us each. Multi-run log for comparison, Notepad2
F5 to reload. Discussion of fixed line widths in modern era. The
cleanest documentation of the mmap log pattern - 8 months before
the Aug 2025 CART file announcement.
7-post thread. NOTimothyLottes: 'Buffer zoo' is the silly season of
Vulkan shader-side stuff to get what you actually want = instruction
intrinsics; just layout + SSBO aliasing hints at brutal API design.
Dream API: 'Read<32,64,128>(uint64_t base, uint32_t offset, uint32_t
immediate, uint32_t cacheControl, uint32_t format); And be done with
this stupid mess.' Rough edges of TEXEL_BUFFER: 9-bit shared 5-bit E
is read-only on NV, no AMD; sRGB yes NV, no AMD; NV limits to 128M
elements = {512MiB, 1GiB, 2GiB} for {32,64,128}-bit. Third sibling of
the Dec 2024 buffer-zoo cluster.
2-post thread. The real 'buffer zoo' problem with Vulkan: need HW
instruction emulation macros with overcomplete both {offset, index}
inputs so emulation can choose the right path based on whatever
{SSBO, TEXEL_BUFFER, future pointer}. TEXEL_BUFFER for formats one
can't load from SSBOs, both need 'indexes', and whenever IHVs actually
correctly optimize the pointer extension, one needs byte offsets.
'Deadcode removal nightmare land wins today.' Sibling to the
1870351985855119449 STORAGE_TEXEL_BUFFER aliasing thread.
5-post thread with @GustavSterbrant + @AgileJebrim. NOTimothyLottes:
most problems can't be fixed by bypassing GLSL and doing SPIR-V
directly; not yet tempted to write a new shader language. At-home
stuff targets VK Windows mostly (unfortunately) - no interface in AMD's
Windows driver to load binary shaders into VK. 'If SteamOS ever
fully took over PC gaming, then certainly I'd just go direct to the
AMD kernel driver and bypass user-mode VK.' Would write an assembler
specific for GCN/RDNA/whateversNext, not just modify an existing
compiler. Precursor to the Aug 2025 SPIR-V-from-data work.
33-post thread, 13 PNGs, the canonical 'shader dev' walkthrough. Reads
FXAA 3.11 / FSR1 / Unity STP, names the permutations pattern (32-bit /
packed 16-bit / implicit mediump / MIN-MAX sampling). DXIL no bitfield
ops vs SPIR-V (HLSL pre-processing on non-Xbox = fail). 16-bit
perf: don't permute from 32-bit float constants (instant PC perf
death), alias FP16 as UINT32 binary blobs. Designing shaders like
GPU assembly, AMD RDNA2 as the design target. Defines map logic to
associated instruction (fma, bitfieldExtract), all-ints-unsigned
convention with SI1_I1()-style bitcast macros, 3-letter type macros.
Compiler pattern-match bugs: tried always-UINT4 bitcast, didn't
work; native types except waveops. Argument passing SSA state
explosion: inout uint4[16] (all VGPRs) didn't end well - shader langs
support globals, use them. Next level: mostly globals with type-
bitcast aliasing; x86-64 union-of-structs-on-globals as the GPU
calling ABI. Foundation for the SPIR-V-from-data + cart-file work
(Aug 2025).
8-post thread on NV-specific 1-deep swap with IMMEDIATE presentation,
after previous AMD-tuned impl stopped working. One descriptor set
always bound (resources static after init). Dropped
VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT
('god awful naming length') to avoid NV indirection perf hit.
2700 lines of engine, embedded headers, one-file compile. 0.25 sec
hot-load on NV dGPU: 4 MiB 'cart' file from pagecache, 512 MiB GPU
buffer, all PSOs, image alloc, command buffer copy+clear. Load-time
parallelism: {instance create, cart map, TLB warming by walking pages,
window bringup} = 0.08 sec. After VK device, signal background SPIR-V
load while building descriptor set layout, then PSO compile
parallel. Earliest documented use of 'cart file' term - 9 months
before the Aug 2025 public announcement.
7-post debate with @SebAaltonen + @Nerfoxingaround. NOTimothyLottes:
back in the day wrote DOS extender (32-bit mode), Sound Blaster drivers,
VGA interface, UI + audio synth + sequencer/editor, all in assembly,
dead easy - a lot easier than bringing up a triangle in Vulkan.
Nothing complex about ASM with a good macro preprocessor; easier than
HLLs because you know exactly what you get; interrupts and syscalls
are easy. The mess came later when systems forced C ABI library
interfaces with their stacks and junk - then C++ made it worse.
'Pure ASM is easy, its interfacing with the bloat world that got
hard.' Philosophical backbone of his single-file-C / no-debugger
lifestyle.
18-post single-author technical walkthrough, 6 PNGs. Defines streaming
qualifier alphabet (W=writeonly coherent, R=readonly, A=atomics,
E=streaming readonly/exclusive, F=streaming writeonly/final) for
future-compat code even though Vulkan is missing them. Only 32/64/128-
bit type descriptors kept; type aliasing for fast path, explicit
type only when buffer compression might help someday. No 16-bit
<U,S>NORM, no 9E5/sRGB buffer access. AMD buffer atomics get signage
from opcode so UINT32 TEXEL buffer can alias r32ui/r32i. Few hundred
macros for STB access. Continuation of the bind-everything-once
engine cleanup.
10-post thread. 9 of 10 posts are duplicates of posts 2-10 in the
existing merged 1917646466417381426 corpus (same conversation, gallery-
dl anchored to this leaf URL). The unique value here is post 10
(2025-04-30 19:04:57): 'I laugh when people say C is like assembly,
they are missing what we actually did in assembly back then, which
was all registers and globals and gotos, no stacks. It's radically
different than good assembly.' Same content also captured in bootslop
references/X.com - Onat & Lottes Interaction 1.png.ocr.md.
13-post thread with @Karyuuntei. Single-source C includes only __FILE__;
WIN32 + VK headers inlined with structural-type rewrites (64-bit ints
not pointers) to get 'toward C--'. GLSL and C mixed in same file,
sharing defines. One external include for compiled SPIR-V; spirv-opt
as pre-processor (else IHV compilers 10x slower). Dev setup: 2
terminals each with own shell script, one loops regenerating SPIR-V,
other loops recompiling+running. MINGW64 not VS. Mmap log format:
{[restart]|[ms]|[line]|[hex]|[dec]|[comment]}, fixed-size lines,
lock-free (one atomic add), wraps, clear = rm. 0.3ms startup.
55-post thread, HIGHEST engagement NOTimothyLottes thread in corpus
(312 likes, 15 reposts, 20147 views), 1 MP4 video. The canonical
project-announcement thread: 'people claim assembly is hard; a good
counter would be showing how to build a x86-64 WIN32 Vulkan engine
from scratch in ASM.' Posts 2-3 lay out the rationale (game logic
on GPU = no point avoiding asm; re-arch argument-gather for cold-
cache via store multicast + linear prefetch). Post 7+ defend the
WIN32-as-Linux-strategy (Valve/Proton + Wine). Post 22 reveals CRT
setup (low-res, bitmap fonts). Post 50 the punchline: no triangles,
PS-free, CS-only, all gfx generated vintage-PC-style on compute GPUs.
Post 51: VK wins for compute because VkEvents pipelinable vs DX12's
serializing barriers vs GL's lack of pipelining. Post 55: live
systems as 'the IDE' with function keys as save/restore pallet,
snapshot the entire project as one file.
5-post thread. Announcement of next at-home project: build-from-assembly
video series + public-domain 'engine' = live-edit toy for GPU-side
PC game dev. Won't run on Intel iGPUs (binding limits). Memory model is
CART-style (RAM CART buffer = snapshotted + dynamic GPU = not). GPU-
side editing tools for shader source + bind tables, build-the-editors-
in-it, load/store to CART. Sized for what a single person could pull
off, not TBs of team-gen content.
6-post thread. Prefers framebuffer-console boot over graphical
login; converting LottesCode6x12 font to PSF2 for framebuffer terminal
source-editing; wants Vulkan swap bringup without X/Wayland.
@darrellprograms suggests SDL KMSDRM option. NOTimothyLottes:
'zero development effort' is the wrong goal for him - the goal is
to push the state of the art, use SDL source as reference. Tangent:
VT switching + VRAM page-out + exclusive GPU ownership.
6-post thread, 6 images, HIGHEST engagement NOTimothyLottes thread in
corpus (98 likes, 18 reposts, 12960 views). CRT emulation on LCDs can
trigger LCD hardware bugs - Steam Deck example: 2x1 {G,RB} checker
inside a window affects the scan outside the window (Deck scan is
90deg rotated). Theory: 90deg scan gives {(bottom)R, G, B (top)}
sub-pixel components; alternate {G,RB} per pixel for new sub-pixel
pattern at different virtual resolution. Linear-energy-conserving in
theory, breaks down in practice. Tangent post 6 from
@realtimekeith on voltage-inversion crosstalk varying across TN/IPS/VA.
3-post tangent. Same root post as 2061124942968545433 (no-debugger
debug / mmap log file evolving toward CART). @retrotink2 (RetroTink
hardware-modder) replies 'here I am still debugging by looking at
if a single LED turns on'; NOTimothyLottes: 'that plus an
oscilloscope, this is the way'.
3-post thread, 1 image. Links a YouTube video on exploring the
permutation space of color-forth-like systems. @VPCOMPRESSB asks if
the program should optimize its own code at/after init for every
subsequent exec to be hyper-specialized. NOTimothyLottes: yes can do
that, but those systems are already faster than human response time
(without external Linux kernel deps); will be able to recompile all
binary code (including GPU-side) in a tiny fraction of frame time.
3-post thread. Replaces the mmap fixed-size log file with a CART file
mmapped on CPU with mapped GPU access (no file IO) + background page
walker to prevent paging out. Beginning of CART is a grid of 32-bit
unsigned values, hex-dumped as the 'log file' to either term or GPU
render. Same framework for CPU and GPU debug ('write and it just
appears'). Visualized as 4-bit/char hex terminal with hex font.
7-post multi-person thread (NOTimothyLottes / @onatt0 / @EskilSteenberg
/ @olson_dan). On-the-fly SPIR-V generation instead of GLSL: cart file
= 'code+data' restartable package, macro-assembly-style language
where defines are played back interleaved for ILP/loop-unroll, SPIR-V
out direct (no GLSL step). Inspired by C64 SID tracker pattern +
instrument. CPU does the SPIR-V generation from data the GPU can
read/write.
5-post thread. vkGetShaderInfoAMD available on RADV (will be filing
optimization bugs). DEVICE_UNCACHED_BIT_AMD works on RADV for
low-latency CPU/GPU. Header-free Vulkan: VkPhysicalDeviceLimits
replaced with 63 64-bit values (504 bytes) for direct byte offset.
Next: another beam-racing effort on Linux, separate queue for
present-only to fully decouple {dispatch, swap}.
4-post thread, highest-engagement NOTimothyLottes thread in the corpus
(42 likes, 5063 views, 2 reposts). Don't search for the ideal
{presentation,graphics,compute} queue - just use queue 0. AMD: render
via compute on queue 0, present on queue 1, decouple for front-buffer
racing. NVIDIA: queue 1 is DMA, queue 2 is compute; queue 0 = gfx +
present, dispatch on queue 2 by default. Tangent: someone complaining
about the bitmap font in Post 1 looking like a captcha.
6-post thread. Root: commits fully to {if,goto} control flow via
better macros (J_(label) -> goto label; JNzI1_(label,v) ->
if(v!=0) goto label;). Customizes nanorc syntax-highlight to color
them. Tangent: someone suggesting Perl DSL, not invited to the
'better software' conference.
11-post thread. Root: 4-byte overhead interpreter with 64KiB aligned
window of directly-jumpable words (write to ax doesn't change other
48 bits), cuts source size in half. Tangent with @noop_dev covering
cold-cache misses, runtime-macroassembler idea, 4K Atari 2600 emu
precedent. End: GPU code generation for AMD where 8+ bitfields in
an opcode means the simple interpreter won't work.
4-post x86-64 interpreter work: all 0-6 arg syscalls in 32 bytes,
embed interpreter inside words with 3-byte overhead (AD lodsd + FF E0
jmp rax), force lower 32-bit but keep 64-bit, pack interpreted forth
words in aligned 8-bytes. Tangent post 4 from @NOTimothyLottes
self-replying about custom bytecode + on-load decompression.
4 posts, 1 image. Post 1 = the actual content (nasm, ELF64, 4 KiB binary
target, radical Forth, no C baggage). Posts 2-4 = tangent with @furan
about the bitmap font in Post 1's screenshot. gallery-dl pulled the
whole conversation tree.
5-post design walkthrough of a branch-free 8-bit/word color-forth variant
for code generation: ~62 dict entries/page with paging, call/return
inlined by the compiler, branch-free compile + branch-free execution,
lookup-table pre-compile writes unaligned 8-bytes. Intended for tiny
self-contained chunks that include their own codegen. Whitney-esk in
single-char vars, non-Whitney in no higher-order arrays.
3-post companion to 2063733456144597200 + 2076893128515112995: defines
X_ = return, G_ = goto. Moves from C-style {if,while,do,switch,for} to
assembly-style {if,goto} so static branch prediction (backward=taken,
forward=not_taken) is explicit. Plus exit-with-error now properly
drains the background console render thread.
3-post sibling to the 1736161886079533186 VK retrospective: same public-
domain release context, Dec 2023. Covers the mmap-ring-buffer error
logger and the multi-session rationale (crash auto-reload + log
preservation, no debugger).
10-post single-author walkthrough of his old Vulkan pipeline: warm-all-pages
startup, auto-relaunch on crash, single-SPIR-V plus spec-constants, Bind-
Everything-Once, SSBO-as-4-types aliasing, GPU-side game logic, hardware-
style fixed resources. High engagement (36 likes, 3778 views). Closes
with the ruthless-anti-complexity thesis.
6-post single-author walkthrough of the fast-path error-check pattern:
volatile store __LINE__ + error code, TEST, conditional forward branch
to a distant Err() call. Companion to the 2063733456144597200 thread
which established the macro system via the conversation with
@winning_tactic.
Path objects with trailing separators (e.g. './media/') intermittently
failed to glob on Windows after download_media.py had just finished
writing the directory. Normalize via rstrip('/\\\\') before Path()
re-wrapping so the CLI is forgiving regardless of OS path quirks.
Repro: gallery-dl ran + immediate render with trailing slash on the
just-created media/ dir -> glob returned nothing -> markdown emitted
no ![Media N] lines. Removing the trailing slash fixed it; this makes
both work.