On Tue, Nov 24, 2015 at 10:35 PM, Kenneth Graunke <kenn...@whitecape.org> wrote: > 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.) > > Cc: "11.1 11.0" <mesa-sta...@lists.freedesktop.org> > Signed-off-by: Kenneth Graunke <kenn...@whitecape.org> > --- > src/mesa/drivers/dri/i965/brw_fs.cpp | 155 > ++++++++++++++++--------------- > src/mesa/drivers/dri/i965/brw_fs.h | 4 +- > src/mesa/drivers/dri/i965/brw_fs_nir.cpp | 3 +- > 3 files changed, 82 insertions(+), 80 deletions(-) > > I seem to recall that passing by non-const reference is generally frowned > upon by most folks here (including Paul), so I'm happy to convert to pointers > if people would prefer that. It's just a lot more asterisks. > > I've also thought about renaming this to emit_general_interpolation_helper > and making emit_general_interpolation just take a nir_variable, so that it > hides the pass-by-reference while also simplifying the interface. > > diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp > b/src/mesa/drivers/dri/i965/brw_fs.cpp > index 777cee5..ab055f8 100644 > --- a/src/mesa/drivers/dri/i965/brw_fs.cpp > +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp > @@ -1056,30 +1056,16 @@ 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,
I'd rather we use pointers for inout arguments. That way you can tell in the code below when the change can escape the function. > const glsl_type *type, > glsl_interp_qualifier > interpolation_mode, > - int location, bool mod_centroid, > + int &location, bool mod_centroid, here too Other than that, the recursion looks much more sane. I didn't double-check that all the code you moved was the same. With the inout parameters switched to pointers, Reviewed-by: Jason Ekstrand <jason.ekstr...@intel.com> > 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; > @@ -1090,71 +1076,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 2d408b2..aded70b 100644 > --- a/src/mesa/drivers/dri/i965/brw_fs.h > +++ b/src/mesa/drivers/dri/i965/brw_fs.h > @@ -205,10 +205,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 c439da2..a094eef 100644 > --- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp > +++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp > @@ -81,9 +81,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 { > + 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); > } > } > -- > 2.6.2 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev