diff --git a/.pick_status.json b/.pick_status.json index 0ee808f2c61..1cee26aff54 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -1704,7 +1704,7 @@ "description": "intel/brw: fixup wm_prog_data_barycentric_modes()", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null, "notes": null diff --git a/src/intel/compiler/brw_compiler.h b/src/intel/compiler/brw_compiler.h index 55deba7e2f8..b4a3d927ef1 100644 --- a/src/intel/compiler/brw_compiler.h +++ b/src/intel/compiler/brw_compiler.h @@ -1290,8 +1290,34 @@ wm_prog_data_barycentric_modes(const struct brw_wm_prog_data *prog_data, * "MSDISPMODE_PERSAMPLE is required in order to select Perspective * Sample or Non-perspective Sample barycentric coordinates." */ - modes &= ~(BITFIELD_BIT(BRW_BARYCENTRIC_PERSPECTIVE_SAMPLE) | - BITFIELD_BIT(BRW_BARYCENTRIC_NONPERSPECTIVE_SAMPLE)); + uint32_t sample_bits = (BITFIELD_BIT(BRW_BARYCENTRIC_PERSPECTIVE_SAMPLE) | + BITFIELD_BIT(BRW_BARYCENTRIC_NONPERSPECTIVE_SAMPLE)); + uint32_t requested_sample = modes & sample_bits; + modes &= ~sample_bits; + /* + * If the shader requested some sample modes and we have to disable + * them, make sure we add back the pixel variant back to not mess up the + * thread payload. + * + * Why does this works out? Because of the ordering in the thread payload : + * + * R7:10 Perspective Centroid Barycentric + * R11:14 Perspective Sample Barycentric + * R15:18 Linear Pixel Location Barycentric + * + * In the backend when persample dispatch is dynamic, we always select + * the sample barycentric and turn off the pixel location (even if + * requested through intrinsics). That way when we dynamically select + * pixel or sample dispatch, the barycentric always match, since the + * pixel location barycentric register offset will align with the sample + * barycentric. + */ + if (requested_sample) { + if (requested_sample & BITFIELD_BIT(BRW_BARYCENTRIC_PERSPECTIVE_SAMPLE)) + modes |= BITFIELD_BIT(BRW_BARYCENTRIC_PERSPECTIVE_PIXEL); + if (requested_sample & BITFIELD_BIT(BRW_BARYCENTRIC_NONPERSPECTIVE_SAMPLE)) + modes |= BITFIELD_BIT(BRW_BARYCENTRIC_NONPERSPECTIVE_PIXEL); + } } return modes; diff --git a/src/intel/compiler/brw_fs.cpp b/src/intel/compiler/brw_fs.cpp index 7ff4a286368..adbbff41467 100644 --- a/src/intel/compiler/brw_fs.cpp +++ b/src/intel/compiler/brw_fs.cpp @@ -1195,7 +1195,8 @@ fs_visitor::import_uniforms(fs_visitor *v) } enum brw_barycentric_mode -brw_barycentric_mode(nir_intrinsic_instr *intr) +brw_barycentric_mode(const struct brw_wm_prog_key *key, + nir_intrinsic_instr *intr) { const glsl_interp_mode mode = (enum glsl_interp_mode) nir_intrinsic_interp_mode(intr); @@ -1207,7 +1208,13 @@ brw_barycentric_mode(nir_intrinsic_instr *intr) switch (intr->intrinsic) { case nir_intrinsic_load_barycentric_pixel: case nir_intrinsic_load_barycentric_at_offset: - bary = BRW_BARYCENTRIC_PERSPECTIVE_PIXEL; + /* When per sample interpolation is dynamic, assume sample + * interpolation. We'll dynamically remap things so that the FS thread + * payload is not affected. + */ + bary = key->persample_interp == BRW_SOMETIMES ? + BRW_BARYCENTRIC_PERSPECTIVE_SAMPLE : + BRW_BARYCENTRIC_PERSPECTIVE_PIXEL; break; case nir_intrinsic_load_barycentric_centroid: bary = BRW_BARYCENTRIC_PERSPECTIVE_CENTROID; @@ -7340,6 +7347,7 @@ is_used_in_not_interp_frag_coord(nir_def *def) */ static unsigned brw_compute_barycentric_interp_modes(const struct intel_device_info *devinfo, + const struct brw_wm_prog_key *key, const nir_shader *shader) { unsigned barycentric_interp_modes = 0; @@ -7368,7 +7376,7 @@ brw_compute_barycentric_interp_modes(const struct intel_device_info *devinfo, nir_intrinsic_op bary_op = intrin->intrinsic; enum brw_barycentric_mode bary = - brw_barycentric_mode(intrin); + brw_barycentric_mode(key, intrin); barycentric_interp_modes |= 1 << bary; @@ -7577,7 +7585,7 @@ brw_nir_populate_wm_prog_data(nir_shader *shader, prog_data->inner_coverage = shader->info.fs.inner_coverage; prog_data->barycentric_interp_modes = - brw_compute_barycentric_interp_modes(devinfo, shader); + brw_compute_barycentric_interp_modes(devinfo, key, shader); /* From the BDW PRM documentation for 3DSTATE_WM: * diff --git a/src/intel/compiler/brw_fs.h b/src/intel/compiler/brw_fs.h index a57274250b9..8ca8b18e5a5 100644 --- a/src/intel/compiler/brw_fs.h +++ b/src/intel/compiler/brw_fs.h @@ -611,7 +611,8 @@ fs_reg setup_imm_b(const brw::fs_builder &bld, fs_reg setup_imm_ub(const brw::fs_builder &bld, uint8_t v); -enum brw_barycentric_mode brw_barycentric_mode(nir_intrinsic_instr *intr); +enum brw_barycentric_mode brw_barycentric_mode(const struct brw_wm_prog_key *key, + nir_intrinsic_instr *intr); uint32_t brw_fb_write_msg_control(const fs_inst *inst, const struct brw_wm_prog_data *prog_data); diff --git a/src/intel/compiler/brw_fs_nir.cpp b/src/intel/compiler/brw_fs_nir.cpp index 399fb5b80ba..f669b4fef26 100644 --- a/src/intel/compiler/brw_fs_nir.cpp +++ b/src/intel/compiler/brw_fs_nir.cpp @@ -4289,7 +4289,8 @@ fs_nir_emit_fs_intrinsic(nir_to_brw_state &ntb, case nir_intrinsic_load_barycentric_centroid: case nir_intrinsic_load_barycentric_sample: { /* Use the delta_xy values computed from the payload */ - enum brw_barycentric_mode bary = brw_barycentric_mode(instr); + enum brw_barycentric_mode bary = brw_barycentric_mode( + reinterpret_cast(s.key), instr); const fs_reg srcs[] = { offset(s.delta_xy[bary], bld, 0), offset(s.delta_xy[bary], bld, 1) }; bld.LOAD_PAYLOAD(dest, srcs, ARRAY_SIZE(srcs), 0); @@ -4384,7 +4385,8 @@ fs_nir_emit_fs_intrinsic(nir_to_brw_state &ntb, dst_xy = retype(get_nir_src(ntb, instr->src[0]), BRW_REGISTER_TYPE_F); } else { /* Use the delta_xy values computed from the payload */ - enum brw_barycentric_mode bary = brw_barycentric_mode(bary_intrinsic); + enum brw_barycentric_mode bary = brw_barycentric_mode( + reinterpret_cast(s.key), bary_intrinsic); dst_xy = s.delta_xy[bary]; }