Skip to content

ASTRO BOT startup: 2D image load/store bound to one-pixel 1D textures #9

Open

Description

@p3n1cillin

ASTRO BOT (PPSA21564 v01.007.000) currently stops before the first completed presentation interval on the Windows integration build. A private failed-request capture reproduces the error offline on upstream main d70b89989473ba1f6ae13e44e079e67f1f8a44b0 with the diagnostics from #8:

image descriptor is incompatible with the static runtime image interface:
source=1 firstUsePc=48 instructionDim=3 class=1 read=1 written=0
descriptorDim=1 numeric=1 conversion=0 packed=0 cube=0
depthBits=0 unorm16=0 srgb=0 emulated=0 fmask=0

PC 48 is 0x30. This is an image_load encoded with DIM 2D, zero x/y coordinates, and a non-null one-pixel 1D RGBA32_FLOAT T#. A subsequent store through the same descriptor is represented as a separate storage interface. There is another one-pixel 1D descriptor used by another load. This is not a deferred-null-pointer failure.

Current integration includes the upstream deferred SRT faults from boykopovar#759 and deferred descriptor capture from boykopovar#1292. The last game run produced no completed presentation intervals; no gameplay, FPS or rendering-success claim follows from this report. No additional game run was performed during the offline investigation.

Independent homebrew reproduction

The tests in #8 contain hand-written eight-word load and nine-word store shaders, not extracted game code. They use one-pixel R32_FLOAT and RGBA32_FLOAT descriptors. Offline replays of 12 combinations on Windows 11 / GCC 15.2 / SPIRV-Tools disabled:

Instruction / T# Loads Stores
DIM 2D / 2D compile compile
DIM 1D / 1D compile compile
DIM 2D / 1D unsupported-interface error unsupported-interface error

Both formats give the same classification. These are compilation results, not GPU execution or RDNA2 measurements.

The following script writes two independent RGBA32_FLOAT mismatch requests for agc_shader_replay. They contain only the homebrew instructions, fictional addresses, and compiler settings. They contain no game shader, data, SRT or memory regions. Do not dispatch these fictional addresses; use the offline replay tool.

from pathlib import Path
Path("line_load.req").write_text("NVNQQQ0AAAAAALAFAAAAAAAIAAAAAAAAAIACBH6AAgZ+CA8A8AIEAQBwP4y/AAB84AAEAIAAAIG/AAAAAAAAAAAAAAAAAAAAACAAAAAAAAAADAAAAAAAAAAAACAAAAAAAAABAACsbwExABAAAAAA0AQAAAAArA8AgAAAAAAAAAAAAAAAAAAAAAABAQAAAAEAAAABAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAEEAAAAMBACAAAAABAAAABgAAAAAAAAABAAAAKwAAACwAAAALAAAA4xQAAGARAAACAAAAAAAAAB8AAAAAAAAAU1BWX0tIUl9waHlzaWNhbF9zdG9yYWdlX2J1ZmZlchQAAAAAAAAAU1BWX0tIUl84Yml0X3N0b3JhZ2UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", encoding="ascii")
Path("line_store.req").write_text("NVNQQQ0AAAAAALAFAAAAAAAJAAAAAAAAAIACBH6AAgZ+gQIIfoICCn6DAgx+hAIOfggPIPACBAEAAACBvwAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAwAAAAAAAAAAAAgAAAAAAAAAQAArG8BMQAQAAAAANAEAAAAAKwPAIAAAAAAAAAAAAAAAAAAAAAAAQEAAAABAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAABBAAAADAQAgAAAAAQAAAAYAAAAAAAAAAQAAACsAAAAsAAAACwAAAOMUAABgEQAAAgAAAAAAAAAfAAAAAAAAAFNQVl9LSFJfcGh5c2ljYWxfc3RvcmFnZV9idWZmZXIUAAAAAAAAAFNQVl9LSFJfOGJpdF9zdG9yYWdlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", encoding="ascii")

Replay each file with agc_shader_replay line_load.req and agc_shader_replay line_store.req. Both exit 1. With #8 the diagnostic identifies load PC 8 / class Sampled / read=1 and store PC 24 / class Storage / written=1, descriptor Dim1D versus instruction Dim2D. The executable is built by the CMake target agc_shader_replay.

Compatibility work still needed

The measured 3D-instruction / 2D-T# work in boykopovar#2133 and boykopovar#2140 does not establish 2D-instruction / 1D-T# loads or stores. The color-target layout work in boykopovar#2095 addresses rendering into color targets rather than these MIMG interfaces. No broad lower-dimension fallback has been reintroduced.

Before implementing a mode, measure the load and store separately on RDNA2 with the upstream hardware oracle: matching-DIM controls, one-pixel and wider 1D descriptors, x=0/in-range/out-of-range, y=0/1/negative, R32_FLOAT and RGBA32_FLOAT, and mip variants if supported. Nonzero discarded coordinates must not be assumed equivalent to zero. A storage implementation also needs compatible image views and texture writeback coverage.

The Windows host enumerates the RTX 5070 and AMD integrated graphics, but no Linux HSA/oracle environment is available here. No native ISA measurement was performed. Shader instruction coverage at 100% does not establish these descriptor/instruction combinations.

AI-assisted investigation and homebrew: Codex. Raw game captures, memory and code remain private.

Activity

  1. p3n1cillin commented on Oct 9, 2026

    @p3n1cillin
    OwnerAuthor

    Native measurements are now available, superseding the earlier note that this host had no usable native AMD execution environment.

    Windows 11; integrated AMD Radeon(TM) Graphics, gfx1036 (RDNA2), driver 32.0.21042.62; installed HIP 5.7 (runtime 50732000) and COMGR API 2.5. Independent AMDGCN assembly was assembled and linked through COMGR, then executed through HIP. No game shader or game data was used in these probes. An integer-add control passed before image probes.

    Using tools/hw-oracle/template.s, wave64, IEEE=0, DX10_CLAMP=1, DENORM32=0, DENORM16=3, ROUND32/16=0 and FP16_OVERFLOW=0:

    • 16 groups / 144 load and store cases passed comparison against the measured model: R32_FLOAT (format 22) and RGBA32_FLOAT (format 77); widths 1 and 8; non-array 1D T#s; linear swizzle; identity destination selectors 0xfac; single level and layer; full DMASK 0xf; ordinary 32-bit image_load and image_store, encoded with DIM 1D and DIM 2D.
    • On these 1D T#s, both instruction dimensions use X and ignore Y. Nonzero and negative Y produce the same result as Y=0. X equal to width or -1 loads four zeros and does not store.
    • R32_FLOAT loads replicate R into all four requested channels. RGBA32_FLOAT preserves each component. Eight additional in-bounds image_sample_lz 1D point samples confirmed R32_FLOAT channel replication.

    The load probe uses coordinate rows (0, width-1, width, -1) for each Y in (0, 1, -1) and texels 10.25 + x + 20*component. The single-lane store probe writes (1.0, 2.0, 3.0, 4.0) at (0,0), (width-1,0), (width,0), (-1,0), (0,1) and (0,-1), comparing the entire independent allocation after synchronization. The core probe instructions are:

    image_load v[10:13], v[4:5], s[16:23] dmask:0xf dim:SQ_RSRC_IMG_2D
    s_waitcnt vmcnt(0)
    
    image_store v[10:13], v[4:5], s[16:23] dmask:0xf dim:SQ_RSRC_IMG_2D
    s_waitcnt vmcnt(0)
    s_waitcnt_vscnt null, 0

    The 1D controls use v4 and SQ_RSRC_IMG_1D. The T# contains the independent device allocation address shifted by 8, format in dword1 bits20+, width-1 split between dword1 bits30+ and dword2, and dword3=0x80000fac; dwords4–7 are zero. No AMD DLL or game capture is included in this record. Native gfx1013/PS5 and tiled layouts were not measured.

    A narrow candidate now admits only these ordinary DIM2D-to-1D forms and formats, keeping sampling, gathers, atomics, mip instructions, d16, partial DMASK, arrays and other descriptor swizzles rejected. It also corrects identity R32_FLOAT 1D sampled views to repeat R. The RTX 5070 execution test matches the native load/store results, checks CPU writeback and unchanged padding, and preserves shader cache reuse across width/format changes. Shader-memory and disk-cache tests pass. The 12 independent serialized requests above all compile with the candidate; the private startup request also compiles offline. Full regression testing and game validation remain in progress.

  2. p3n1cillin commented on Oct 9, 2026

    @p3n1cillin
    OwnerAuthor

    The integration game run at 38102bb exercised the new failure path successfully. It retained a fragment-stage request with 612 code words, 32 user-data words, two linked programs and four captured memory regions. Offline replay with the current integration tool reproduces the same image-interface error at firstUsePc 760. The original presentation failure and SIGABRT were preserved, and the monitor stopped the exact game process. No game capture or shader content is included here.

    The failing access is full-DMASK, 32-bit image_sample_lz with DIM2D against a 1x1 non-array 1D descriptor: format 71 (RGBA16_FLOAT), identity selectors, level zero and SW_64KB_R_X. It is outside the ordinary R32_FLOAT/RGBA32_FLOAT load/store forms measured and admitted by #10. Its sampling and tiling behavior need native measurement before adding compatibility.

    Both diagnostic runs ended before a completed presentation; no gameplay or FPS result is available. All runtime processes from these runs have ended. The recorded heap-capacity registration warnings also existed before #10; old logs show the same programs exceeding the four-descriptor storage heap.

  3. p3n1cillin commented on Oct 9, 2026

    @p3n1cillin
    OwnerAuthor

    Native gfx1036 measurements and a focused follow-up are recorded in draft #12 (depends on #10/#8): full-DMASK image_sample_lz on identity single-level 1D R32_FLOAT, RGBA16_FLOAT and RGBA32_FLOAT textures ignores the encoded 2D Y coordinate; ordinary R32_FLOAT/RGBA32_FLOAT loads also work with every nonzero DMASK and compact selected components into consecutive destination registers.

    The native checks passed 144 filtered-sampling groups (5,760 samples), 240 ordinary partial-load groups (3,600 loads), and a 513-coordinate half-float interpolation sweep. A matching 1D Vulkan instruction exposed an existing NVIDIA half-float filter precision difference: 39.53125 instead of the native 39.515625. The follow-up uses texel fetches and float32 interpolation with the measured eight-bit round-to-even weights. Console tiled fixtures retain the existing Navi1x equations, rather than substituting the Ryzen GPU's different offsets.

    Review build 8f2bdea: full Windows build; 508 tests passed, zero failed, one intentional skip. New/extended execution tests and cold repository-cache runs passed. The privately captured fragment request now recompiles completely to 43,869 SPIR-V words, including the subsequent one-channel load that became visible after the sampling fix. Native provenance and remaining measurement limits are in #12; no proprietary captures or code were published. Integrated game validation is next; there is no new gameplay/FPS result yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions