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