* to produce the correct values.
*/
-struct attr_wa_state {
- nir_builder builder;
- bool impl_progress;
- const uint8_t *wa_flags;
-};
-
static bool
-apply_attr_wa_block(nir_block *block, struct attr_wa_state *state)
+apply_attr_wa_instr(nir_builder *b, nir_instr *instr, void *cb_data)
{
- nir_builder *b = &state->builder;
+ const uint8_t *attrib_wa_flags = cb_data;
- nir_foreach_instr_safe(instr, block) {
- if (instr->type != nir_instr_type_intrinsic)
- continue;
+ if (instr->type != nir_instr_type_intrinsic)
+ return false;
- nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
- if (intrin->intrinsic != nir_intrinsic_load_input)
- continue;
+ nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
+ if (intrin->intrinsic != nir_intrinsic_load_input)
+ return false;
- uint8_t wa_flags = state->wa_flags[intrin->const_index[0]];
- if (wa_flags == 0)
- continue;
+ uint8_t wa_flags = attrib_wa_flags[intrin->const_index[0]];
+ if (wa_flags == 0)
+ return false;
- b->cursor = nir_after_instr(instr);
+ b->cursor = nir_after_instr(instr);
- nir_ssa_def *val = &intrin->dest.ssa;
+ nir_ssa_def *val = &intrin->dest.ssa;
- /* Do GL_FIXED rescaling for GLES2.0. Our GL_FIXED attributes
- * come in as floating point conversions of the integer values.
- */
- if (wa_flags & BRW_ATTRIB_WA_COMPONENT_MASK) {
- nir_ssa_def *scaled =
- nir_fmul(b, val, nir_imm_float(b, 1.0f / 65536.0f));
- nir_ssa_def *comps[4];
- for (int i = 0; i < val->num_components; i++) {
- bool rescale = i < (wa_flags & BRW_ATTRIB_WA_COMPONENT_MASK);
- comps[i] = nir_channel(b, rescale ? scaled : val, i);
- }
- val = nir_vec(b, comps, val->num_components);
+ /* Do GL_FIXED rescaling for GLES2.0. Our GL_FIXED attributes
+ * come in as floating point conversions of the integer values.
+ */
+ if (wa_flags & BRW_ATTRIB_WA_COMPONENT_MASK) {
+ nir_ssa_def *scaled =
+ nir_fmul(b, val, nir_imm_float(b, 1.0f / 65536.0f));
+ nir_ssa_def *comps[4];
+ for (int i = 0; i < val->num_components; i++) {
+ bool rescale = i < (wa_flags & BRW_ATTRIB_WA_COMPONENT_MASK);
+ comps[i] = nir_channel(b, rescale ? scaled : val, i);
}
+ val = nir_vec(b, comps, val->num_components);
+ }
- /* Do sign recovery for 2101010 formats if required. */
- if (wa_flags & BRW_ATTRIB_WA_SIGN) {
- /* sign recovery shift: <22, 22, 22, 30> */
- nir_ssa_def *shift = nir_imm_ivec4(b, 22, 22, 22, 30);
- val = nir_ishr(b, nir_ishl(b, val, shift), shift);
- }
+ /* Do sign recovery for 2101010 formats if required. */
+ if (wa_flags & BRW_ATTRIB_WA_SIGN) {
+ /* sign recovery shift: <22, 22, 22, 30> */
+ nir_ssa_def *shift = nir_imm_ivec4(b, 22, 22, 22, 30);
+ val = nir_ishr(b, nir_ishl(b, val, shift), shift);
+ }
- /* Apply BGRA swizzle if required. */
- if (wa_flags & BRW_ATTRIB_WA_BGRA) {
- val = nir_swizzle(b, val, (unsigned[4]){2,1,0,3}, 4);
- }
+ /* Apply BGRA swizzle if required. */
+ if (wa_flags & BRW_ATTRIB_WA_BGRA) {
+ val = nir_swizzle(b, val, (unsigned[4]){2,1,0,3}, 4);
+ }
- if (wa_flags & BRW_ATTRIB_WA_NORMALIZE) {
- /* ES 3.0 has different rules for converting signed normalized
- * fixed-point numbers than desktop GL.
+ if (wa_flags & BRW_ATTRIB_WA_NORMALIZE) {
+ /* ES 3.0 has different rules for converting signed normalized
+ * fixed-point numbers than desktop GL.
+ */
+ if (wa_flags & BRW_ATTRIB_WA_SIGN) {
+ /* According to equation 2.2 of the ES 3.0 specification,
+ * signed normalization conversion is done by:
+ *
+ * f = c / (2^(b-1)-1)
+ *
+ * OpenGL 4.2+ uses this equation as well. Since most contexts
+ * promote to the new higher version, and this is what Haswell+
+ * hardware does anyway, we just always use this formula.
*/
- if (wa_flags & BRW_ATTRIB_WA_SIGN) {
- /* According to equation 2.2 of the ES 3.0 specification,
- * signed normalization conversion is done by:
- *
- * f = c / (2^(b-1)-1)
- *
- * OpenGL 4.2+ uses this equation as well. Since most contexts
- * promote to the new higher version, and this is what Haswell+
- * hardware does anyway, we just always use this formula.
- */
- nir_ssa_def *es3_normalize_factor =
- nir_imm_vec4(b, 1.0f / ((1 << 9) - 1), 1.0f / ((1 << 9) - 1),
- 1.0f / ((1 << 9) - 1), 1.0f / ((1 << 1) - 1));
- val = nir_fmax(b,
- nir_fmul(b, nir_i2f32(b, val), es3_normalize_factor),
- nir_imm_float(b, -1.0f));
- } else {
- /* The following equation is from the OpenGL 3.2 specification:
- *
- * 2.1 unsigned normalization
- * f = c/(2^n-1)
- */
- nir_ssa_def *normalize_factor =
- nir_imm_vec4(b, 1.0f / ((1 << 10) - 1), 1.0f / ((1 << 10) - 1),
- 1.0f / ((1 << 10) - 1), 1.0f / ((1 << 2) - 1));
-
- val = nir_fmul(b, nir_u2f32(b, val), normalize_factor);
- }
- }
+ nir_ssa_def *es3_normalize_factor =
+ nir_imm_vec4(b, 1.0f / ((1 << 9) - 1), 1.0f / ((1 << 9) - 1),
+ 1.0f / ((1 << 9) - 1), 1.0f / ((1 << 1) - 1));
+ val = nir_fmax(b,
+ nir_fmul(b, nir_i2f32(b, val), es3_normalize_factor),
+ nir_imm_float(b, -1.0f));
+ } else {
+ /* The following equation is from the OpenGL 3.2 specification:
+ *
+ * 2.1 unsigned normalization
+ * f = c/(2^n-1)
+ */
+ nir_ssa_def *normalize_factor =
+ nir_imm_vec4(b, 1.0f / ((1 << 10) - 1), 1.0f / ((1 << 10) - 1),
+ 1.0f / ((1 << 10) - 1), 1.0f / ((1 << 2) - 1));
- if (wa_flags & BRW_ATTRIB_WA_SCALE) {
- val = (wa_flags & BRW_ATTRIB_WA_SIGN) ? nir_i2f32(b, val)
- : nir_u2f32(b, val);
+ val = nir_fmul(b, nir_u2f32(b, val), normalize_factor);
}
+ }
- nir_ssa_def_rewrite_uses_after(&intrin->dest.ssa, val,
- val->parent_instr);
- state->impl_progress = true;
+ if (wa_flags & BRW_ATTRIB_WA_SCALE) {
+ val = (wa_flags & BRW_ATTRIB_WA_SIGN) ? nir_i2f32(b, val)
+ : nir_u2f32(b, val);
}
+ nir_ssa_def_rewrite_uses_after(&intrin->dest.ssa, val,
+ val->parent_instr);
+
return true;
}
brw_nir_apply_attribute_workarounds(nir_shader *shader,
const uint8_t *attrib_wa_flags)
{
- bool progress = false;
- struct attr_wa_state state = {
- .wa_flags = attrib_wa_flags,
- };
-
- nir_foreach_function(func, shader) {
- if (!func->impl)
- continue;
-
- nir_builder_init(&state.builder, func->impl);
- state.impl_progress = false;
-
- nir_foreach_block(block, func->impl) {
- apply_attr_wa_block(block, &state);
- }
-
- if (state.impl_progress) {
- nir_metadata_preserve(func->impl, nir_metadata_block_index |
- nir_metadata_dominance);
- progress = true;
- }
- }
-
- return progress;
+ return nir_shader_instructions_pass(shader, apply_attr_wa_instr,
+ nir_metadata_block_index |
+ nir_metadata_dominance,
+ (void *)attrib_wa_flags);
}