i965: "Fix" aux offsets
[mesa.git] / src / mesa / drivers / dri / i965 / brw_nir_attribute_workarounds.c
1 /*
2 * Copyright © 2016 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "compiler/nir/nir_builder.h"
25 #include "brw_nir.h"
26 #include "brw_vs.h"
27
28 /**
29 * Prior to Haswell, the hardware can't natively support GL_FIXED or
30 * 2_10_10_10_REV vertex formats. This pass inserts extra shader code
31 * to produce the correct values.
32 */
33
34 struct attr_wa_state {
35 nir_builder builder;
36 bool impl_progress;
37 bool use_legacy_snorm_formula;
38 const uint8_t *wa_flags;
39 };
40
41 static bool
42 apply_attr_wa_block(nir_block *block, struct attr_wa_state *state)
43 {
44 nir_builder *b = &state->builder;
45
46 nir_foreach_instr_safe(instr, block) {
47 if (instr->type != nir_instr_type_intrinsic)
48 continue;
49
50 nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
51 if (intrin->intrinsic != nir_intrinsic_load_input)
52 continue;
53
54 uint8_t wa_flags = state->wa_flags[intrin->const_index[0]];
55 if (wa_flags == 0)
56 continue;
57
58 b->cursor = nir_after_instr(instr);
59
60 nir_ssa_def *val = &intrin->dest.ssa;
61
62 /* Do GL_FIXED rescaling for GLES2.0. Our GL_FIXED attributes
63 * come in as floating point conversions of the integer values.
64 */
65 if (wa_flags & BRW_ATTRIB_WA_COMPONENT_MASK) {
66 nir_ssa_def *scaled =
67 nir_fmul(b, val, nir_imm_float(b, 1.0f / 65536.0f));
68 nir_ssa_def *comps[4];
69 for (int i = 0; i < val->num_components; i++) {
70 bool rescale = i < (wa_flags & BRW_ATTRIB_WA_COMPONENT_MASK);
71 comps[i] = nir_channel(b, rescale ? scaled : val, i);
72 }
73 val = nir_vec(b, comps, val->num_components);
74 }
75
76 /* Do sign recovery for 2101010 formats if required. */
77 if (wa_flags & BRW_ATTRIB_WA_SIGN) {
78 /* sign recovery shift: <22, 22, 22, 30> */
79 nir_ssa_def *shift = nir_imm_ivec4(b, 22, 22, 22, 30);
80 val = nir_ishr(b, nir_ishl(b, val, shift), shift);
81 }
82
83 /* Apply BGRA swizzle if required. */
84 if (wa_flags & BRW_ATTRIB_WA_BGRA) {
85 val = nir_swizzle(b, val, (unsigned[4]){2,1,0,3}, 4, true);
86 }
87
88 if (wa_flags & BRW_ATTRIB_WA_NORMALIZE) {
89 /* ES 3.0 has different rules for converting signed normalized
90 * fixed-point numbers than desktop GL.
91 */
92 if ((wa_flags & BRW_ATTRIB_WA_SIGN) &&
93 !state->use_legacy_snorm_formula) {
94 /* According to equation 2.2 of the ES 3.0 specification,
95 * signed normalization conversion is done by:
96 *
97 * f = c / (2^(b-1)-1)
98 */
99 nir_ssa_def *es3_normalize_factor =
100 nir_imm_vec4(b, 1.0f / ((1 << 9) - 1), 1.0f / ((1 << 9) - 1),
101 1.0f / ((1 << 9) - 1), 1.0f / ((1 << 1) - 1));
102 val = nir_fmax(b,
103 nir_fmul(b, nir_i2f(b, val), es3_normalize_factor),
104 nir_imm_float(b, -1.0f));
105 } else {
106 /* The following equations are from the OpenGL 3.2 specification:
107 *
108 * 2.1 unsigned normalization
109 * f = c/(2^n-1)
110 *
111 * 2.2 signed normalization
112 * f = (2c+1)/(2^n-1)
113 *
114 * Both of these share a common divisor, which we handle by
115 * multiplying by 1 / (2^b - 1) for b = <10, 10, 10, 2>.
116 */
117 nir_ssa_def *normalize_factor =
118 nir_imm_vec4(b, 1.0f / ((1 << 10) - 1), 1.0f / ((1 << 10) - 1),
119 1.0f / ((1 << 10) - 1), 1.0f / ((1 << 2) - 1));
120
121 if (wa_flags & BRW_ATTRIB_WA_SIGN) {
122 /* For signed normalization, the numerator is 2c+1. */
123 nir_ssa_def *two = nir_imm_float(b, 2.0f);
124 nir_ssa_def *one = nir_imm_float(b, 1.0f);
125 val = nir_fadd(b, nir_fmul(b, nir_i2f(b, val), two), one);
126 } else {
127 /* For unsigned normalization, the numerator is just c. */
128 val = nir_u2f(b, val);
129 }
130 val = nir_fmul(b, val, normalize_factor);
131 }
132 }
133
134 if (wa_flags & BRW_ATTRIB_WA_SCALE) {
135 val = (wa_flags & BRW_ATTRIB_WA_SIGN) ? nir_i2f(b, val)
136 : nir_u2f(b, val);
137 }
138
139 nir_ssa_def_rewrite_uses_after(&intrin->dest.ssa, nir_src_for_ssa(val),
140 val->parent_instr);
141 state->impl_progress = true;
142 }
143
144 return true;
145 }
146
147 bool
148 brw_nir_apply_attribute_workarounds(nir_shader *shader,
149 bool use_legacy_snorm_formula,
150 const uint8_t *attrib_wa_flags)
151 {
152 bool progress = false;
153 struct attr_wa_state state = {
154 .use_legacy_snorm_formula = use_legacy_snorm_formula,
155 .wa_flags = attrib_wa_flags,
156 };
157
158 nir_foreach_function(func, shader) {
159 if (!func->impl)
160 continue;
161
162 nir_builder_init(&state.builder, func->impl);
163 state.impl_progress = false;
164
165 nir_foreach_block(block, func->impl) {
166 apply_attr_wa_block(block, &state);
167 }
168
169 if (state.impl_progress) {
170 nir_metadata_preserve(func->impl, nir_metadata_block_index |
171 nir_metadata_dominance);
172 progress = true;
173 }
174 }
175
176 return progress;
177 }