From 79ee2361addcb5f7851edd7c41f35ed69dba8d59 Mon Sep 17 00:00:00 2001 From: Erik Date: Mon, 27 Jul 2026 19:41:08 +0200 Subject: [PATCH] docs(render): close Campaign V slice V4a and file #249 V4a landed on the second attempt at 096dd203, verified independently: offline pixel gate passing at 22 differing pixels against an 8-26 same-commit noise band, App suite at exactly the 3,843/3 baseline, 26 files touched, no encoding damage. Three audits of the reverted first attempt found defects that outlive it - resident bindless handles never released, no test coverage for the Multisample state dimension, and no encoding guard - now tracked as #249. Co-Authored-By: Claude Fable 5 --- docs/ISSUES.md | 39 ++++++++++++++++++++++++ docs/plans/2026-07-27-vulkan-campaign.md | 15 +++++++++ 2 files changed, 54 insertions(+) diff --git a/docs/ISSUES.md b/docs/ISSUES.md index 2bf4cc74..2a59ed93 100644 --- a/docs/ISSUES.md +++ b/docs/ISSUES.md @@ -97,6 +97,45 @@ Copy this block when adding a new issue: --- +## #249 — Bindless handles stay resident after their table slot is released + +**Status:** OPEN +**Severity:** MEDIUM +**Filed:** 2026-07-27 +**Component:** rendering / GPU resource lifetime + +**Description:** `GlGpuDevice.ReleaseTextureSlot` zeroes the table entry and +returns the index to the free list, but never calls +`BindlessSupport.MakeNonResident`. Two consequences: + +1. Callers go on to `glDeleteTexture` a texture whose bindless handle is still + resident, which `GL_ARB_bindless_texture` leaves undefined. Six other caches in + the tree (`TextureCache`, `CompositeTextureArrayCache`, + `StandaloneBindlessTextureCache`, `TerrainAtlas`) do call `MakeNonResident` + first, so the omission is inconsistent as well as unsafe. +2. Every released slot leaks a resident handle for the process lifetime, even + though the index itself is recycled. + +**Provenance:** found by the Campaign V slice V4a audits. Introduced in V1 +(`4f94ad7d`), not in either V4a attempt; present on the current tree. + +**Also in scope for this issue** (same audits, same class of "no gate would have +caught it"): +- No test covers the `Multisample` dimension of `GlRenderStateCache`. Mistyping + that comparison would leave the whole suite green — that is exactly the + regression that forced the V4a revert (`9aaf97e7`). Add a positive test plus + `Assert.False(changes.Multisample)` in the existing negative cases. +- Add an encoding guard: an `.editorconfig` with `charset = utf-8` and a + `.gitattributes` text rule, plus a check that rejects newly introduced BOMs or + mojibake. The first V4a attempt re-encoded 259 files and corrupted non-ASCII + characters in 116 of them, and no existing gate noticed. + +**Acceptance:** released slots make their handle non-resident before the texture +is deleted; a test proves the `Multisample` dimension is diffed; an encoding +guard fails on a reintroduced BOM. + +--- + ## #248 — FrustumCuller extracts the near plane with the GL-convention formula **Status:** OPEN diff --git a/docs/plans/2026-07-27-vulkan-campaign.md b/docs/plans/2026-07-27-vulkan-campaign.md index d728c5fc..f53a4e70 100644 --- a/docs/plans/2026-07-27-vulkan-campaign.md +++ b/docs/plans/2026-07-27-vulkan-campaign.md @@ -616,6 +616,21 @@ forces revert of good work along with bad. Do not change type visibility, do not delete or weaken tests, and do not refactor adjacent code. If the slice genuinely cannot land without one of those, stop and report instead. +**Outstanding hardening from the V4a audits.** Three independent audits of the +reverted attempt found defects that outlive it and are tracked as `#249`: + +1. `GlGpuDevice.ReleaseTextureSlot` frees the table index but never calls + `BindlessSupport.MakeNonResident`. Deleting a texture whose handle is still + resident is undefined under `GL_ARB_bindless_texture`, and every released slot + leaks a resident handle for the process lifetime. This is V1 code, present on + the current tree. +2. No test covers the `Multisample` render-state dimension. Mistyping the + comparison in `GlRenderStateCache` would leave the whole suite green — the + very regression that reverted V4a. +3. There is no `.editorconfig` `charset` rule and no `.gitattributes` text rule. + The first attempt silently re-encoded 259 files and corrupted non-ASCII text in + 116 of them, and **no gate noticed**. + **Pre-approved transitional seam.** The retained UI draws the paperdoll and appraisal viewport textures, which are produced by renderers that stay raw GL until V4g. The GL backend may therefore expose a documented way to register an