pan/mdg: Use bifrost_nir_lower_store_component

Move the pass from the Bifrost compiler to the Midgard/Bifrost common code
directory, and take advantage of it on Midgard, where it fixes the same
tests as it fixed originally on Bifrost.

Signed-off-by: Alyssa Rosenzweig <alyssa@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19363>
This commit is contained in:
Alyssa Rosenzweig
2022-10-15 20:09:25 -04:00
committed by Marge Bot
parent 17589be72b
commit d0281fc16a
6 changed files with 118 additions and 73 deletions

View File

@@ -4686,68 +4686,6 @@ bi_opt_post_ra(bi_context *ctx)
}
}
/* If the shader packs multiple varyings into the same location with different
* location_frac, we'll need to lower to a single varying store that collects
* all of the channels together.
*/
static bool
bifrost_nir_lower_store_component(struct nir_builder *b,
nir_instr *instr, void *data)
{
if (instr->type != nir_instr_type_intrinsic)
return false;
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
if (intr->intrinsic != nir_intrinsic_store_output)
return false;
struct hash_table_u64 *slots = data;
unsigned component = nir_intrinsic_component(intr);
nir_src *slot_src = nir_get_io_offset_src(intr);
uint64_t slot = nir_src_as_uint(*slot_src) + nir_intrinsic_base(intr);
nir_intrinsic_instr *prev = _mesa_hash_table_u64_search(slots, slot);
unsigned mask = (prev ? nir_intrinsic_write_mask(prev) : 0);
nir_ssa_def *value = intr->src[0].ssa;
b->cursor = nir_before_instr(&intr->instr);
nir_ssa_def *undef = nir_ssa_undef(b, 1, value->bit_size);
nir_ssa_def *channels[4] = { undef, undef, undef, undef };
/* Copy old */
u_foreach_bit(i, mask) {
assert(prev != NULL);
nir_ssa_def *prev_ssa = prev->src[0].ssa;
channels[i] = nir_channel(b, prev_ssa, i);
}
/* Copy new */
unsigned new_mask = nir_intrinsic_write_mask(intr);
mask |= (new_mask << component);
u_foreach_bit(i, new_mask) {
assert(component + i < 4);
channels[component + i] = nir_channel(b, value, i);
}
intr->num_components = util_last_bit(mask);
nir_instr_rewrite_src_ssa(instr, &intr->src[0],
nir_vec(b, channels, intr->num_components));
nir_intrinsic_set_component(intr, 0);
nir_intrinsic_set_write_mask(intr, mask);
if (prev) {
_mesa_hash_table_u64_remove(slots, slot);
nir_instr_remove(&prev->instr);
}
_mesa_hash_table_u64_insert(slots, slot, intr);
return false;
}
/* Dead code elimination for branches at the end of a block - only one branch
* per block is legal semantically, but unreachable jumps can be generated.
* Likewise on Bifrost we can generate jumps to the terminal block which need
@@ -4934,12 +4872,7 @@ bi_finalize_nir(nir_shader *nir, unsigned gpu_id, bool is_blend)
BITFIELD64_BIT(VARYING_SLOT_PSIZ), false);
}
struct hash_table_u64 *stores = _mesa_hash_table_u64_create(NULL);
NIR_PASS_V(nir, nir_shader_instructions_pass,
bifrost_nir_lower_store_component,
nir_metadata_block_index |
nir_metadata_dominance, stores);
_mesa_hash_table_u64_destroy(stores);
NIR_PASS_V(nir, pan_nir_lower_store_component);
}
NIR_PASS_V(nir, nir_lower_ssbo);

View File

@@ -40,11 +40,6 @@ dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_min_reverse_src_dst_x,Fa
dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_min_reverse_src_dst_y,Fail
dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_min_reverse_src_x,Fail
dEQP-GLES3.functional.fbo.blit.rect.nearest_consistency_min_reverse_src_y,Fail
dEQP-GLES31.functional.separate_shader.random.35,Fail
dEQP-GLES31.functional.separate_shader.random.68,Fail
dEQP-GLES31.functional.separate_shader.random.79,Fail
dEQP-GLES31.functional.separate_shader.random.80,Fail
dEQP-GLES31.functional.separate_shader.random.89,Fail
dEQP-GLES31.functional.texture.gather.basic.cube.depth32f.no_corners.size_pot.compare_greater.clamp_to_edge_repeat,Fail
dEQP-GLES31.functional.texture.gather.basic.cube.depth32f.no_corners.size_pot.compare_greater.mirrored_repeat_clamp_to_edge,Fail
dEQP-GLES31.functional.texture.gather.basic.cube.depth32f.no_corners.size_pot.compare_greater.repeat_mirrored_repeat,Fail

View File

@@ -3186,6 +3186,16 @@ midgard_compile_shader_nir(nir_shader *nir,
NIR_PASS_V(nir, nir_lower_io, nir_var_shader_in | nir_var_shader_out,
glsl_type_size, 0);
if (ctx->stage == MESA_SHADER_VERTEX) {
/* nir_lower[_explicit]_io is lazy and emits mul+add chains even
* for offsets it could figure out are constant. Do some
* constant folding before pan_nir_lower_store_component below.
*/
NIR_PASS_V(nir, nir_opt_constant_folding);
NIR_PASS_V(nir, pan_nir_lower_store_component);
}
NIR_PASS_V(nir, nir_lower_ssbo);
NIR_PASS_V(nir, pan_nir_lower_zs_store);

View File

@@ -29,6 +29,7 @@ libpanfrost_util_files = files(
'pan_lower_framebuffer.c',
'pan_lower_helper_invocation.c',
'pan_lower_sample_position.c',
'pan_lower_store_component.c',
'pan_lower_writeout.c',
'pan_lower_xfb.c',
'pan_lower_64bit_intrin.c',

View File

@@ -502,6 +502,7 @@ bool pan_has_dest_mod(nir_dest **dest, nir_op op);
#define PAN_WRITEOUT_2 8
bool pan_nir_lower_zs_store(nir_shader *nir);
bool pan_nir_lower_store_component(nir_shader *shader);
bool pan_nir_lower_64bit_intrin(nir_shader *shader);

View File

@@ -0,0 +1,105 @@
/*
* Copyright (C) 2020-2022 Collabora Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Authors (Collabora):
* Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
*/
#include "pan_ir.h"
#include "compiler/nir/nir_builder.h"
/*
* If the shader packs multiple varyings into the same location with different
* location_frac, we'll need to lower to a single varying store that collects
* all of the channels together. This is because the varying instruction on
* Midgard and Bifrost is slot-based, writing out an entire vec4 slot at a time.
*/
static bool
lower_store_component(nir_builder *b, nir_instr *instr, void *data)
{
if (instr->type != nir_instr_type_intrinsic)
return false;
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
if (intr->intrinsic != nir_intrinsic_store_output)
return false;
struct hash_table_u64 *slots = data;
unsigned component = nir_intrinsic_component(intr);
nir_src *slot_src = nir_get_io_offset_src(intr);
uint64_t slot = nir_src_as_uint(*slot_src) + nir_intrinsic_base(intr);
nir_intrinsic_instr *prev = _mesa_hash_table_u64_search(slots, slot);
unsigned mask = (prev ? nir_intrinsic_write_mask(prev) : 0);
nir_ssa_def *value = intr->src[0].ssa;
b->cursor = nir_before_instr(&intr->instr);
nir_ssa_def *undef = nir_ssa_undef(b, 1, value->bit_size);
nir_ssa_def *channels[4] = { undef, undef, undef, undef };
/* Copy old */
u_foreach_bit(i, mask) {
assert(prev != NULL);
nir_ssa_def *prev_ssa = prev->src[0].ssa;
channels[i] = nir_channel(b, prev_ssa, i);
}
/* Copy new */
unsigned new_mask = nir_intrinsic_write_mask(intr);
mask |= (new_mask << component);
u_foreach_bit(i, new_mask) {
assert(component + i < 4);
channels[component + i] = nir_channel(b, value, i);
}
intr->num_components = util_last_bit(mask);
nir_instr_rewrite_src_ssa(instr, &intr->src[0],
nir_vec(b, channels, intr->num_components));
nir_intrinsic_set_component(intr, 0);
nir_intrinsic_set_write_mask(intr, mask);
if (prev) {
_mesa_hash_table_u64_remove(slots, slot);
nir_instr_remove(&prev->instr);
}
_mesa_hash_table_u64_insert(slots, slot, intr);
return false;
}
bool
pan_nir_lower_store_component(nir_shader *s)
{
assert(s->info.stage == MESA_SHADER_VERTEX);
struct hash_table_u64 *stores = _mesa_hash_table_u64_create(NULL);
bool progress = nir_shader_instructions_pass(s, lower_store_component,
nir_metadata_block_index |
nir_metadata_dominance,
stores);
_mesa_hash_table_u64_destroy(stores);
return progress;
}