aco_dump: compiling shaders without a GPU

Mar 20, 2026

I wrote a tool called aco_dump. It takes a SPIR-V binary, runs it through the RADV/ACO pipeline, and dumps the ACO IR. No GPU needed. It runs on the noop drm-shim device.

I proposed it upstream. The discussion is on issue #15111.

The problem

Normally, to see what ACO does to a shader, you need an AMD GPU and a running Vulkan app. Capture a frame, extract shaders, set RADV_DEBUG=shaders, look at the dump. Slow. Limited to whatever app you can run.

I wanted: give it a .spv file, get ACO IR out. For any gfx level. From any machine.

How it works

Two pieces make this possible: drm-shim and PipelineBuilder.

drm-shim is a library that intercepts DRM ioctls and fakes a GPU. RADV asks "what hardware is this?", drm-shim answers with whatever gfx level you picked. Mesa initializes normally. It just can't submit work — which doesn't matter, I only want the compiler output.

PipelineBuilder is Mesa's internal test utility. It constructs Vulkan pipeline objects programmatically, without the full API surface. I used this instead of fossilize because I need direct control over pipeline state, not replay of pre-recorded captures.

Usage

ninja -C build src/amd/compiler/tests/aco_dump

Compute shader:

LD_PRELOAD=build/src/amd/drm-shim/libamdgpu_noop_drm_shim.so \
  build/src/amd/compiler/tests/aco_dump gfx9 cs compute.spv

Vertex + fragment pipeline:

LD_PRELOAD=build/src/amd/drm-shim/libamdgpu_noop_drm_shim.so \
  build/src/amd/compiler/tests/aco_dump gfx10 vsfs vert.spv frag.spv

Supports gfx6 through gfx12. Two modes: cs for compute, vsfs for vertex+fragment. The gfx level is the first argument, so comparing output across generations is just changing one word.

The upstream discussion

The main pushback was maintenance. Anything that depends on RADV internals breaks when those internals change, and they change often. The tool lives under src/amd/compiler/tests/ to stay close to the existing test infrastructure and minimize coupling.

What I got out of it

Building this meant understanding every piece of state that flows from RADV into ACO. Hardware caps, shader stage info, pipeline layout, binding models — inside ACO, all of this is already there. When you're setting it up yourself, you learn what each field actually means.

The other useful thing: comparing the same shader across gfx levels. Same SPIR-V, different instruction encodings, different register pressure, different scheduling. Side by side, no hardware swap needed.

← Back to main page