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 static bool
should_lower(enum agx_opcode op,agx_index uniform,unsigned src_index)16 should_lower(enum agx_opcode op, agx_index uniform, unsigned src_index)
17 {
18 if (uniform.type != AGX_INDEX_UNIFORM)
19 return false;
20
21 /* Some instructions only seem able to access uniforms in the low half */
22 bool high = uniform.value >= 256;
23
24 switch (op) {
25 case AGX_OPCODE_IMAGE_LOAD:
26 case AGX_OPCODE_TEXTURE_LOAD:
27 case AGX_OPCODE_TEXTURE_SAMPLE:
28 return src_index != 1 && src_index != 2;
29 case AGX_OPCODE_DEVICE_LOAD:
30 return src_index != 0 || high;
31 case AGX_OPCODE_DEVICE_STORE:
32 case AGX_OPCODE_ATOMIC:
33 return src_index != 1 || high;
34 case AGX_OPCODE_LOCAL_LOAD:
35 return src_index != 0;
36 case AGX_OPCODE_LOCAL_STORE:
37 return src_index != 1;
38 case AGX_OPCODE_IMAGE_WRITE:
39 return src_index != 3;
40 case AGX_OPCODE_ZS_EMIT:
41 case AGX_OPCODE_ST_TILE:
42 case AGX_OPCODE_LD_TILE:
43 case AGX_OPCODE_BLOCK_IMAGE_STORE:
44 case AGX_OPCODE_UNIFORM_STORE:
45 case AGX_OPCODE_ST_VARY:
46 case AGX_OPCODE_LOCAL_ATOMIC:
47 case AGX_OPCODE_SAMPLE_MASK:
48 case AGX_OPCODE_ITER:
49 case AGX_OPCODE_ITERPROJ:
50 case AGX_OPCODE_STACK_LOAD:
51 case AGX_OPCODE_STACK_STORE:
52 return true;
53 default:
54 return false;
55 }
56 }
57
58 void
agx_lower_uniform_sources(agx_context * ctx)59 agx_lower_uniform_sources(agx_context *ctx)
60 {
61 agx_foreach_instr_global_safe(ctx, I) {
62 agx_builder b = agx_init_builder(ctx, agx_before_instr(I));
63
64 agx_foreach_src(I, s) {
65 if (should_lower(I->op, I->src[s], s))
66 I->src[s] = agx_mov(&b, I->src[s]);
67 }
68 }
69 }
70