fix(#40): textured render probe + first-failure diagnostic capture in RenderSanity#570
Merged
Merged
Conversation
RenderSanity's probe was 2D-only, so it false-passes the exact issue #40 symptom: 2D primitives blit fine while the textured world comes up blank under the dgVoodoo->ReShade swapchain race. On a real hit it only bumped a retry counter, capturing no root-cause data. Two additive, low-risk changes (existing 2D probe + retry/counter flow left intact): 1. Textured-render check (RenderSanityTextureProbe). Builds a throwaway scene -- one camera, one full-bright sprite textured with a known-green CreateTexture -- RenderWorlds it to the backbuffer (no Flip, never user-visible), then ReadPixels the screen centre and asserts the texel came back GREEN. An untextured sprite shows the white brush colour or the black clear; the green-specific assert rejects both, catching the "world renders but textures are dead" case a 2D probe cannot. All temp entities/texture are freed; soft-fails (never RuntimeErrors). RenderSanityProbe now requires BOTH 2D and textured checks to pass. 2. First-failure diagnostic artifact (RenderSanityWriteDiagnostic). On the first detected probe failure of a session, BEFORE the curative EndGraphics+Graphics3D re-init perturbs device state, writes a one-shot Data\Logs\gfxprobe_diag.txt (atomic via SafeWriteOpen/SafeWriteCommit). Dumps timestamp, uptime, GFXPROBE env, requested vs actual mode, TotalVidMem/AvailVidMem, the gfx driver name(s), the measured 2D and textured readback pixels, the retry attempt index, and dgVoodoo/ReShade wrapper-DLL presence next to the exe. Guarded by a session flag so a flapping probe can't spam files. This adds a Logging.bb dependency (for the atomic-write helpers). Include is include-once, so Server/Client/GUE/Loom dedupe it; Project Manager -- which reaches this file via RCCEGraphics -- gains it. Logging.bb is non-Strict and resolves MainLog to an implicit 0 when no Global MainLog exists (GUE already relies on this), so no target needs a MainLog declaration. Full compile.bat (all 5 engine targets + 7 tools) is clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Instruments the render-health probe (
RenderSanity.bb) for release-blocker #40 ("world boots with no textures", suspected dgVoodoo→ReShade cold-start swapchain race). Two additive changes:RenderWorld: a green 32×32 texture on a full-bright sprite, rendered to the backbuffer (noFlip, never user-visible), thenReadPixela 5×5 center cluster and assert the texel is green (g>100 And r<100 And b<100). A 2D-only probe false-passes Randomly the Client (and possibly GUE and Server) will run with no textures #40's exact signature (2D primitives render while textures are blank); this catches it. All created entities (camera/sprite/texture) are freed on every path and prior buffer +ClsColorare restored.EndGraphics+Graphics3D, atomically writes (once per session)Data\Logs\gfxprobe_diag.txtwith timestamp, uptime, retry attempt, requested-vs-actualGraphicsWidth/Height/Depth,Total/AvailVidMem, allGfxDriverName$, the measured 2D + textured readback pixels, and dgVoodoo/ReShade wrapper presence next to the exe. Turns a real hit into root-cause data instead of just a counter bump.Two flags (surfaced for maintainer awareness — this is your release-blocker code)
RenderWorldon the boot frame, exercising the 3D/swapchain path Randomly the Client (and possibly GUE and Server) will run with no textures #40 is suspected to live in. Independent verifier judged this acceptable: it neverFlips, leaks nothing, restores state, and is far less invasive than theEndGraphics+Graphics3Ddevice teardown/rebuild it already sits in front of. If you'd prefer it gated to re-init attempts only, that's a one-line change — but that would stop it catching the first-boot symptom, which is the point.Logging.bbdependency. The module header advertised "builtins only"; using the atomic-write helpers addedInclude "Modules\Logging.bb", which also pulls Logging into Project Manager. Verified include-once-safe; Project Manager builds clean.Verification
RenderSanity.bb, +226/-16), UTF-8 no BOM, fully soft-fail (noRuntimeError/Throw, all creates null-checked,ReadPixelclusters in-bounds, once-per-session guard effective). TracedSafeWriteCommit(…,0)againstLogging.bb: caller closes the handle,0skips the helper's double-close and still runs the full atomic.bak-demote + promote.compile.bat(not-t) exits 0 — all 5 engine targets + 7 tools, including Project Manager.Test plan
Data\Logs\gfxprobe_diag.txtis written with the listed fields before any re-init.