Legacy texture-operation capability correction — 2026-10-23
Demonstrated defect on exact input 5406777ecbcef9cf9b03b40d592d722bb0086de0:
d3dim_fill_device_desc7 advertised 0x003FF at offset 180, claiming ten
texture operations. Both legacy routes implement SELECTARG1, SELECTARG2 and
MODULATE, while the other advertised operations silently modulate. Correct the
mask to 0x0000E. This changes one production constant and its explanation;
no new combiner operations or other capability fields are implemented.
The Microsoft-owned legacy d3dcaps.h defines these capability bits in operation order. Its D3DPRIMCAPS and D3DDEVICEDESC7 declarations establish the 236-byte structure, texture-operation DWORD at 180, and stage-limit WORDs at 184/186. Microsoft's operation documentation defines the corresponding behavior; the legacy extended-capability documentation confirms that each capability asserts operation support. Checked 2026-10-23. The older sized D3DDEVICEDESC writer has no texture-operation store and is unchanged. This is not the D3DPRIMCAPS texture-blend mask.
DISABLE was checked separately. Setting COLOROP=1 does not unbind the texture:
the actual setter stores it, d3dim_bound_texture_entry still resolves it,
both software outer triangle dispatches reach the textured raster sink with
operation 1 unchanged, and the actual GPU descriptor/lowering retains an active
texture and emits MODULATE. The software inner combiner also modulates. Thus
the DISABLE bit is removed on direct outer-path evidence. An alpha-only DISABLE
with color enabled is undefined in the documented API; no support claim is
inferred from that case.
The distinguishing operands are texture 0xA0C08040 and diffuse 0x8060A0E0.
All seven removed operations produce 0x50485038 (red 72), with the GPU lowering
emitting operation 4 for both color and alpha:
| Removed operation | Bit | Required red before quantization/clamping |
|---|---|---|
| DISABLE | 0x001 | 96 (diffuse; no stage-0 texture mapping) |
| MODULATE2X | 0x010 | 144.565 |
| MODULATE4X | 0x020 | 255 (clamped) |
| ADD | 0x040 | 255 (clamped) |
| ADDSIGNED | 0x080 | 160.5 |
| ADDSIGNED2X | 0x100 | 255 (clamped) |
| SUBTRACT | 0x200 | 96 |
The retained bits are SELECTARG1=0x2, SELECTARG2=0x4, MODULATE=0x8. Nine independent RGB/alpha combinations execute the actual production combiner and actual legacy GPU lowering, checking both operations and TEXTURE/DIFFUSE arguments. Reversed operands, white identity and zero inputs also execute the software combiner. Both software outer dispatches are exercised. The GPU draw uses the actual WAT descriptor and JS lowering; allocation, texture upload and submission are explicit fixture doubles. Software raster submission is an explicit recording sink, not a substituted combiner.
Run from this checkout:
node --max-old-space-size=256 test/test-legacy-texture-operation-caps.js --negative-controls
node --max-old-space-size=256 test/test-d3dim-gpu-batching.js
node --max-old-space-size=256 test/test-d3dim-gpu-points.js
All three pass. The exact baseline runs the same distinguishing behavior and fails specifically at the executed capability writer assertion. Three capability mutations (restore DISABLE, restore MODULATE2X, drop MODULATE), a software SELECTARG1 operand mutation and a GPU SELECTARG lowering mutation are rejected. The complete 236-byte baseline/candidate descriptors differ only at bytes 180/181, with masks 1023/14; all 232 bytes outside that DWORD are identical.
Evidence is adjacent in legacy-texture-operation-caps-20261023/:
baseline-results.json, candidate-results.json, descriptor-comparison.json,
both *-excerpt-manifest.json files and seals.json. The manifests bind every
compiler path to exact Git blob, full-file SHA-256 and size, and each production
form to byte offsets, line ranges, byte count and hash. The extraction recipe
keeps forms verbatim and wraps them with explicit fixture imports/globals and
exports. WATX consumes top-level forms. The final assembled source is 32,939
bytes, SHA-256 f05616f67b30f52efec42aeeeb17f66278af5a59790d9e3045cada42d3c4d48a;
each compiled variant is 4,380 bytes with one 64 KiB memory page. No full-source
compilation or 512 MiB native guest occurs. Compiler identity and byte-exact
excerpt checks pass before acceptance compilation.
The first focused manifest measured 16 files/1,330,408 bytes. Adding the actual
fill_primcaps dependency required a revised measured selection of 17 files/
2,388,036 bytes before that additional checkout. The complete closure includes
the GPU's transitive local imports and all four authentic compiler stages.
The shared clone was --no-checkout, with explicit non-cone file patterns
installed before checkout. The donor and installed tools remain standing,
read-only inputs. Installed Node is v24.18.1 at
/home/user/.nvm/versions/node/v24.18.1/bin/node, 123,656,816 bytes, SHA-256
f3432a45b03b2da0d270095fdd8813dc34cbea73f5fc8b18c7a384b7cf9b333a.
Resource evidence includes first-admission.json, complete-admission.json,
expanded-admission.json, resource-before-publication.json,
prelaunch-baseline.json, direct-capture-allowance.json, and the executable
guard/recovery recipes. The pre-publication projection is 36,334,951 of
67,108,864 NEW bytes, including an 8 MiB private peak, at least 16 MiB future
external growth and 8 MiB reserve; projected host free is 4,479,762,246 bytes.
Standing SQLite is excluded, while every sampled positive SQLite/WAL/SHM growth
is charged cumulatively without shrink credit. Task outputs/session events,
Git/index, copied evidence, guard, and an 8 KiB conservative baseline/board
allowance are charged. The final live receipt remains in
/tmp/legacy-texture-operation-caps-oct23/final-resource.json after publication.
All substantive commands retain streaming capture, per-file 24 MiB, process
ownership and cleanup checks. Node uses a 256 MiB heap, 60-second CPU/wall and
fresh MemAvailable >=805,306,368; Python uses a 60-second wall. The actual
32-byte capture rejection control terminated its child, left the sentinel
absent and verified owned-group cleanup. Direct instruction/source/web reads
and receipt reprints have a conservative cumulative 327,680-byte charge, in
addition to actual guarded child output; the combined limit is 524,288 bytes.
No substantive resource-denial retry occurred. The explicit 2 MB selection
estimate failed before the extra checkout; its replacement was an exact
measured closure within unchanged resource limits. Routine fixture corrections
included missing import signatures, WATX API/result shape, a baseline excerpt
path and mutation-receipt preservation. execution.jsonl records all actual
guarded argv/exits and bounded output; unguarded-bootstrap-attempts.json
records the initial missing Python alias and inspection-helper name collision.
The evidence snapshot has 64 guarded commands, 12 nonzero exits (including
intentional rejection controls/baselines and corrected fixture failures), all
with verified cleanup. Later validation/publication commands are retained in
the live execution log rather than recursively copying that log into itself.
Qualification is limited to source and small fixtures: actual capability writer, combiner, selected outer dispatch, descriptor and legacy GPU lowering. This is not full COM, native guest, real WebGL pixel, gameplay, or full-build acceptance. No runtime access, package installation/download, public deployment, shared integration, main merge, worker launch or donor/root tracked-file/index/ref mutation was performed. Original native qualification checkout, fixture09dc, memory watcher, Shadow Man approval hold and runtime403 holds remain preserved. No box is assigned (ID/state/expiry N/A); coordinator retains lifecycle ownership.
Publication is only task/legacy-texture-operation-caps-oct23, using strict
trusted SSH and no force. Final commit/actual remote SHA are recorded in
/tmp/legacy-texture-operation-caps-oct23/publication.json and the root append-only
messageboard. No integration is requested by this worker; coordinator decides
independent acceptance and integration.