Anna Maniscalco (Valve) @pac85@treehouse.systems
Alyssa Milburn @noopwafel@teh.entar.net
TellowKrinkle @TellowKrinkle@treehouse.systems
Viola @viola@treehouse.systems - Couldn’t be here
How much could Apple possibly have changed?
// PBE descriptor
agx_pack(..., PBE, cfg) {
cfg.dimension = AGX_TEXTURE_DIMENSION_2D;
cfg.layout = AGX_LAYOUT_LINEAR;
cfg.channels = R8G8B8A8;
cfg.type = AGX_TEXTURE_TYPE_UNORM;
cfg.swizzle_r = 0;
cfg.swizzle_g = 1;
cfg.swizzle_b = 2;
cfg.swizzle_a = 3;
cfg.width = width;
cfg.height = height;
cfg.buffer = out_bo.va->addr & 0xffffffff;
cfg.level = 1;
cfg.stride = (width * 4) - 16;
}// PBE descriptor
agx_pack(..., PBE, cfg) {
cfg.dimension = AGX_TEXTURE_DIMENSION_2D;
cfg.layout = AGX_LAYOUT_LINEAR;
cfg.channels = R8G8B8A8;
cfg.type = AGX_TEXTURE_TYPE_UNORM;
cfg.swizzle_r = 0;
cfg.swizzle_g = 1;
cfg.swizzle_b = 2;
cfg.swizzle_a = 3;
cfg.width = width;
cfg.height = height;
cfg.buffer = out_bo.va->addr;
cfg.level = 1;
cfg.stride = (width * 4) - 16;
}Oh no, new ISA!
00000000 cb fe ba be 00 00 00 02 01 00 00 13 00 00 01 42 00000010 00 00 00 30 00 00 20 a0 00 00 00 04 01 00 00 17 00000020 00 00 00 0b 00 00 20 d0 00 00 12 3c 00 00 00 04 00000030 cf fa ed fe 13 00 00 01 42 01 00 00 0d 00 00 00
00000000 cb fe ba be 00 00 00 02 01 00 00 13 00 00 01 42 00000010 00 00 00 30 00 00 20 a0 00 00 00 04 01 00 00 17 00000020 00 00 00 0b 00 00 20 d0 00 00 12 3c 00 00 00 04 00000030 cf fa ed fe 13 00 00 01 42 01 00 00 0d 00 00 00
00000000 cb fe ba be 00 00 00 02 01 00 00 13 00 00 01 42 00000010 00 00 00 30 00 00 20 a0 00 00 00 04 01 00 00 17 00000020 00 00 00 0b 00 00 20 d0 00 00 12 3c 00 00 00 04 00000030 cf fa ed fe 13 00 00 01 42 01 00 00 0d 00 00 00
$ file test.bin test.bin: [applegpu_g13g:Mach-O 64-bit GPU executable applegpu_g13g] [air64:MetalLib executable (MacOS), version 1.2.8] test.bin (for architecture applegpu_g13g): Mach-O 64-bit GPU executable applegpu_g13g test.bin (for architecture cputype (16777239) cpusubtype (11)): MetalLib executable (MacOS), version 1.2.8
__TEXT,__vertex,
__TEXT,__fragment, and __TEXT,__compute
__TEXT,__vertex,
__TEXT,__fragment, and __TEXT,__compute
00000000 cf fa ed fe 13 00 00 01 42 01 00 00 01 00 00 00
00000010 03 00 00 00 90 02 00 00 00 00 00 00 00 00 00 00
00000020 19 00 00 00 28 02 00 00 00 00 00 00 00 00 00 00
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
__TEXT,__vertex,
__TEXT,__fragment, and __TEXT,__compute
00000000 cf fa ed fe 13 00 00 01 42 01 00 00 01 00 00 00
00000010 03 00 00 00 90 02 00 00 00 00 00 00 00 00 00 00
00000020 19 00 00 00 28 02 00 00 00 00 00 00 00 00 00 00
00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
__TEXT,__text, and has symbols like _agc.main
and _agc.main.constant_program, which contain GPU ISA
kernel void test(uint pos [[thread_position_in_grid]], device uint4* out, const device uint4* in0, device uint4* in1) {
out[pos] = in0[pos] + in1[pos];
}
$ pbpaste | python3 compiler_explorer.py -
compute shader:
0: 72111004 get_sr r4, sr80 (thread_position_in_grid.x)
4: 0501840e00c8f200 device_load 0, i32, xyzw, r0_r1_r2_r3, u2_u3, r4, unsigned, lsl 2
c: 0529880e00c8f200 device_load 0, i32, xyzw, r5_r6_r7_r8, u4_u5, r4, unsigned, lsl 2
14: 3800 wait 0
16: 0e01ca022c000000 iadd r0, r5.discard, r0.discard
1e: 0e05cc222c000000 iadd r1, r6.discard, r1.discard
26: 0e09ce422c000000 iadd r2, r7.discard, r2.discard
2e: 0e0dd0622c000000 iadd r3, r8.discard, r3.discard
36: 4501800e00c8f200 device_store 0, i32, xyzw, r0_r1_r2_r3, u0_u1, r4, unsigned, lsl 2, 0
3e: 8800 stop
$ python3 hwtestbed.py "isub.sat r0, r0, r1" -r{1,-8},{2,0x7fffffff}
Thread 0: r0: 00000000 (0 ), input: 1,2
Thread 1: r0: fffffff6 (-10 ), input: -8,2
Thread 2: r0: 00000000 (0 ), input: 1,0x7fffffff
Thread 3: r0: 7ffffff9 (2147483641), input: -8,0x7fffffff
$ python3 hwtestbed.py "isub.sat r0, r0, r1.sx" -r{1,-8},{2,0x7fffffff}
Thread 0: r0: ffffffff (-1 ), input: 1,2
Thread 1: r0: 7fffffff (2147483647), input: -8,2
Thread 2: r0: 80000002 (-2147483646), input: 1,0x7fffffff
Thread 3: r0: 7ffffff9 (2147483641), input: -8,0x7fffffff
$ python3 hwtestbed.py -b 4e01402a24000000 -r{1,-8},{2,0x7fffffff}
Thread 0: r0: 00000000 (0 ), input: 1,2
Thread 1: r0: fffffff6 (-10 ), input: -8,2
Thread 2: r0: 00000000 (0 ), input: 1,0x7fffffff
Thread 3: r0: 7ffffff9 (2147483641), input: -8,0x7fffffff
$ python3 hwtestbed.py -b 4e01402a64000000 -r{1,-8},{2,0x7fffffff}
Thread 0: r0: ffffffff (-1 ), input: 1,2
Thread 1: r0: 7fffffff (2147483647), input: -8,2
Thread 2: r0: 80000002 (-2147483646), input: 1,0x7fffffff
Thread 3: r0: 7ffffff9 (2147483641), input: -8,0x7fffffff
compiler_explorer.py works without modification
compute shader prolog:
0: 0300 <disassembly failed>
2: 0700 <disassembly failed>
TODO: 1000
| M1 | M3 |
|---|---|
| Variable length ISA, in multiples of 16 bits | |
| Simple compression scheme (upper bits are 0) | |
| Field placement is consistent |
kernel void test(uint pos [[thread_position_in_grid]], device uint4* out, const device uint4* in0, device uint4* in1) {
out[pos] = in0[pos] + in1[pos];
}
compute shader:
00000000: 8C A0 10 06 06 04 06 00 06 00 06 00 67 10 54 00 ............g.T.
00000010: 01 08 20 00 57 01 00 40 40 00 67 00 44 08 02 08 .. .W..@@.g.D...
00000020: 20 00 57 01 00 40 40 00 06 80 06 00 06 00 06 00 .W..@@.........
00000030: 9F 01 56 00 02 10 00 A8 17 05 9F 01 54 02 02 14 ..V.........T...
00000040: 08 A8 17 05 9F 01 54 04 02 18 10 A8 17 05 9F 01 ......T.........
00000050: 54 06 02 1C 18 A8 17 05 E7 00 54 00 00 08 21 00 T.........T...!.
00000060: 17 00 00 10 10 00 0E 00 00 00 ..........
kernel void test(uint pos [[thread_position_in_grid]], device uint4* out, const device uint4* in0, device uint4* in1) {
out[pos] = in0[pos] + in1[pos];
}
compute shader:
00000000: 8C A0 10 06 06 04 06 00 06 00 06 00 67 10 54 00 ............g.T.
00000010: 01 08 20 00 57 01 00 40 40 00 67 00 44 08 02 08 .. .W..@@.g.D...
00000020: 20 00 57 01 00 40 40 00 06 80 06 00 06 00 06 00 .W..@@.........
00000030: 9F 01 56 00 02 10 00 A8 17 05 9F 01 54 02 02 14 ..V.........T...
00000040: 08 A8 17 05 9F 01 54 04 02 18 10 A8 17 05 9F 01 ......T.........
00000050: 54 06 02 1C 18 A8 17 05 E7 00 54 00 00 08 21 00 T.........T...!.
00000060: 17 00 00 10 10 00 0E 00 00 00 ..........
kernel void test(uint pos [[thread_position_in_grid]], device uint4* out, const device uint4* in0, device uint4* in1) {
out[pos] = in0[pos] + in1[pos];
}
compute shader:
0: 8C A0 10 06
4: 06 04 06 00 06 00 06 00
c: 67 10 54 00 01 08 20 00 57 01 00 40 40 00
1a: 67 00 44 08 02 08 20 00 57 01 00 40 40 00
28: 06 80 06 00 06 00 06 00
30: 9F 01 56 00 02 10 00 A8 17 05
3a: 9F 01 54 02 02 14 08 A8 17 05
44: 9F 01 54 04 02 18 10 A8 17 05
4e: 9F 01 54 06 02 1C 18 A8 17 05
58: E7 00 54 00 00 08 21 00 17 00 00 10 10 00
66: 0E 00 00 00
kernel void test(uint pos [[thread_position_in_grid]], device uint4* out, const device uint4* in0, device uint4* in1) {
out[pos] = in0[pos] + in1[pos];
}
compute shader:
0: 8C A0 10 06 get_sr 0, r8, sr32 (thread_position_in_grid.x)
4: 06 04 06 00 06 00 06 00 wait_long 0
c: 67 10 54 00 01 08 20 00 57 01 00 40 40 00 device_load 5, i32, xyzw, r0_r1_r2_r3, u2_u3, r8, lsl 4, 0, wait 0, 1, 1, 0
1a: 67 00 44 08 02 08 20 00 57 01 00 40 40 00 device_load 5, i32, xyzw, r4_r5_r6_r7, u4_u5, r8, lsl 4, 0, 1, 0, 0
28: 06 80 06 00 06 00 06 00 wait_long 5
30: 9F 01 56 00 02 10 00 A8 17 05 iadd r0, r4.discard, r0.discard, wait 5
3a: 9F 01 54 02 02 14 08 A8 17 05 iadd r1, r5.discard, r1.discard
44: 9F 01 54 04 02 18 10 A8 17 05 iadd r2, r6.discard, r2.discard
4e: 9F 01 54 06 02 1C 18 A8 17 05 iadd r3, r7.discard, r3.discard
58: E7 00 54 00 00 08 21 00 17 00 00 10 10 00 device_store 0, i32, xyzw, r0_r1_r2_r3, u0_u1, r8.discard, lsl 4, 0, 1, 1
66: 0E 00 00 00 stop
kernel void test(uint pos [[thread_position_in_grid]], device float4* out, const device float4* in0, device float4* in1) {
out[pos] = in0[pos] + in1[pos];
}
compute shader:
0: 8C A0 10 06 get_sr 0, r8, sr32 (thread_position_in_grid.x)
4: 06 04 06 00 06 00 06 00 wait_long 0
c: 67 10 54 00 01 08 20 00 57 01 00 40 40 00 device_load 5, i32, xyzw, r0_r1_r2_r3, u2_u3, r8, lsl 4, 0, wait 0, 1, 1, 0
1a: 67 00 44 08 02 08 20 00 57 01 00 40 40 00 device_load 5, i32, xyzw, r4_r5_r6_r7, u4_u5, r8, lsl 4, 0, 1, 0, 0
28: 06 80 06 00 06 00 06 00 wait_long 5
30: 09 09 1C 01 00 C0 fadd r0, r4.discard, r0.discard, wait 5
36: 19 0B 18 03 fadd r1, r5.discard, r1.discard
3a: 29 0D 18 05 fadd r2, r6.discard, r2.discard
3e: 39 0F 18 07 fadd r3, r7.discard, r3.discard
42: E7 00 54 00 00 08 21 00 17 00 00 10 10 00 device_store 0, i32, xyzw, r0_r1_r2_r3, u0_u1, r8.discard, lsl 4, 0, 1, 1
50: 0E 00 00 00 stop
| M1 | M3 |
|---|---|
| Variable length ISA, in multiples of 16 bits | |
| Simple compression scheme (upper bits are 0) | Complicated compression scheme |
| Field placement is consistent | Fields look like they’ve been packed like C bitfields |
M1
| 63 | 62 | 61 | 60 | 59 | 58 | 57 | 56 | 55 | 54 | 53 | 52 | 51 | 50 | 49 | 48 | 47 | 46 | 45 | 44 | 43 | 42 | 41 | 40 | 39 | 38 | 37 | 36 | 35 | 34 | 33 | 32 | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| Imm32 | Opcode | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
M1
| 63 | 62 | 61 | 60 | 59 | 58 | 57 | 56 | 55 | 54 | 53 | 52 | 51 | 50 | 49 | 48 | 47 | 46 | 45 | 44 | 43 | 42 | 41 | 40 | 39 | 38 | 37 | 36 | 35 | 34 | 33 | 32 | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| Opcode | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
M1
| 63 | 62 | 61 | 60 | 59 | 58 | 57 | 56 | 55 | 54 | 53 | 52 | 51 | 50 | 49 | 48 | 47 | 46 | 45 | 44 | 43 | 42 | 41 | 40 | 39 | 38 | 37 | 36 | 35 | 34 | 33 | 32 | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| Opcode | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
M3
| 63 | 62 | 61 | 60 | 59 | 58 | 57 | 56 | 55 | 54 | 53 | 52 | 51 | 50 | 49 | 48 | 47 | 46 | 45 | 44 | 43 | 42 | 41 | 40 | 39 | 38 | 37 | 36 | 35 | 34 | 33 | 32 | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| Opcode | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
x, z, xz,
xyzwx, y, z, w| Mask | |
|---|---|
| 0 | |
| 1 | x |
| 2 | yw |
| 3 | xyw |
| 4 | zw |
| 5 | xzw |
| 6 | yzw |
| 7 | xyzw |
| 8 | y |
| 9 | xy |
| a | z |
| b | xz |
| c | yz |
| d | xyz |
| e | w |
| f | xw |
| Buffer | Texture | |
|---|---|---|
| 0 | x | |
| 1 | x | y |
| 2 | yw | z |
| 3 | xyw | w |
| 4 | zw | xw |
| 5 | xzw | xy |
| 6 | yzw | xyz |
| 7 | xyzw | xyzw |
| 8 | y | xz |
| 9 | xy | yz |
| a | z | yw |
| b | xz | zw |
| c | yz | xzw |
| d | xyz | xyw |
| e | w | yzw |
| f | xw |
| Buffer | Texture | |
|---|---|---|
| 0 | x | |
| 1 | x | y |
| 2 | yw | z |
| 3 | xyw | w |
| 4 | zw | xw |
| 5 | xzw | xy |
| 6 | yzw | xyz |
| 7 | xyzw | xyzw |
| 8 | y | xz |
| 9 | xy | yz |
| a | z | yw |
| b | xz | zw |
| c | yz | xzw |
| d | xyz | xyw |
| e | w | yzw |
| f | xw |
Texture one is at bits 27, 28, 37, and 86
D = A > B ? X : Y
if_icmpif
cmp and full
cmpselcc variantscmp is encoded as a cmpsel with the
destination size set to 32 but with a non-32-bit-aligned registercmp and sets for cmpselcc
cmpselcc calculates
A > B ? Y : XThis shader is treated like a descriptor
0: 2C A0 02 00 12 08 78 01 mov_imm r2, 3085472
8: 3C 80 02 00 04 00 00 00 mov_imm r3, 256
10: 6C E0 42 00 06 00 20 00 mov_imm r22, 262624
18: 7C 80 42 00 04 00 00 00 mov_imm r23, 256
20: 67 00 54 24 02 00 00 00 57 00 00 40 26 00 device_load 1, i32, xyzw, r18_r19_r20_r21, r2_r3, 0, lsl 2, 0, 1, 1, 0
2e: 67 00 54 34 16 00 00 00 57 00 02 40 26 00 device_load 1, i32, xyzw, r26_r27_r28_r29, r22_r23, 0, lsl 2, 16, 1, 1, 0
3c: 67 00 54 2C 16 00 00 00 57 04 00 40 26 00 device_load 1, i32, xyzw, r22_r23_r24_r25, r22_r23, 0, lsl 2, 0, 1, 1, 1
4a: 77 00 2A 41 00 00 00 00 load_shader.todo 130
52: 77 01 AA A6 00 00 00 02 load_shader.todo 17179869517
5a: 06 00 nop
5c: F7 00 2A 00 00 10 20 10 20 00 ralloc 1026, 1026
66: 1C 80 02 00 00 00 00 00 mov_imm r1, 0
6e: 14 81 11 06 00 00 00 00 get_sr 0, r1l, sr1
76: 0C 80 02 00 04 00 00 00 mov_imm r0, 256
7e: 9F 11 54 00 02 00 08 A8 10 05 iadd r0, r0, r1, lsl 4, wait 0
88: 1C 80 02 00 04 00 00 00 mov_imm r1, 256
90: 0F 12 54 00 4C 00 06 08 06 00 <disassembly failed>
9a: 06 00 nop
9c: 06 00 nop
9e: 0B 24 09 04 mov u0, r18.discard
a2: 1B 26 09 04 mov u1, r19.discard
a6: 2B 28 09 04 mov u2, r20.discard
aa: 3B 2A 09 04 mov u3, r21.discard
ae: 8B 34 09 04 mov u8, r26.discard
b2: 9B 36 09 04 mov u9, r27.discard
b6: AB 38 09 04 mov u10, r28.discard
ba: BB 3A 09 04 mov u11, r29.discard
be: 4B 2C 09 04 mov u4, r22.discard
c2: 5B 2E 09 04 mov u5, r23.discard
c6: 6B 30 09 04 mov u6, r24.discard
ca: 7B 32 09 04 mov u7, r25.discard
ce: 0E 00 00 00 stop 🤯
.. if only we had some way to observe this?
We’ve implemented
We can compile this shader
nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE,
&agx_nir_options, "agx_troll");
nir_def *l = nir_load_global(&b, 1, 32, nir_imm_int64(&b, iova));
nir_def *cond = nir_ilt_imm(&b, nir_ior_imm(&b, l, 1), 10);
nir_if * if_ = nir_push_if(&b, cond);
nir_push_loop(&b);
nir_store_global(&b, nir_ior(&b, l, nir_imm_int(&b, 67)), nir_imm_int64(&b, iova));
nir_break_if(&b, cond);
nir_pop_loop(&b, NULL);
nir_pop_if(&b, if_); output
0: 2C 80 02 00 00 00 0C 00 mov_imm r2, 98304
8: 3C 80 02 00 04 00 00 00 mov_imm r3, 256
10: 67 00 44 02 02 00 00 00 31 00 00 00 20 00 device_load 0, i32, x, r1, r2_r3, 0, lsl 4, 0, 0, 0, 0
1e: 06 04 06 00 06 00 06 00 wait_long 0
26: 4B 03 07 80 12 0A 00 00 00 00 or r4, r1, 1
30: 0A 09 0D 8A 22 81 07 02 20 80 cmpsel slt, r0h, r4.discard, 10, 1, 0
3a: 1A 80 23 00 06 00 97 00 00 00 cmp ine, cc0, 0, r0h
44: 0F 05 54 01 if cc0, 1
48: 0A 80 23 80 06 00 87 02 00 00 cmp ieq, cc0, 0, 0
52: 0F 05 54 01 if cc0, 1
56: 4B 03 07 C2 12 0A 00 00 00 00 or r4, r1, 67
60: E7 00 44 08 02 00 00 00 31 00 00 00 08 00 device_store 0, i32, x, r4, r2_r3, 0, lsl 4, 0, 0, 0
6e: 06 04 06 00 06 00 06 00 wait_long 0
76: 1A 80 23 00 06 00 97 00 00 00 cmp ine, cc0, 0, r0h
80: 0F 05 54 01 if cc0, 1
84: 8F 05 54 02 00 06 <disassembly failed>
8a: 0F 06 04 01 00 00 pop_exec 1
90: 0F 00 54 E2 FF FF FF FF FF 00 jmp_exec_any 0x72
9a: 0F 06 04 01 00 00 pop_exec 1
a0: 0F 06 04 01 00 00 pop_exec 1
a6: 0E 00 00 00 stop
...
Output buffer after dequeue, 67None of this is hard, mostly just significant work
drivers/gpu/drm/asahi/driver.rs
@@ -145,6 +145,11 @@ impl drm::driver::Driver for AsahiDriver {
+ (
+ of::DeviceId::new(c_str!("apple,agx-t8122")),
+ &hw::t8122::HWCONFIG
+ ),
+
@@ -205,6 +210,9 @@ fn probe(
+ (hw::GpuGen::G15, _, &[14, 7, 0]) => {
+ gpu::GpuManagerG15V14_7::new(&drm.clone(), &res, cfg)? as Arc<dyn gpu::GpuManager>
+ }arch/arm64/boot/dts/apple/t8122.dtsi
@@ -374,6 +408,65 @@ soc {
+ gpu: gpu@292400000 {
+ compatible = "apple,agx-t8122", "apple,agx-g15g";
+ reg = <0x2 0x92400000 0 0x70000>,[1.245075] asahi 292400000.gpu: Probing...
[1.271715] asahi 292400000.gpu: GPU Information:
[1.272328] asahi 292400000.gpu: Type: G15G
[1.276848] asahi 292400000.gpu: Cores: 10 (10)
[5.139875] [drm] Initialized asahi 0.0.0 for 292400000.gpu on minor 1
Three small tweaks:
CBW. WC3D job_params3 =
CBW. WC3D Start3DJobParameters3:
CBW. WC3D.S3DP3 scissor_array = Start3DArrayAddr:
CBW. WC3D.S3DP3 ptr = 0x10001c50000
CBW. WC3D.S3DP3 visibility_result_buffer = 0x10001af8000
CBW. WC3D.S3DP3 unk_partial_bg = Start3DBackgroundProgram:
CBW. WC3D.S3DP3 pipeline_bind = 0x7800000000040
CBW. WC3D.S3DP3 address = 0x10001ae8100
CBW. WC3D.S3DP3 partial_bg = Start3DBackgroundProgram:
CBW. WC3D.S3DP3 pipeline_bind = 0xffff800000000000
CBW. WC3D.S3DP3 address = 0x10001ae8000
CBW. WC3D.S3DP3 depth_flags = 0x0
CBW. WC3D.S3DP3 unk_290 = 0x4040404[gfx-asc] frag work item
[gfx-asc] vert work item
[gfx-asc] kick~!
[gfx-asc] stats: Power ON: spent 0.5544s powered off (13305045 ticks)
[gfx-asc] stats: PowerState: ps=1 100 0 0 3 0 0 0 0
[gfx-asc] stats: Power: 22.291 mW
[gfx-asc] stats: TempSensor: #3 40.19°C s=4 tmin=32 tmax=40
[gfx-asc] stats: Temp: 40.61°C s=4 tmin=32 tmax=40
[gfx-asc] stats: Power OFF: spent 0.003242s powered on (77810 ticks)
[gfx-asc] pong~!
regionB.page_mgr_info (0xfffffc20000e0000..0xfffffc20000e01ff)
0003ae00 10000002 00004a00 0000bca0 00005c00 00000000 00000000 00000000
[gfx-asc] event fired: 1, 2(Someone maintained the m1n1 debug tooling, right?)
pub(crate) struct RunWorkQueueMsg {
+ #[ver(V < V14_7)]
pub(crate) pipe_type: PipeType,
pub(crate) work_queue: Option<GpuWeakPointer<super::workqueue::...>>,
+ #[ver(V >= V14_7)]
+ pub(crate) pipe_type: PipeType,
+ #[ver(V < V14_7)]
pub(crate) wptr: u32,
+ #[ver(V >= V14_7)]
+ pub(crate) wptr: u16,
+ #[ver(V < V14_7)]
pub(crate) event_slot: u32,
+ #[ver(V >= V14_7)]
+ pub(crate) event_slot: u8,
...Surprisingly little on top of G14X:
Ver("G >= G15", "g15_unk_8" / Int64ul), # 0
Ver("G >= G15", "g15_unk_10" / Int64ul), # 0
Ver("G >= G15", "g15_ptr_18" / Int64ul), # blockmgr buf
Ver("G >= G15", "g15_ptr_20" / Int64ul), # 0
Ver("G >= G15", "g15_gptr_28" / Int64ul), # pmgr buf1
Ver("G >= G15", "g15_gptr_30" / Int64ul), # pmgr buf2
Ver("G >= G15", "g15_gptr_38" / Int64ul), # pmgr buf3
Ver("G >= G15", "g15_gptr_40" / Int64ul), # pmgr buf4CBW. WCCP. SCC.[0x164.8] g15_unk_8 = 0x0
CBW. WCCP. SCC.[0x16c.8] g15_unk_10 = 0x0
CBW. WCCP. SCC.[0x174.8] g15_ptr_18 = 0xfffffc2000190000
CBW. WCCP. SCC.[0x17c.8] g15_ptr_20 = 0x0
CBW. WCCP. SCC.[0x184.8] g15_gptr_28 = 0x1000c5d0000
CBW. WCCP. SCC.[0x18c.8] g15_gptr_30 = 0x1000c5df400
CBW. WCCP. SCC.[0x194.8] g15_gptr_38 = 0x1000c5ee800
CBW. WCCP. SCC.[0x19c.8] g15_gptr_40 = 0x1000c5ef000.. huh, why would the HW be allocating memory?
ralloc 2052
mov_imm r6, 458855 # 0x67 | (7 << 16)
mov r7, r6.cache, group 4
...
mov_imm r6, 134086759 # 0x67 | (2046 << 16)
mov r2046, r6.cache, group 4
mov_imm r6, 134152295 # 0x67 | (2047 << 16)
mov r2047, r6.cache, group 4
agx_push(out, CDM_GLOBAL_SIZE, cfg) {
cfg.x = 8;
cfg.y = 8;
cfg.z = 4;
}
>>> chexdump(agx.uat.ioread(1, 0x10080000000 + 0x17000, 0x1000))
00000000 67 00 39 00 67 00 39 00 67 00 39 00 67 00 39 00
00000010 *
00000080 67 00 3a 00 67 00 3a 00 67 00 3a 00 67 00 3a 00
00000090 *
00000100 67 00 3b 00 67 00 3b 00 67 00 3b 00 67 00 3b 00
00000110 *
000001c0 67 00 3c 00 67 00 3c 00 67 00 3c 00 67 00 3c 00
000001d0 *
For now .. kind of works as-is?
(Assuming you don’t want more than 4GB.)
[8.086635] asahi 292400000.gpu: GPU: run_job
[8.087234] asahi 292400000.gpu: GPU: run_job: pipe_type=Compute
[8.087993] asahi 292400000.gpu: GPU: run_job: run()
[8.088669] asahi 292400000.gpu: Pipe: RunWorkQueueMsgG15V14_7 { timestamp: 0, work_queue:
Some(0xfffffc0800267e80 (asahi::fw::workqueue::QueueInfoG15V14_7)), pipe_type: Compute,
wptr: 1, event_slot: 0, is_new: true, __pad: <pad> }
[8.097272] asahi 292400000.gpu: GPU: run_job: ring doorbell
[8.098834] asahi 292400000.gpu: Stats: PowerOn { off_time: 0x1d604a9f }
[8.099680] asahi 292400000.gpu: Stats: PowerState { timestamp: 0x1d604a9f, last_busy_ts: 0x24edb549,
active: 0, poweroff: 0, unk1: 0, pstate: 1, unk2: 100, unk3: 0 }
[8.101344] asahi: Unknown stats message: (15, [159, 74, 96, 29, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
[8.103587] asahi 292400000.gpu: Stats: PowerOff { on_time: 0x5a96 }🤔
commit b5076d68c85a4ca1df054c1f9a7234b31a64fbf4
Date: Sat, 7 Mar 2026
demo: it's metalover
commit a1006e523146717b4e75078a25c67389b41bf2ce
Date: Sat, 28 Mar 2026
M3 agx test: compute shader runs
😴 🏃♀️💨 ⏳
Status: coming soon™
[ 6.101783] asahi 292400000.gpu: Stats: TempSensor { __pad: <pad>, sensor_id: 11, raw_value: 21346, scale: 8, tmin: 34, tmax: 41 }
[ 6.103294] asahi 292400000.gpu: Event: Timeout { counter: 0, unk_8: 0, event_slot: 0 }
[ 6.104420] asahi 292400000.gpu: (\________/)
[ 6.105180] asahi 292400000.gpu: | |
[ 6.105964] asahi 292400000.gpu: '.| \ , / |.'
[ 6.106741] asahi 292400000.gpu: --| / (( \ |--
[ 6.107513] asahi 292400000.gpu: .'| _-_- |'.
[ 6.108287] asahi 292400000.gpu: |________|
[ 6.109060] asahi 292400000.gpu: ** GPU timeout nya~!!!!! **
[ 6.109940] asahi 292400000.gpu: Event slot: 0
[ 6.110712] asahi 292400000.gpu: Timeout count: 0
[ 6.111514] asahi 292400000.gpu: Unk: 0
[ 6.112231] asahi 292400000.gpu: Pending events:
[ 6.113030] asahi 292400000.gpu: Halt count: 0
[ 6.113808] asahi 292400000.gpu: Halted: 0
We’d like to thank Vio for her contributions
(As well as all the Asahi folks)
And the audience for listening
demo time!