a73x

68df7b96

Clarify dirty-row rendering edge cases

a73x   2026-04-08 18:20


diff --git a/docs/superpowers/specs/2026-04-08-dirty-row-rendering-design.md b/docs/superpowers/specs/2026-04-08-dirty-row-rendering-design.md
index ff2cfcb..c058edd 100644
--- a/docs/superpowers/specs/2026-04-08-dirty-row-rendering-design.md
+++ b/docs/superpowers/specs/2026-04-08-dirty-row-rendering-design.md
@@ -82,6 +82,19 @@ Behavior:
- If `layout_dirty == true`, repack all rows and upload the full packed buffer.
- Otherwise, overwrite only the changed row byte ranges and cursor byte range in the GPU instance buffer.

### Dirty-flag lifecycle

Dirty flags are consumed by the renderer cache and must be cleared only after cache state has been brought in sync with the current render state.

Rules:

- Read `term.render_state.dirty` and `row_data.items(.dirty)` immediately after `term.snapshot()`.
- Complete all required row-cache rebuilds, cursor-cache rebuilds, and any repack decisions before clearing flags.
- Clear `term.render_state.dirty` and any consumed row dirty flags only after CPU cache state is updated successfully.
- If a rebuild, repack, atlas insertion, or upload-preparation step fails, do not clear dirty flags for that frame.

This prevents both permanent “always dirty” behavior and lost updates caused by clearing too early.

### No redraw

If terminal state is not dirty and no window/swapchain event forces a frame, skip both cache work and draw submission.
@@ -99,6 +112,12 @@ Behavior:
- Copy the provided slice into the instance buffer at `offset_instances * @sizeOf(Instance)`.
- Unmap memory.

Important fallback rule:

- If capacity growth is required, `uploadInstanceRange` must not attempt to preserve prior GPU contents implicitly.
- Buffer growth forces `layout_dirty = true`, followed by full repack and a full-buffer upload from `packed_instances`.
- Partial range uploads are only valid when the underlying GPU buffer remains allocated and existing offsets stay valid.

Keep `uploadInstances` for full-buffer writes.

No pipeline or draw-call structure changes are required.
@@ -150,6 +169,9 @@ Add tests before implementation for:
- Layout remains stable when a rebuilt row keeps the same instance count.
- Layout becomes dirty when a rebuilt row changes instance count.
- Packing offsets remain contiguous after full repack.
- Cursor-only updates rebuild cursor cache without requiring unrelated row rebuilds.
- Instance-buffer growth during a partial update forces full repack/full upload fallback.
- Dirty flags are cleared only after cache refresh planning succeeds.

Verification after implementation: