# Phase 0 — substrate for iter6 Opened **2026-05-19** after [iter5 close GREEN](phase8_iteration5_close.md). ## Locked research question — iter6 > **Render a depth-tested scene into a 128×128 RGBA8 color attachment + 128×128 D32_SFLOAT depth attachment via dynamic rendering:** > > - **Triangle A (red):** large, NDC (-0.8,-0.8), (0.8,-0.8), (0.0,0.8), all with z=0.7 > - **Triangle B (green):** small, NDC (-0.4,-0.4), (0.4,-0.4), (0.0,0.4), all with z=0.3 — fully geometrically inside Triangle A > - Draw A first, then B. Depth test enabled (`VK_COMPARE_OP_LESS`). > - Triangle B's lower z should make it appear in front of A wherever they overlap. > > **Verify specific pixels:** > 1. `(0, 0)` — clear (outside both, top-left corner) > 2. `(127, 127)` — clear (outside both, bottom-right corner) > 3. `(64, 64)` — inside both, GREEN (B in front) > 4. `(64, 30)` — inside A only (above B's reach in pixel-y), RED > 5. `(64, 100)` — inside A only (below B's reach), RED ## Why this shape iter5 closed all single-draw, no-depth, descriptor-binding paths. iter6 adds: - **Depth/stencil attachment** (D32_SFLOAT) — new image format, new aspect, new usage flag (DEPTH_STENCIL_ATTACHMENT) - **Depth test + depth write** in pipeline state (`VkPipelineDepthStencilStateCreateInfo`) - **Multi-draw within one render pass** — two `vkCmdDraw` calls between begin/end - **z-coordinate handling** in the vertex shader (gl_Position.z affects depth) - **128×128 image** instead of 64×64 (more tiles — 8×8 grid of 16×16 = 64 tiles) - **Depth attachment format** in `VkPipelineRenderingCreateInfoKHR.depthAttachmentFormat` - **Depth attachment** in `VkRenderingInfoKHR.pDepthAttachment` ## Hypothesis space 1. **D32_SFLOAT depth format on Bifrost.** Bifrost packs depth into tiles; the layout differs from color. First time we use a non-color attachment. 2. **Depth-stencil image creation + layout (`DEPTH_STENCIL_ATTACHMENT_OPTIMAL`).** New layout never used. 3. **Depth test plumbing.** PanVk-Bifrost's path from `VkPipelineDepthStencilStateCreateInfo` → tile descriptor depth-state fields. 4. **Depth write back to depth attachment.** Mali stores depth in tile memory then flushes; per-tile flush + cache invalidation. 5. **Multi-draw within one render pass.** Bifrost's binner may have bugs handling N>1 jobs per render pass — particularly around per-draw state changes. 6. **z-coordinate from vertex shader.** Vertex output position.z passes through to rasterizer. 7. **Tile binning at 128×128** (64 tiles vs. iter3's 16). More potential for binner state bugs. ## In-scope (LOCKED 2026-05-19 for iter6) - 128×128 RGBA8 color + 128×128 D32_SFLOAT depth attachment. - 6 vertices (2 triangles) in one vertex buffer, vec3 pos + vec3 color. - Depth test enabled, depth write enabled, compare LESS. - Two `vkCmdDraw(3, 1, *, 0)` calls within one render pass. - 5-point pixel-level verification. ## Out-of-scope (LOCKED 2026-05-19 for iter6) - Stencil (D32_SFLOAT has no stencil aspect anyway). - D24_UNORM_S8_UINT or other depth formats (iter would explore if iter6 fails). - Depth clear via load-op only (no separate clear-image). - Front-face culling, polygon-mode lines. - Indexed draws. - More than 2 triangles. - WSI / surface — still off-screen attachment + buffer readback. ## Reference - Prior closes: [iter1](phase8_iteration1_close.md) — [iter5](phase8_iteration5_close.md).