diff --git a/src/intel/compiler/brw_fs_nir.cpp b/src/intel/compiler/brw_fs_nir.cpp index 545e1bf18b1..fc34800df72 100644 --- a/src/intel/compiler/brw_fs_nir.cpp +++ b/src/intel/compiler/brw_fs_nir.cpp @@ -567,8 +567,46 @@ optimize_extract_to_float(nir_to_brw_state &ntb, const fs_builder &bld, op0.type = brw_type_for_nir_type(devinfo, (nir_alu_type)(nir_op_infos[src0->op].input_types[0] | nir_src_bit_size(src0->src[0].src))); + + /* It is not documented in the Bspec, but DG2 and newer platforms cannot do + * direct byte-to-float conversions from scalars. MR !30140 has more + * details. If the optimization is applied in cases that would require + * lower_regioning to do some lowering, the code generated will be much, + * much worse. + */ + if (devinfo->verx10 >= 125 && bytes == 1) { + /* If the source truly scalar, for example from the UNIFORM file, skip + * the optimize_extract_to_float optimization. + * + * Note: is_scalar values won't have zero stride until after the call to + * offset() below that applies the swizzle. + */ + if (is_uniform(op0)) + return false; + + /* If the dispatch width matches the scalar allocation width, then + * is_scalar can be demoted to non-is_scalar. This prevents offset() and + * component() (both called below) from setting the stride to zero, and + * that avoids the awful code generated by lower_regioning. + */ + if (op0.is_scalar) { + const unsigned allocation_width = 8 * reg_unit(ntb.devinfo); + if (ntb.bld.dispatch_width() != allocation_width) + return false; + + assert(bld.dispatch_width() == allocation_width); + op0.is_scalar = false; + } + } + op0 = offset(op0, bld, src0->src[0].swizzle[0]); + /* If the dispatch width matches the scalar allocation width, offset() will + * not modify the stride, but having source stride <0;1,0> is advantageous. + */ + if (op0.is_scalar) + op0 = component(op0, 0); + /* Bspec "Register Region Restrictions" for Xe says: * * "In case of all float point data types used in destination