diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c index 6e75b0b4099..f28e41ece90 100644 --- a/src/compiler/nir/nir.c +++ b/src/compiler/nir/nir.c @@ -2247,6 +2247,8 @@ nir_intrinsic_from_system_value(gl_system_value val) return nir_intrinsic_load_ray_geometry_index; case SYSTEM_VALUE_RAY_INSTANCE_CUSTOM_INDEX: return nir_intrinsic_load_ray_instance_custom_index; + case SYSTEM_VALUE_FRAG_SHADING_RATE: + return nir_intrinsic_load_frag_shading_rate; default: unreachable("system value does not directly correspond to intrinsic"); } @@ -2382,6 +2384,8 @@ nir_system_value_from_intrinsic(nir_intrinsic_op intrin) return SYSTEM_VALUE_RAY_GEOMETRY_INDEX; case nir_intrinsic_load_ray_instance_custom_index: return SYSTEM_VALUE_RAY_INSTANCE_CUSTOM_INDEX; + case nir_intrinsic_load_frag_shading_rate: + return SYSTEM_VALUE_FRAG_SHADING_RATE; default: unreachable("intrinsic doesn't produce a system value"); } diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 9b2debc846f..80376c57217 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -3070,6 +3070,7 @@ typedef enum { nir_divergence_single_patch_per_tcs_subgroup = (1 << 1), nir_divergence_single_patch_per_tes_subgroup = (1 << 2), nir_divergence_view_index_uniform = (1 << 3), + nir_divergence_single_frag_shading_rate_per_subgroup = (1 << 4), } nir_divergence_options; typedef struct nir_shader_compiler_options { diff --git a/src/compiler/nir/nir_divergence_analysis.c b/src/compiler/nir/nir_divergence_analysis.c index e76e8dfc394..43977716048 100644 --- a/src/compiler/nir/nir_divergence_analysis.c +++ b/src/compiler/nir/nir_divergence_analysis.c @@ -136,6 +136,9 @@ visit_intrinsic(nir_shader *shader, nir_intrinsic_instr *instr) break; /* Intrinsics with divergence depending on shader stage and hardware */ + case nir_intrinsic_load_frag_shading_rate: + is_divergent = !(options & nir_divergence_single_frag_shading_rate_per_subgroup); + break; case nir_intrinsic_load_input: is_divergent = instr->src[0].ssa->divergent; if (stage == MESA_SHADER_FRAGMENT) diff --git a/src/compiler/nir/nir_gather_info.c b/src/compiler/nir/nir_gather_info.c index 097aaa8e541..285206bab75 100644 --- a/src/compiler/nir/nir_gather_info.c +++ b/src/compiler/nir/nir_gather_info.c @@ -465,6 +465,7 @@ gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader, case nir_intrinsic_load_draw_id: case nir_intrinsic_load_invocation_id: case nir_intrinsic_load_frag_coord: + case nir_intrinsic_load_frag_shading_rate: case nir_intrinsic_load_point_coord: case nir_intrinsic_load_line_coord: case nir_intrinsic_load_front_face: diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index 952650fd4fd..f1626bbab0b 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -943,6 +943,15 @@ store("global", [1], [WRITE_MASK, ACCESS, ALIGN_MUL, ALIGN_OFFSET]) # src[] = { value, offset }. store("scratch", [1], [ALIGN_MUL, ALIGN_OFFSET, WRITE_MASK]) +# A bit field to implement SPIRV FragmentShadingRateKHR +# bit | name | description +# 0 | Vertical2Pixels | Fragment invocation covers 2 pixels vertically +# 1 | Vertical4Pixels | Fragment invocation covers 4 pixels vertically +# 2 | Horizontal2Pixels | Fragment invocation covers 2 pixels horizontally +# 3 | Horizontal4Pixels | Fragment invocation covers 4 pixels horizontally +intrinsic("load_frag_shading_rate", dest_comp=1, bit_sizes=[32], + flags=[CAN_ELIMINATE, CAN_REORDER]) + # IR3-specific version of most SSBO intrinsics. The only different # compare to the originals is that they add an extra source to hold # the dword-offset, which is needed by the backend code apart from diff --git a/src/compiler/nir/nir_opt_peephole_select.c b/src/compiler/nir/nir_opt_peephole_select.c index 01efb84422e..7c40e4bac21 100644 --- a/src/compiler/nir/nir_opt_peephole_select.c +++ b/src/compiler/nir/nir_opt_peephole_select.c @@ -113,6 +113,7 @@ block_check_for_allowed_instrs(nir_block *block, unsigned *count, case nir_intrinsic_load_subgroup_id: case nir_intrinsic_load_subgroup_invocation: case nir_intrinsic_load_num_subgroups: + case nir_intrinsic_load_frag_shading_rate: if (!alu_ok) return false; break; diff --git a/src/compiler/shader_enums.c b/src/compiler/shader_enums.c index 7114877f73b..543678fcea4 100644 --- a/src/compiler/shader_enums.c +++ b/src/compiler/shader_enums.c @@ -304,6 +304,7 @@ gl_system_value_name(gl_system_value sysval) ENUM(SYSTEM_VALUE_RAY_GEOMETRY_INDEX), ENUM(SYSTEM_VALUE_GS_HEADER_IR3), ENUM(SYSTEM_VALUE_TCS_HEADER_IR3), + ENUM(SYSTEM_VALUE_FRAG_SHADING_RATE), }; STATIC_ASSERT(ARRAY_SIZE(names) == SYSTEM_VALUE_MAX); return NAME(sysval); diff --git a/src/compiler/shader_enums.h b/src/compiler/shader_enums.h index a4d2191db33..30020256c5e 100644 --- a/src/compiler/shader_enums.h +++ b/src/compiler/shader_enums.h @@ -288,7 +288,8 @@ typedef enum VARYING_SLOT_BOUNDING_BOX1, /* Only appears as TCS output. */ VARYING_SLOT_VIEW_INDEX, VARYING_SLOT_VIEWPORT_MASK, /* Does not appear in FS */ - VARYING_SLOT_VAR0, /* First generic varying slot */ + VARYING_SLOT_PRIMITIVE_SHADING_RATE = VARYING_SLOT_FACE, /* Does not appear in FS. */ + VARYING_SLOT_VAR0 = 32, /* First generic varying slot */ /* the remaining are simply for the benefit of gl_varying_slot_name() * and not to be construed as an upper bound: */ @@ -708,6 +709,11 @@ typedef enum SYSTEM_VALUE_GS_HEADER_IR3, SYSTEM_VALUE_TCS_HEADER_IR3, + /** + * Fragment shading rate used for KHR_fragment_shading_rate (Vulkan). + */ + SYSTEM_VALUE_FRAG_SHADING_RATE, + SYSTEM_VALUE_MAX /**< Number of values */ } gl_system_value;