2 * Copyright © 2016 Intel Corporation
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:
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
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
24 #include "compiler/nir/nir_builder.h"
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.
34 struct attr_wa_state
{
37 bool use_legacy_snorm_formula
;
38 const uint8_t *wa_flags
;
42 apply_attr_wa_block(nir_block
*block
, void *void_state
)
44 struct attr_wa_state
*state
= void_state
;
45 nir_builder
*b
= &state
->builder
;
47 nir_foreach_instr_safe(block
, instr
) {
48 if (instr
->type
!= nir_instr_type_intrinsic
)
51 nir_intrinsic_instr
*intrin
= nir_instr_as_intrinsic(instr
);
52 if (intrin
->intrinsic
!= nir_intrinsic_load_input
)
55 uint8_t wa_flags
= state
->wa_flags
[intrin
->const_index
[0]];
59 b
->cursor
= nir_after_instr(instr
);
61 nir_ssa_def
*val
= &intrin
->dest
.ssa
;
63 /* Do GL_FIXED rescaling for GLES2.0. Our GL_FIXED attributes
64 * come in as floating point conversions of the integer values.
66 if (wa_flags
& BRW_ATTRIB_WA_COMPONENT_MASK
) {
68 nir_fmul(b
, val
, nir_imm_float(b
, 1.0f
/ 65536.0f
));
69 nir_ssa_def
*comps
[4];
70 for (int i
= 0; i
< val
->num_components
; i
++) {
71 bool rescale
= i
< (wa_flags
& BRW_ATTRIB_WA_COMPONENT_MASK
);
72 comps
[i
] = nir_channel(b
, rescale
? scaled
: val
, i
);
74 val
= nir_vec(b
, comps
, val
->num_components
);
77 /* Do sign recovery for 2101010 formats if required. */
78 if (wa_flags
& BRW_ATTRIB_WA_SIGN
) {
79 /* sign recovery shift: <22, 22, 22, 30> */
80 nir_ssa_def
*shift
= nir_imm_ivec4(b
, 22, 22, 22, 30);
81 val
= nir_ishr(b
, nir_ishl(b
, val
, shift
), shift
);
84 /* Apply BGRA swizzle if required. */
85 if (wa_flags
& BRW_ATTRIB_WA_BGRA
) {
86 val
= nir_swizzle(b
, val
, (unsigned[4]){2,1,0,3}, 4, true);
89 if (wa_flags
& BRW_ATTRIB_WA_NORMALIZE
) {
90 /* ES 3.0 has different rules for converting signed normalized
91 * fixed-point numbers than desktop GL.
93 if ((wa_flags
& BRW_ATTRIB_WA_SIGN
) &&
94 !state
->use_legacy_snorm_formula
) {
95 /* According to equation 2.2 of the ES 3.0 specification,
96 * signed normalization conversion is done by:
100 nir_ssa_def
*es3_normalize_factor
=
101 nir_imm_vec4(b
, 1.0f
/ ((1 << 9) - 1), 1.0f
/ ((1 << 9) - 1),
102 1.0f
/ ((1 << 9) - 1), 1.0f
/ ((1 << 1) - 1));
104 nir_fmul(b
, nir_i2f(b
, val
), es3_normalize_factor
),
105 nir_imm_float(b
, -1.0f
));
107 /* The following equations are from the OpenGL 3.2 specification:
109 * 2.1 unsigned normalization
112 * 2.2 signed normalization
115 * Both of these share a common divisor, which we handle by
116 * multiplying by 1 / (2^b - 1) for b = <10, 10, 10, 2>.
118 nir_ssa_def
*normalize_factor
=
119 nir_imm_vec4(b
, 1.0f
/ ((1 << 10) - 1), 1.0f
/ ((1 << 10) - 1),
120 1.0f
/ ((1 << 10) - 1), 1.0f
/ ((1 << 2) - 1));
122 if (wa_flags
& BRW_ATTRIB_WA_SIGN
) {
123 /* For signed normalization, the numerator is 2c+1. */
124 nir_ssa_def
*two
= nir_imm_float(b
, 2.0f
);
125 nir_ssa_def
*one
= nir_imm_float(b
, 1.0f
);
126 val
= nir_fadd(b
, nir_fmul(b
, nir_i2f(b
, val
), two
), one
);
128 /* For unsigned normalization, the numerator is just c. */
129 val
= nir_u2f(b
, val
);
131 val
= nir_fmul(b
, val
, normalize_factor
);
135 if (wa_flags
& BRW_ATTRIB_WA_SCALE
) {
136 val
= (wa_flags
& BRW_ATTRIB_WA_SIGN
) ? nir_i2f(b
, val
)
140 nir_ssa_def_rewrite_uses_after(&intrin
->dest
.ssa
, nir_src_for_ssa(val
),
142 state
->impl_progress
= true;
149 brw_nir_apply_attribute_workarounds(nir_shader
*shader
,
150 bool use_legacy_snorm_formula
,
151 const uint8_t *attrib_wa_flags
)
153 bool progress
= false;
154 struct attr_wa_state state
= {
155 .use_legacy_snorm_formula
= use_legacy_snorm_formula
,
156 .wa_flags
= attrib_wa_flags
,
159 nir_foreach_function(shader
, func
) {
163 nir_builder_init(&state
.builder
, func
->impl
);
164 state
.impl_progress
= false;
166 nir_foreach_block(func
->impl
, apply_attr_wa_block
, &state
);
168 if (state
.impl_progress
) {
169 nir_metadata_preserve(func
->impl
, nir_metadata_block_index
|
170 nir_metadata_dominance
);