xref: /aosp_15_r20/external/mesa3d/src/asahi/compiler/agx_lower_uniform_sources.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2023 Alyssa Rosenzweig
3  * SPDX-License-Identifier: MIT
4  */
5 #include "agx_builder.h"
6 #include "agx_compiler.h"
7 
8 /*
9  * Not all instructions can take uniforms. Memory instructions can take
10  * uniforms, but only for their base (first) source and only in the
11  * low-half of the uniform file.
12  *
13  * This pass lowers invalid uniforms.
14  */
15 bool
agx_instr_accepts_uniform(enum agx_opcode op,unsigned src_index,unsigned value,enum agx_size size)16 agx_instr_accepts_uniform(enum agx_opcode op, unsigned src_index,
17                           unsigned value, enum agx_size size)
18 {
19    /* Some instructions only seem able to access uniforms in the low half */
20    bool high = value >= 256;
21 
22    /* ALU cannot access 64-bit uniforms */
23    bool is_64 = size == AGX_SIZE_64;
24 
25    switch (op) {
26    case AGX_OPCODE_IMAGE_LOAD:
27    case AGX_OPCODE_TEXTURE_LOAD:
28    case AGX_OPCODE_TEXTURE_SAMPLE:
29       /* Unknown if this works, but the driver will never hit this. */
30       assert(!(src_index == 2 && high) && "texture heap always low");
31       return !high && (src_index == 1 || src_index == 2);
32 
33    case AGX_OPCODE_DEVICE_LOAD:
34       return src_index == 0 && !high;
35    case AGX_OPCODE_DEVICE_STORE:
36    case AGX_OPCODE_ATOMIC:
37       return src_index == 1 && !high;
38    case AGX_OPCODE_LOCAL_LOAD:
39       return src_index == 0;
40    case AGX_OPCODE_LOCAL_STORE:
41       return src_index == 1;
42    case AGX_OPCODE_IMAGE_WRITE:
43       return src_index == 3;
44    case AGX_OPCODE_BLOCK_IMAGE_STORE:
45       return src_index == 0;
46    case AGX_OPCODE_ZS_EMIT:
47    case AGX_OPCODE_ST_TILE:
48    case AGX_OPCODE_LD_TILE:
49    case AGX_OPCODE_UNIFORM_STORE:
50    case AGX_OPCODE_ST_VARY:
51    case AGX_OPCODE_LOCAL_ATOMIC:
52    case AGX_OPCODE_SAMPLE_MASK:
53    case AGX_OPCODE_ITER:
54    case AGX_OPCODE_ITERPROJ:
55    case AGX_OPCODE_STACK_LOAD:
56    case AGX_OPCODE_STACK_STORE:
57    case AGX_OPCODE_BALLOT:
58    case AGX_OPCODE_FCMP_BALLOT:
59    case AGX_OPCODE_ICMP_BALLOT:
60    case AGX_OPCODE_QUAD_BALLOT:
61    case AGX_OPCODE_FCMP_QUAD_BALLOT:
62    case AGX_OPCODE_ICMP_QUAD_BALLOT:
63       return false;
64    default:
65       return !is_64;
66    }
67 }
68 
69 void
agx_lower_uniform_sources(agx_context * ctx)70 agx_lower_uniform_sources(agx_context *ctx)
71 {
72    agx_foreach_instr_global_safe(ctx, I) {
73       agx_builder b = agx_init_builder(ctx, agx_before_instr(I));
74 
75       agx_foreach_src(I, s) {
76          if (I->src[s].type == AGX_INDEX_UNIFORM &&
77              !agx_instr_accepts_uniform(I->op, s, I->src[s].value,
78                                         I->src[s].size)) {
79 
80             agx_index idx = I->src[s];
81             idx.abs = idx.neg = false;
82             agx_replace_src(I, s, agx_mov(&b, idx));
83          }
84       }
85    }
86 }
87