panfrost: add intrinsic to load frag coord at a barycentric

This is needed for noperspective lowering, where we need to multiply the
varying value by gl_FragCoord.w at the same barycentric as the varying.
Normal nir_load_frag_coord_zw instructions are lowered to the new
intrinsic on bifrost with the pan_lower_frag_coord_zw pass.

Signed-off-by: Benjamin Lee <benjamin.lee@collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32127>
This commit is contained in:
Benjamin Lee
2024-12-11 19:07:10 -08:00
committed by Marge Bot
parent 9033e64b02
commit 6f541e2016
7 changed files with 60 additions and 5 deletions
@@ -763,6 +763,7 @@ visit_intrinsic(nir_intrinsic_instr *instr, struct divergence_state *state)
case nir_intrinsic_load_line_coord:
case nir_intrinsic_load_frag_coord:
case nir_intrinsic_load_frag_coord_zw:
case nir_intrinsic_load_frag_coord_zw_pan:
case nir_intrinsic_load_frag_coord_unscaled_ir3:
case nir_intrinsic_load_pixel_coord:
case nir_intrinsic_load_fully_covered:
+5
View File
@@ -1504,6 +1504,11 @@ store("raw_output_pan", [], [IO_SEMANTICS, BASE])
store("combined_output_pan", [1, 1, 1, 4], [IO_SEMANTICS, COMPONENT, SRC_TYPE, DEST_TYPE])
load("raw_output_pan", [1], [IO_SEMANTICS], [CAN_ELIMINATE, CAN_REORDER])
# Like the frag_coord_zw intrinsic, but takes a barycentric. This is needed for
# noperspective lowering.
# src[] = { barycoord }
intrinsic("load_frag_coord_zw_pan", [2], dest_comp=1, indices=[COMPONENT], flags=[CAN_ELIMINATE, CAN_REORDER], bit_sizes=[32])
# Loads the sampler paramaters <min_lod, max_lod, lod_bias>
# src[] = { sampler_index }
load("sampler_lod_parameters_pan", [1], flags=[CAN_ELIMINATE, CAN_REORDER])
+1
View File
@@ -112,6 +112,7 @@ can_sink_instr(nir_instr *instr, nir_move_options options, bool *can_mov_out_of_
case nir_intrinsic_load_per_vertex_input:
case nir_intrinsic_load_frag_coord:
case nir_intrinsic_load_frag_coord_zw:
case nir_intrinsic_load_frag_coord_zw_pan:
case nir_intrinsic_load_pixel_coord:
case nir_intrinsic_load_attribute_pan:
return options & nir_move_load_input;
+16 -5
View File
@@ -1654,11 +1654,21 @@ bi_emit_atomic_i32_to(bi_builder *b, bi_index dst, bi_index addr, bi_index arg,
}
static void
bi_emit_load_frag_coord_zw(bi_builder *b, bi_index dst, unsigned channel)
bi_emit_load_frag_coord_zw_pan(bi_builder *b, nir_intrinsic_instr *instr)
{
bi_index dst = bi_def_index(&instr->def);
unsigned channel = nir_intrinsic_component(instr);
nir_intrinsic_instr *bary = nir_src_as_intrinsic(instr->src[0]);
enum bi_sample sample = bi_interp_for_intrinsic(bary->intrinsic);
bi_index src0 = bi_varying_src0_for_barycentric(b, bary);
/* .explicit is not supported with frag_z */
if (channel == 2)
assert(sample != BI_SAMPLE_EXPLICIT);
bi_ld_var_special_to(
b, dst, bi_zero(), BI_REGISTER_FORMAT_F32, BI_SAMPLE_CENTER,
BI_UPDATE_CLOBBER,
b, dst, src0, BI_REGISTER_FORMAT_F32, sample, BI_UPDATE_CLOBBER,
(channel == 2) ? BI_VARYING_NAME_FRAG_Z : BI_VARYING_NAME_FRAG_W,
BI_VECSIZE_NONE);
}
@@ -1904,8 +1914,8 @@ bi_emit_intrinsic(bi_builder *b, nir_intrinsic_instr *instr)
bi_mov_i32_to(b, dst, bi_preload(b, 59));
break;
case nir_intrinsic_load_frag_coord_zw:
bi_emit_load_frag_coord_zw(b, dst, nir_intrinsic_component(instr));
case nir_intrinsic_load_frag_coord_zw_pan:
bi_emit_load_frag_coord_zw_pan(b, instr);
break;
case nir_intrinsic_load_converted_output_pan:
@@ -5334,6 +5344,7 @@ bifrost_preprocess_nir(nir_shader *nir, unsigned gpu_id)
NIR_PASS(_, nir, nir_lower_var_copies);
NIR_PASS(_, nir, nir_lower_alu);
NIR_PASS(_, nir, nir_lower_frag_coord_to_pixel_coord);
NIR_PASS(_, nir, pan_nir_lower_frag_coord_zw);
}
static bi_context *
+1
View File
@@ -9,6 +9,7 @@ libpanfrost_util_files = files(
'pan_ir.c',
'pan_ir.h',
'pan_liveness.c',
'pan_lower_frag_coord_zw.c',
'pan_lower_framebuffer.c',
'pan_lower_helper_invocation.c',
'pan_lower_image_index.c',
+2
View File
@@ -386,6 +386,8 @@ bool pan_nir_lower_store_component(nir_shader *shader);
bool pan_nir_lower_image_ms(nir_shader *shader);
bool pan_nir_lower_frag_coord_zw(nir_shader *shader);
bool pan_lower_helper_invocation(nir_shader *shader);
bool pan_lower_sample_pos(nir_shader *shader);
bool pan_lower_xfb(nir_shader *nir);
@@ -0,0 +1,34 @@
/*
* Copyright © 2024 Collabora Ltd.
* SPDX-License-Identifier: MIT
*/
#include "compiler/nir/nir_builder.h"
#include "pan_ir.h"
/* Lowers nir_load_frag_coord_zw to nir_load_frag_coord_zw_pan. */
static bool
lower_frag_coord_zw(nir_builder *b, nir_intrinsic_instr *intrin, void *data)
{
if (intrin->intrinsic != nir_intrinsic_load_frag_coord_zw)
return false;
b->cursor = nir_before_instr(&intrin->instr);
nir_def *bary = nir_load_barycentric_pixel(b, 32,
.interp_mode = INTERP_MODE_NOPERSPECTIVE
);
unsigned component = nir_intrinsic_component(intrin);
nir_def *new = nir_load_frag_coord_zw_pan(b, bary, .component = component);
nir_def_replace(&intrin->def, new);
return true;
}
bool
pan_nir_lower_frag_coord_zw(nir_shader *shader)
{
return nir_shader_intrinsics_pass(shader, lower_frag_coord_zw,
nir_metadata_control_flow, NULL);
}