summaryrefslogtreecommitdiffstats
path: root/src/mesa
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/drivers/dri/i965/Makefile.sources1
-rw-r--r--src/mesa/drivers/dri/i965/brw_nir.c19
-rw-r--r--src/mesa/drivers/dri/i965/brw_nir.h7
-rw-r--r--src/mesa/drivers/dri/i965/brw_nir_attribute_workarounds.c176
-rw-r--r--src/mesa/drivers/dri/i965/brw_shader.cpp2
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4.cpp3
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp2
-rw-r--r--src/mesa/drivers/dri/i965/brw_vec4_vs_visitor.cpp109
8 files changed, 202 insertions, 117 deletions
diff --git a/src/mesa/drivers/dri/i965/Makefile.sources b/src/mesa/drivers/dri/i965/Makefile.sources
index caabb0decfb..300c13909d4 100644
--- a/src/mesa/drivers/dri/i965/Makefile.sources
+++ b/src/mesa/drivers/dri/i965/Makefile.sources
@@ -43,6 +43,7 @@ i965_compiler_FILES = \
brw_nir.h \
brw_nir.c \
brw_nir_analyze_boolean_resolves.c \
+ brw_nir_attribute_workarounds.c \
brw_nir_opt_peephole_ffma.c \
brw_nir_uniforms.cpp \
brw_packed_float.c \
diff --git a/src/mesa/drivers/dri/i965/brw_nir.c b/src/mesa/drivers/dri/i965/brw_nir.c
index 46b51163579..41059b3227e 100644
--- a/src/mesa/drivers/dri/i965/brw_nir.c
+++ b/src/mesa/drivers/dri/i965/brw_nir.c
@@ -205,7 +205,9 @@ remap_patch_urb_offsets(nir_block *block, void *closure)
static void
brw_nir_lower_inputs(nir_shader *nir,
const struct brw_device_info *devinfo,
- bool is_scalar)
+ bool is_scalar,
+ bool use_legacy_snorm_formula,
+ const uint8_t *vs_attrib_wa_flags)
{
switch (nir->stage) {
case MESA_SHADER_VERTEX:
@@ -225,6 +227,9 @@ brw_nir_lower_inputs(nir_shader *nir,
add_const_offset_to_base(nir, nir_var_shader_in);
+ brw_nir_apply_attribute_workarounds(nir, use_legacy_snorm_formula,
+ vs_attrib_wa_flags);
+
if (is_scalar) {
/* Finally, translate VERT_ATTRIB_* values into the actual registers.
*
@@ -501,12 +506,15 @@ brw_preprocess_nir(nir_shader *nir, bool is_scalar)
nir_shader *
brw_nir_lower_io(nir_shader *nir,
const struct brw_device_info *devinfo,
- bool is_scalar)
+ bool is_scalar,
+ bool use_legacy_snorm_formula,
+ const uint8_t *vs_attrib_wa_flags)
{
bool progress; /* Written by OPT and OPT_V */
(void)progress;
- OPT_V(brw_nir_lower_inputs, devinfo, is_scalar);
+ OPT_V(brw_nir_lower_inputs, devinfo, is_scalar,
+ use_legacy_snorm_formula, vs_attrib_wa_flags);
OPT_V(brw_nir_lower_outputs, devinfo, is_scalar);
OPT_V(nir_lower_io, nir_var_all, is_scalar ? type_size_scalar : type_size_vec4);
@@ -617,9 +625,10 @@ brw_create_nir(struct brw_context *brw,
OPT_V(nir_lower_atomics, shader_prog);
}
- if (nir->stage != MESA_SHADER_TESS_CTRL &&
+ if (nir->stage != MESA_SHADER_VERTEX &&
+ nir->stage != MESA_SHADER_TESS_CTRL &&
nir->stage != MESA_SHADER_TESS_EVAL) {
- nir = brw_nir_lower_io(nir, devinfo, is_scalar);
+ nir = brw_nir_lower_io(nir, devinfo, is_scalar, false, NULL);
}
return nir;
diff --git a/src/mesa/drivers/dri/i965/brw_nir.h b/src/mesa/drivers/dri/i965/brw_nir.h
index 079d8b25174..9a90e36964b 100644
--- a/src/mesa/drivers/dri/i965/brw_nir.h
+++ b/src/mesa/drivers/dri/i965/brw_nir.h
@@ -84,11 +84,16 @@ nir_shader *brw_create_nir(struct brw_context *brw,
nir_shader *brw_preprocess_nir(nir_shader *nir, bool is_scalar);
nir_shader *brw_nir_lower_io(nir_shader *nir,
const struct brw_device_info *devinfo,
- bool is_scalar);
+ bool is_scalar,
+ bool use_legacy_snorm_formula,
+ const uint8_t *vs_attrib_wa_flags);
nir_shader *brw_postprocess_nir(nir_shader *nir,
const struct brw_device_info *devinfo,
bool is_scalar);
+bool brw_nir_apply_attribute_workarounds(nir_shader *nir,
+ bool use_legacy_snorm_formula,
+ const uint8_t *attrib_wa_flags);
nir_shader *brw_nir_apply_sampler_key(nir_shader *nir,
const struct brw_device_info *devinfo,
diff --git a/src/mesa/drivers/dri/i965/brw_nir_attribute_workarounds.c b/src/mesa/drivers/dri/i965/brw_nir_attribute_workarounds.c
new file mode 100644
index 00000000000..9c65e540d79
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/brw_nir_attribute_workarounds.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright © 2016 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include "compiler/nir/nir_builder.h"
+#include "brw_nir.h"
+#include "brw_vs.h"
+
+/**
+ * Prior to Haswell, the hardware can't natively support GL_FIXED or
+ * 2_10_10_10_REV vertex formats. This pass inserts extra shader code
+ * to produce the correct values.
+ */
+
+struct attr_wa_state {
+ nir_builder builder;
+ bool impl_progress;
+ bool use_legacy_snorm_formula;
+ const uint8_t *wa_flags;
+};
+
+static bool
+apply_attr_wa_block(nir_block *block, void *void_state)
+{
+ struct attr_wa_state *state = void_state;
+ nir_builder *b = &state->builder;
+
+ nir_foreach_instr_safe(block, instr) {
+ if (instr->type != nir_instr_type_intrinsic)
+ continue;
+
+ nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
+ if (intrin->intrinsic != nir_intrinsic_load_input)
+ continue;
+
+ uint8_t wa_flags = state->wa_flags[intrin->const_index[0]];
+ if (wa_flags == 0)
+ continue;
+
+ b->cursor = nir_after_instr(instr);
+
+ 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 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, true);
+ }
+
+ 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) &&
+ !state->use_legacy_snorm_formula) {
+ /* According to equation 2.2 of the ES 3.0 specification,
+ * signed normalization conversion is done by:
+ *
+ * f = c / (2^(b-1)-1)
+ */
+ 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_i2f(b, val), es3_normalize_factor),
+ nir_imm_float(b, -1.0f));
+ } else {
+ /* The following equations are from the OpenGL 3.2 specification:
+ *
+ * 2.1 unsigned normalization
+ * f = c/(2^n-1)
+ *
+ * 2.2 signed normalization
+ * f = (2c+1)/(2^n-1)
+ *
+ * Both of these share a common divisor, which we handle by
+ * multiplying by 1 / (2^b - 1) for b = <10, 10, 10, 2>.
+ */
+ 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_SIGN) {
+ /* For signed normalization, the numerator is 2c+1. */
+ nir_ssa_def *two = nir_imm_float(b, 2.0f);
+ nir_ssa_def *one = nir_imm_float(b, 1.0f);
+ val = nir_fadd(b, nir_fmul(b, nir_i2f(b, val), two), one);
+ } else {
+ /* For unsigned normalization, the numerator is just c. */
+ val = nir_u2f(b, val);
+ }
+ val = nir_fmul(b, val, normalize_factor);
+ }
+ }
+
+ if (wa_flags & BRW_ATTRIB_WA_SCALE) {
+ val = (wa_flags & BRW_ATTRIB_WA_SIGN) ? nir_i2f(b, val)
+ : nir_u2f(b, val);
+ }
+
+ nir_ssa_def_rewrite_uses_after(&intrin->dest.ssa, nir_src_for_ssa(val),
+ val->parent_instr);
+ state->impl_progress = true;
+ }
+
+ return true;
+}
+
+bool
+brw_nir_apply_attribute_workarounds(nir_shader *shader,
+ bool use_legacy_snorm_formula,
+ const uint8_t *attrib_wa_flags)
+{
+ bool progress = false;
+ struct attr_wa_state state = {
+ .use_legacy_snorm_formula = use_legacy_snorm_formula,
+ .wa_flags = attrib_wa_flags,
+ };
+
+ nir_foreach_function(shader, func) {
+ if (!func->impl)
+ continue;
+
+ nir_builder_init(&state.builder, func->impl);
+ state.impl_progress = false;
+
+ nir_foreach_block(func->impl, apply_attr_wa_block, &state);
+
+ if (state.impl_progress) {
+ nir_metadata_preserve(func->impl, nir_metadata_block_index |
+ nir_metadata_dominance);
+ progress = true;
+ }
+ }
+
+ return progress;
+}
diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp
index 6a6efa9aea2..8518622c0b6 100644
--- a/src/mesa/drivers/dri/i965/brw_shader.cpp
+++ b/src/mesa/drivers/dri/i965/brw_shader.cpp
@@ -1229,7 +1229,7 @@ brw_compile_tes(const struct brw_compiler *compiler,
nir = brw_nir_apply_sampler_key(nir, devinfo, &key->tex, is_scalar);
nir->info.inputs_read = key->inputs_read;
nir->info.patch_inputs_read = key->patch_inputs_read;
- nir = brw_nir_lower_io(nir, compiler->devinfo, is_scalar);
+ nir = brw_nir_lower_io(nir, compiler->devinfo, is_scalar, false, NULL);
nir = brw_postprocess_nir(nir, compiler->devinfo, is_scalar);
brw_compute_vue_map(devinfo, &prog_data->base.vue_map,
diff --git a/src/mesa/drivers/dri/i965/brw_vec4.cpp b/src/mesa/drivers/dri/i965/brw_vec4.cpp
index e8bc2ec241f..109080af9a6 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4.cpp
@@ -1992,6 +1992,9 @@ brw_compile_vs(const struct brw_compiler *compiler, void *log_data,
nir_shader *shader = nir_shader_clone(mem_ctx, src_shader);
shader = brw_nir_apply_sampler_key(shader, compiler->devinfo, &key->tex,
is_scalar);
+ shader = brw_nir_lower_io(shader, compiler->devinfo, is_scalar,
+ use_legacy_snorm_formula,
+ key->gl_attrib_wa_flags);
shader = brw_postprocess_nir(shader, compiler->devinfo, is_scalar);
const unsigned *assembly = NULL;
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp b/src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp
index 0d56356a016..d8bb00f5d03 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_tcs.cpp
@@ -516,7 +516,7 @@ brw_compile_tcs(const struct brw_compiler *compiler,
nir = brw_nir_apply_sampler_key(nir, devinfo, &key->tex, is_scalar);
nir->info.outputs_written = key->outputs_written;
nir->info.patch_outputs_written = key->patch_outputs_written;
- nir = brw_nir_lower_io(nir, compiler->devinfo, is_scalar);
+ nir = brw_nir_lower_io(nir, compiler->devinfo, is_scalar, false, NULL);
nir = brw_postprocess_nir(nir, compiler->devinfo, is_scalar);
prog_data->instances = DIV_ROUND_UP(nir->info.tcs.vertices_out, 2);
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_vs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_vs_visitor.cpp
index 1d6914902b3..f3cfc8892d3 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_vs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_vs_visitor.cpp
@@ -30,115 +30,6 @@ namespace brw {
void
vec4_vs_visitor::emit_prolog()
{
- dst_reg sign_recovery_shift;
- dst_reg normalize_factor;
- dst_reg es3_normalize_factor;
-
- for (int i = 0; i < VERT_ATTRIB_MAX; i++) {
- if (vs_prog_data->inputs_read & BITFIELD64_BIT(i)) {
- uint8_t wa_flags = key->gl_attrib_wa_flags[i];
- dst_reg reg(ATTR, i);
- dst_reg reg_d = reg;
- reg_d.type = BRW_REGISTER_TYPE_D;
- dst_reg reg_ud = reg;
- reg_ud.type = BRW_REGISTER_TYPE_UD;
-
- /* 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) {
- dst_reg dst = reg;
- dst.type = brw_type_for_base_type(glsl_type::vec4_type);
- dst.writemask = (1 << (wa_flags & BRW_ATTRIB_WA_COMPONENT_MASK)) - 1;
- emit(MUL(dst, src_reg(dst), brw_imm_f(1.0f / 65536.0f)));
- }
-
- /* Do sign recovery for 2101010 formats if required. */
- if (wa_flags & BRW_ATTRIB_WA_SIGN) {
- if (sign_recovery_shift.file == BAD_FILE) {
- /* shift constant: <22,22,22,30> */
- sign_recovery_shift = dst_reg(this, glsl_type::uvec4_type);
- emit(MOV(writemask(sign_recovery_shift, WRITEMASK_XYZ), brw_imm_ud(22u)));
- emit(MOV(writemask(sign_recovery_shift, WRITEMASK_W), brw_imm_ud(30u)));
- }
-
- emit(SHL(reg_ud, src_reg(reg_ud), src_reg(sign_recovery_shift)));
- emit(ASR(reg_d, src_reg(reg_d), src_reg(sign_recovery_shift)));
- }
-
- /* Apply BGRA swizzle if required. */
- if (wa_flags & BRW_ATTRIB_WA_BGRA) {
- src_reg temp = src_reg(reg);
- temp.swizzle = BRW_SWIZZLE4(2,1,0,3);
- emit(MOV(reg, temp));
- }
-
- 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) && !use_legacy_snorm_formula) {
- /* According to equation 2.2 of the ES 3.0 specification,
- * signed normalization conversion is done by:
- *
- * f = c / (2^(b-1)-1)
- */
- if (es3_normalize_factor.file == BAD_FILE) {
- /* mul constant: 1 / (2^(b-1) - 1) */
- es3_normalize_factor = dst_reg(this, glsl_type::vec4_type);
- emit(MOV(writemask(es3_normalize_factor, WRITEMASK_XYZ),
- brw_imm_f(1.0f / ((1<<9) - 1))));
- emit(MOV(writemask(es3_normalize_factor, WRITEMASK_W),
- brw_imm_f(1.0f / ((1<<1) - 1))));
- }
-
- dst_reg dst = reg;
- dst.type = brw_type_for_base_type(glsl_type::vec4_type);
- emit(MOV(dst, src_reg(reg_d)));
- emit(MUL(dst, src_reg(dst), src_reg(es3_normalize_factor)));
- emit_minmax(BRW_CONDITIONAL_GE, dst, src_reg(dst), brw_imm_f(-1.0f));
- } else {
- /* The following equations are from the OpenGL 3.2 specification:
- *
- * 2.1 unsigned normalization
- * f = c/(2^n-1)
- *
- * 2.2 signed normalization
- * f = (2c+1)/(2^n-1)
- *
- * Both of these share a common divisor, which is represented by
- * "normalize_factor" in the code below.
- */
- if (normalize_factor.file == BAD_FILE) {
- /* 1 / (2^b - 1) for b=<10,10,10,2> */
- normalize_factor = dst_reg(this, glsl_type::vec4_type);
- emit(MOV(writemask(normalize_factor, WRITEMASK_XYZ),
- brw_imm_f(1.0f / ((1<<10) - 1))));
- emit(MOV(writemask(normalize_factor, WRITEMASK_W),
- brw_imm_f(1.0f / ((1<<2) - 1))));
- }
-
- dst_reg dst = reg;
- dst.type = brw_type_for_base_type(glsl_type::vec4_type);
- emit(MOV(dst, src_reg((wa_flags & BRW_ATTRIB_WA_SIGN) ? reg_d : reg_ud)));
-
- /* For signed normalization, we want the numerator to be 2c+1. */
- if (wa_flags & BRW_ATTRIB_WA_SIGN) {
- emit(MUL(dst, src_reg(dst), brw_imm_f(2.0f)));
- emit(ADD(dst, src_reg(dst), brw_imm_f(1.0f)));
- }
-
- emit(MUL(dst, src_reg(dst), src_reg(normalize_factor)));
- }
- }
-
- if (wa_flags & BRW_ATTRIB_WA_SCALE) {
- dst_reg dst = reg;
- dst.type = brw_type_for_base_type(glsl_type::vec4_type);
- emit(MOV(dst, src_reg((wa_flags & BRW_ATTRIB_WA_SIGN) ? reg_d : reg_ud)));
- }
- }
- }
}