diff --git a/src/compiler/nir/nir_divergence_analysis.c b/src/compiler/nir/nir_divergence_analysis.c index 1536b065d51..9ee3d805576 100644 --- a/src/compiler/nir/nir_divergence_analysis.c +++ b/src/compiler/nir/nir_divergence_analysis.c @@ -364,6 +364,7 @@ visit_intrinsic(nir_intrinsic_instr *instr, struct divergence_state *state) case nir_intrinsic_load_call_return_address_amd: case nir_intrinsic_load_indirect_address_intel: case nir_intrinsic_load_alpha_to_coverage_enable_ir3: + case nir_intrinsic_load_frag_shading_rate_intel: case nir_intrinsic_load_msaa_rate_intel: is_divergent = false; break; diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index 615f2699098..653442fe0e5 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -2656,6 +2656,9 @@ system_value("coverage_mask_intel", 1) # MSAA rate provided by the FS payload. system_value("msaa_rate_intel", 1) +# Raw fragment shading rate provided to the FS payload. +system_value("frag_shading_rate_intel", 2) + # Load a relocatable 32-bit value intrinsic("load_reloc_const_intel", dest_comp=1, bit_sizes=[32], indices=[PARAM_IDX, BASE], flags=[CAN_ELIMINATE, CAN_REORDER]) diff --git a/src/intel/compiler/brw/brw_from_nir.cpp b/src/intel/compiler/brw/brw_from_nir.cpp index 6106bacddbe..11aa0df5624 100644 --- a/src/intel/compiler/brw/brw_from_nir.cpp +++ b/src/intel/compiler/brw/brw_from_nir.cpp @@ -54,7 +54,6 @@ static void brw_from_nir_emit_intrinsic(nir_to_brw_state &ntb, const brw_builder static brw_reg emit_samplepos_setup(nir_to_brw_state &ntb); static brw_reg emit_sampleid_setup(nir_to_brw_state &ntb); static brw_reg emit_samplemaskin_setup(nir_to_brw_state &ntb); -static brw_reg emit_shading_rate_setup(nir_to_brw_state &ntb); static void brw_from_nir_emit_impl(nir_to_brw_state &ntb, nir_function_impl *impl); static void brw_from_nir_emit_cf_list(nir_to_brw_state &ntb, exec_list *list); @@ -222,12 +221,6 @@ emit_system_values_block(nir_to_brw_state &ntb, nir_block *block) } break; - case nir_intrinsic_load_frag_shading_rate: - reg = &ntb.system_values[SYSTEM_VALUE_FRAG_SHADING_RATE]; - if (reg->file == BAD_FILE) - *reg = emit_shading_rate_setup(ntb); - break; - default: break; } @@ -3600,49 +3593,54 @@ emit_samplemaskin_setup(nir_to_brw_state &ntb) return mask; } -static brw_reg -emit_shading_rate_setup(nir_to_brw_state &ntb) +static void +emit_frag_shading_rate_setup(nir_to_brw_state &ntb, brw_reg result) { const intel_device_info *devinfo = ntb.devinfo; const brw_builder &bld = ntb.bld; - assert(devinfo->ver >= 11); - struct brw_fs_prog_data *fs_prog_data = brw_fs_prog_data(bld.shader->prog_data); + const brw_builder abld = bld.annotate("compute fragment size"); + + result.type = BRW_TYPE_UD; + + bld.MOV(offset(result, bld, 0), brw_imm_ud(1)); + bld.MOV(offset(result, bld, 1), brw_imm_ud(1)); + /* Coarse pixel shading size fields overlap with other fields of not in - * coarse pixel dispatch mode, so report 0 when that's not the case. + * coarse pixel dispatch mode, so report (1, 1) when that's not the case. */ if (fs_prog_data->coarse_pixel_dispatch == INTEL_NEVER) - return brw_imm_ud(0); + return; - const brw_builder abld = bld.annotate("compute fragment shading rate"); - - /* The shading rates provided in the shader are the actual 2D shading - * rate while the SPIR-V built-in is the enum value that has the shading - * rate encoded as a bitfield. Fortunately, the bitfield value is just - * the shading rate divided by two and shifted. - */ + assert(devinfo->ver >= 11); /* r1.0 - 0:7 ActualCoarsePixelShadingSize.X */ brw_reg actual_x = brw_reg(retype(brw_vec1_grf(1, 0), BRW_TYPE_UB)); /* r1.0 - 15:8 ActualCoarsePixelShadingSize.Y */ brw_reg actual_y = byte_offset(actual_x, 1); - brw_reg int_rate_y = abld.SHR(actual_y, brw_imm_ud(1)); - brw_reg int_rate_x = abld.SHR(actual_x, brw_imm_ud(1)); + brw_reg coarse_size = abld.vgrf(BRW_TYPE_UD, 2); - brw_reg rate = abld.OR(abld.SHL(int_rate_x, brw_imm_ud(2)), int_rate_y); + bld.MOV(offset(coarse_size, bld, 0), actual_x); + bld.MOV(offset(coarse_size, bld, 1), actual_y); - if (fs_prog_data->coarse_pixel_dispatch == INTEL_ALWAYS) - return rate; + if (fs_prog_data->coarse_pixel_dispatch == INTEL_ALWAYS) { + for (unsigned i = 0; i < 2; i++) + bld.MOV(offset(result, bld, i), offset(coarse_size, bld, i)); + return; + } brw_check_dynamic_fs_config(abld, fs_prog_data, INTEL_FS_CONFIG_COARSE_RT_WRITES); - set_predicate(BRW_PREDICATE_NORMAL, abld.SEL(rate, rate, brw_imm_ud(0))); - - return rate; + for (unsigned i = 0; i < 2; i++) { + set_predicate(BRW_PREDICATE_NORMAL, + abld.SEL(offset(result, bld, i), + offset(coarse_size, bld, i), + offset(result, bld, i))); + } } /* Input data is organized with first the per-primitive values, followed @@ -3793,8 +3791,7 @@ brw_from_nir_emit_fs_intrinsic(nir_to_brw_state &ntb, case nir_intrinsic_load_helper_invocation: case nir_intrinsic_load_sample_mask_in: - case nir_intrinsic_load_sample_id: - case nir_intrinsic_load_frag_shading_rate: { + case nir_intrinsic_load_sample_id: { gl_system_value sv = nir_system_value_from_intrinsic(instr->intrinsic); brw_reg val = ntb.system_values[sv]; assert(val.file != BAD_FILE); @@ -3803,6 +3800,11 @@ brw_from_nir_emit_fs_intrinsic(nir_to_brw_state &ntb, break; } + case nir_intrinsic_load_frag_shading_rate_intel: { + emit_frag_shading_rate_setup(ntb, dest); + break; + } + case nir_intrinsic_load_coverage_mask_intel: { struct brw_fs_prog_data *fs_prog_data = brw_fs_prog_data(ntb.s.prog_data); assert(fs_prog_data->uses_sample_mask); diff --git a/src/intel/compiler/brw/brw_nir.c b/src/intel/compiler/brw/brw_nir.c index aac6a599441..cc8045a1fb0 100644 --- a/src/intel/compiler/brw/brw_nir.c +++ b/src/intel/compiler/brw/brw_nir.c @@ -1458,6 +1458,36 @@ fragment_top_block_or_after_wa_18019110168(nir_function_impl *impl) post_wa_18019110168_block : nir_start_block(impl); } +static bool +lower_frag_shading_rate(nir_builder *b, nir_intrinsic_instr *intrin, void *data) +{ + if (intrin->intrinsic != nir_intrinsic_load_frag_shading_rate) + return false; + + b->cursor = nir_before_instr(&intrin->instr); + + /* The shading rates provided in the shader are the actual 2D shading + * rate while the SPIR-V built-in is the enum value that has the shading + * rate encoded as a bitfield. Fortunately, the bitfield value is just + * the shading rate divided by two and shifted. + */ + nir_def *sr = nir_load_frag_shading_rate_intel(b); + nir_def *int_rate_x = nir_ushr_imm(b, nir_channel(b, sr, 0), 1); + nir_def *int_rate_y = nir_ushr_imm(b, nir_channel(b, sr, 1), 1); + nir_def *rate = nir_ior(b, nir_ishl_imm(b, int_rate_x, 2), int_rate_y); + + nir_def_replace(&intrin->def, rate); + + return true; +} + +static bool +brw_nir_lower_frag_shading_rate(nir_shader *nir) +{ + return nir_shader_intrinsics_pass(nir, lower_frag_shading_rate, + nir_metadata_control_flow, NULL); +} + void brw_nir_lower_fs_inputs(nir_shader *nir, const struct intel_device_info *devinfo, @@ -1525,6 +1555,9 @@ brw_nir_lower_fs_inputs(nir_shader *nir, if (brw_needs_vertex_attributes_bypass(nir)) brw_nir_lower_fs_barycentrics(nir); + if (devinfo->ver >= 11) + NIR_PASS(_, nir, brw_nir_lower_frag_shading_rate); + if (key->multisample_fbo == INTEL_NEVER) { nir_lower_single_sampled_options lss_opts = { .lower_sample_mask_in = key->coarse_pixel == INTEL_NEVER,