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:
@@ -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:
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 *
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user