diff --git a/dm/gfx/nvn/nvn_mtl.m b/dm/gfx/nvn/nvn_mtl.m index b471fee..77eba31 100644 --- a/dm/gfx/nvn/nvn_mtl.m +++ b/dm/gfx/nvn/nvn_mtl.m @@ -8088,6 +8088,11 @@ static int present_now(const tex_t *t, double period, uint64_t frame, uint64_t t PD("X ser=%llu", t->serial); id src = tex_mtl(t); if (!src) { RED_ONCE(8, "present texture could not get an MTLTexture"); return 0; } + // A texture made on first resolution joins the residency set (res_add), which a submission commits; a window texture presented before any submission has used it was still + // outside the committed set when the display command buffer sampled it. Super Smash Bros. Ultimate presents its window texture in its first frames before drawing into it: + // the display queue page-faulted (kIOGPUCommandBufferCallbackErrorPageFault) and macOS then ignored every later command buffer of the process, so the window stayed pink + // (headless runs never present, and every game before drew into a window texture before presenting it). A commit with nothing new costs nothing + res_commit(); // DM_NVN_REGLUM=x0,y0,x1,y1:file (normalized coordinates): read back this region on every present and record "present sequence number, present time ns, region mean luminance, subsampled grayscale thumbnail (hex)" (diagnostic: verify that animation speed is independent of frame rate). // A separate command buffer is queued after this frame's rendering (the same queue executes in submit order); does not wait for the GPU and does not disturb frame pacing static int rl = -1; static float rr[4]; static FILE *rlf; static pthread_mutex_t rlmu = PTHREAD_MUTEX_INITIALIZER; diff --git a/docs/agents/04-graphics.md b/docs/agents/04-graphics.md index 0663143..a806be6 100644 --- a/docs/agents/04-graphics.md +++ b/docs/agents/04-graphics.md @@ -439,3 +439,6 @@ Next Level Games' deferred renderer on SDK 7.3.2 (NVN 53): the scene draws into - **A depth texture drawn through a colour view** (the boot aborted in Metal's pipeline validation: `MTLPixelFormatDepth16Unorm is not color renderable`): a 1024×1024 D16 texture drawn through an R16 view. Metal has no colour view of a depth texture, so such a pass draws into a colour shadow of the same pixel size, copied in before and back after the pass through a buffer, as a compressed render target is (`shrt_block`; D16 and D32F, whose Metal pixel is the NVN pixel; not D24S8). - **Post-process passes with stale texture handles**: the game patches handles into recorded commands ([03](03-bringup.md)). - **Not done:** the tessellation stages (15 hull, 18 domain shaders; `primitive type 14 not implemented`, their patch draws are skipped) and 10 geometry shaders (one expands a box from two corners). Neither is drawn much. Two tessellated programs (vertex `28a39709d0adfcfa` / hull `51d2d156bb12c260` / domain `0b95742e863bec50`, and `d4d89931b5a9a514` / `8aa6feeb7d33e9f6` / `f254b4dce2d6c012`) draw twice a frame for about 30 frames, in the title scene behind the file select as it slides out before a new game. No draw used a geometry shader from the title through the opening cutscene to the lobby. A program whose geometry shader has no library used to draw silently without that stage, with the vertex shader's positions taken as clip coordinates; `draw with geometry shader … which has no library` now names it. SPIRV-Cross already writes the hull shaders as kernels and the domain shaders as post-tessellation vertex functions, but Metal 4's render encoder and pipelines have no tessellation (no `drawPatches`, no factor buffer), so the draws would need a tessellator in a compute kernel and domain shaders rewritten as plain vertex functions. The hull kernels also write quad factors (`MTLQuadTessellationFactorsHalf`) for triangle patches. The vertex shaders that feed a hull or geometry shader can be found from the shader headers (SPH): the generic attribute map at +0x18 of the consumer's header (inputs) equals the one at +0x36 of the vertex shader's (outputs). In LM3, 40 vertex shaders match a hull shader and 49 a geometry shader. A few pixel shaders declare a 3D texture in a slot the game fills with a 32×32 2D texture (`texture type mismatch`), on paths not seen taken. + +### Seen in Super Smash Bros. Ultimate +- **A pink window, every command buffer ignored, while headless runs looked right** (13.0.5, `DM_WINDOW=1`): the first presents failed on the display command buffer with `kIOGPUCommandBufferCallbackErrorPageFault`, and after a few of those macOS ignored every submission of the process ("Ignored (for causing prior/excessive GPU errors)"). The game presents its window texture in its first frames before drawing into it; the texture was made on that first resolution in the present path and added to the residency set (`res_add`), but only a submission commits the set, so the display command buffer sampled a texture outside the committed set. `present_now` now commits the residency set after resolving the presented texture (`res_commit`, free when nothing changed), for every game. Headless runs never present, which is why they looked right; Breath of the Wild windowed with the change: its title, 60 fps, no GPU error.