Module: Mesa Branch: master Commit: 3e9003e9cf55265ab1fb6522dc5cbb2f455ea1f9 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=3e9003e9cf55265ab1fb6522dc5cbb2f455ea1f9
Author: Kenneth Graunke <[email protected]> Date: Thu Nov 19 20:03:25 2015 -0800 i965: Fix fragment shader struct inputs. Apparently we have literally no support for FS varying struct inputs. This is somewhat surprising, given that we've had tests for that very feature that have been passing for a long time. Normally, varying packing splits up structures for us, so we don't see them in the backend. However, with SSO, varying packing isn't around to save us, and we get actual structs that we have to handle. This patch changes fs_visitor::emit_general_interpolation() to work recursively, properly handling nested structs/arrays/and so on. (It's easier to read with diff -b, as indentation changes.) When using the vec4 VS backend, this fixes rendering in an upcoming game from Feral Interactive. (The scalar VS backend requires additional bug fixes in the next patch.) v2: Use pointers instead of pass-by-mutable-reference (Jason, Matt). Cc: "11.1 11.0" <[email protected]> Signed-off-by: Kenneth Graunke <[email protected]> Reviewed-by: Jason Ekstrand <[email protected]> Reviewed-by: Matt Turner <[email protected]> --- src/mesa/drivers/dri/i965/brw_fs.cpp | 157 +++++++++++++++--------------- src/mesa/drivers/dri/i965/brw_fs.h | 4 +- src/mesa/drivers/dri/i965/brw_fs_nir.cpp | 5 +- 3 files changed, 84 insertions(+), 82 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index 29f19cc..7904f4d 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -1043,33 +1043,19 @@ fs_visitor::emit_linterp(const fs_reg &attr, const fs_reg &interp, } void -fs_visitor::emit_general_interpolation(fs_reg attr, const char *name, +fs_visitor::emit_general_interpolation(fs_reg *attr, const char *name, const glsl_type *type, glsl_interp_qualifier interpolation_mode, - int location, bool mod_centroid, + int *location, bool mod_centroid, bool mod_sample) { - attr.type = brw_type_for_base_type(type->get_scalar_type()); - assert(stage == MESA_SHADER_FRAGMENT); brw_wm_prog_data *prog_data = (brw_wm_prog_data*) this->prog_data; brw_wm_prog_key *key = (brw_wm_prog_key*) this->key; - unsigned int array_elements; - - if (type->is_array()) { - array_elements = type->arrays_of_arrays_size(); - if (array_elements == 0) { - fail("dereferenced array '%s' has length 0\n", name); - } - type = type->without_array(); - } else { - array_elements = 1; - } - if (interpolation_mode == INTERP_QUALIFIER_NONE) { bool is_gl_Color = - location == VARYING_SLOT_COL0 || location == VARYING_SLOT_COL1; + *location == VARYING_SLOT_COL0 || *location == VARYING_SLOT_COL1; if (key->flat_shade && is_gl_Color) { interpolation_mode = INTERP_QUALIFIER_FLAT; } else { @@ -1077,71 +1063,86 @@ fs_visitor::emit_general_interpolation(fs_reg attr, const char *name, } } - for (unsigned int i = 0; i < array_elements; i++) { - for (unsigned int j = 0; j < type->matrix_columns; j++) { - if (prog_data->urb_setup[location] == -1) { - /* If there's no incoming setup data for this slot, don't - * emit interpolation for it. - */ - attr = offset(attr, bld, type->vector_elements); - location++; - continue; - } + if (type->is_array() || type->is_matrix()) { + const glsl_type *elem_type = glsl_get_array_element(type); + const unsigned length = glsl_get_length(type); - if (interpolation_mode == INTERP_QUALIFIER_FLAT) { - /* Constant interpolation (flat shading) case. The SF has - * handed us defined values in only the constant offset - * field of the setup reg. - */ - for (unsigned int k = 0; k < type->vector_elements; k++) { - struct brw_reg interp = interp_reg(location, k); - interp = suboffset(interp, 3); - interp.type = attr.type; - bld.emit(FS_OPCODE_CINTERP, attr, fs_reg(interp)); - attr = offset(attr, bld, 1); - } - } else { - /* Smooth/noperspective interpolation case. */ - for (unsigned int k = 0; k < type->vector_elements; k++) { - struct brw_reg interp = interp_reg(location, k); - if (devinfo->needs_unlit_centroid_workaround && mod_centroid) { - /* Get the pixel/sample mask into f0 so that we know - * which pixels are lit. Then, for each channel that is - * unlit, replace the centroid data with non-centroid - * data. - */ - bld.emit(FS_OPCODE_MOV_DISPATCH_TO_FLAGS); - - fs_inst *inst; - inst = emit_linterp(attr, fs_reg(interp), interpolation_mode, - false, false); - inst->predicate = BRW_PREDICATE_NORMAL; - inst->predicate_inverse = true; - if (devinfo->has_pln) - inst->no_dd_clear = true; - - inst = emit_linterp(attr, fs_reg(interp), interpolation_mode, - mod_centroid && !key->persample_shading, - mod_sample || key->persample_shading); - inst->predicate = BRW_PREDICATE_NORMAL; - inst->predicate_inverse = false; - if (devinfo->has_pln) - inst->no_dd_check = true; + for (unsigned i = 0; i < length; i++) { + emit_general_interpolation(attr, name, elem_type, interpolation_mode, + location, mod_centroid, mod_sample); + } + } else if (type->is_record()) { + for (unsigned i = 0; i < type->length; i++) { + const glsl_type *field_type = type->fields.structure[i].type; + emit_general_interpolation(attr, name, field_type, interpolation_mode, + location, mod_centroid, mod_sample); + } + } else { + assert(type->is_scalar() || type->is_vector()); - } else { - emit_linterp(attr, fs_reg(interp), interpolation_mode, - mod_centroid && !key->persample_shading, - mod_sample || key->persample_shading); - } - if (devinfo->gen < 6 && interpolation_mode == INTERP_QUALIFIER_SMOOTH) { - bld.MUL(attr, attr, this->pixel_w); - } - attr = offset(attr, bld, 1); - } + if (prog_data->urb_setup[*location] == -1) { + /* If there's no incoming setup data for this slot, don't + * emit interpolation for it. + */ + *attr = offset(*attr, bld, type->vector_elements); + (*location)++; + return; + } - } - location++; + attr->type = brw_type_for_base_type(type->get_scalar_type()); + + if (interpolation_mode == INTERP_QUALIFIER_FLAT) { + /* Constant interpolation (flat shading) case. The SF has + * handed us defined values in only the constant offset + * field of the setup reg. + */ + for (unsigned int i = 0; i < type->vector_elements; i++) { + struct brw_reg interp = interp_reg(*location, i); + interp = suboffset(interp, 3); + interp.type = attr->type; + bld.emit(FS_OPCODE_CINTERP, *attr, fs_reg(interp)); + *attr = offset(*attr, bld, 1); + } + } else { + /* Smooth/noperspective interpolation case. */ + for (unsigned int i = 0; i < type->vector_elements; i++) { + struct brw_reg interp = interp_reg(*location, i); + if (devinfo->needs_unlit_centroid_workaround && mod_centroid) { + /* Get the pixel/sample mask into f0 so that we know + * which pixels are lit. Then, for each channel that is + * unlit, replace the centroid data with non-centroid + * data. + */ + bld.emit(FS_OPCODE_MOV_DISPATCH_TO_FLAGS); + + fs_inst *inst; + inst = emit_linterp(*attr, fs_reg(interp), interpolation_mode, + false, false); + inst->predicate = BRW_PREDICATE_NORMAL; + inst->predicate_inverse = true; + if (devinfo->has_pln) + inst->no_dd_clear = true; + + inst = emit_linterp(*attr, fs_reg(interp), interpolation_mode, + mod_centroid && !key->persample_shading, + mod_sample || key->persample_shading); + inst->predicate = BRW_PREDICATE_NORMAL; + inst->predicate_inverse = false; + if (devinfo->has_pln) + inst->no_dd_check = true; + + } else { + emit_linterp(*attr, fs_reg(interp), interpolation_mode, + mod_centroid && !key->persample_shading, + mod_sample || key->persample_shading); + } + if (devinfo->gen < 6 && interpolation_mode == INTERP_QUALIFIER_SMOOTH) { + bld.MUL(*attr, *attr, this->pixel_w); + } + *attr = offset(*attr, bld, 1); + } } + (*location)++; } } diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index 278d8a1..621d8d5 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -185,10 +185,10 @@ public: fs_reg *emit_frontfacing_interpolation(); fs_reg *emit_samplepos_setup(); fs_reg *emit_sampleid_setup(); - void emit_general_interpolation(fs_reg attr, const char *name, + void emit_general_interpolation(fs_reg *attr, const char *name, const glsl_type *type, glsl_interp_qualifier interpolation_mode, - int location, bool mod_centroid, + int *location, bool mod_centroid, bool mod_sample); fs_reg *emit_vs_system_value(int location); void emit_interpolation_setup_gen4(); diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp index 15bd98f..8495eba 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp @@ -76,9 +76,10 @@ fs_visitor::nir_setup_inputs() reg.type = BRW_REGISTER_TYPE_D; bld.emit(FS_OPCODE_CINTERP, retype(input, BRW_REGISTER_TYPE_D), reg); } else { - emit_general_interpolation(input, var->name, var->type, + int location = var->data.location; + emit_general_interpolation(&input, var->name, var->type, (glsl_interp_qualifier) var->data.interpolation, - var->data.location, var->data.centroid, + &location, var->data.centroid, var->data.sample); } } _______________________________________________ mesa-commit mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/mesa-commit
