From c4f423aa366548b919ed78407bacab032a077398 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 19 Apr 2019 11:12:34 -0700 Subject: [PATCH] freedreno/ir3: lower load_barycentric_at_sample This lowers load_barycentric_at_sample to load_sample_pos_from_id plus load_barycentric_at_offset. Signed-off-by: Rob Clark --- src/compiler/nir/nir_intrinsics.py | 7 ++ src/freedreno/ir3/ir3_nir.h | 1 + .../ir3/ir3_nir_lower_load_barycentric_at_sample.c | 130 +++++++++++++++++++++ src/freedreno/ir3/meson.build | 1 + 4 files changed, 139 insertions(+) create mode 100644 src/freedreno/ir3/ir3_nir_lower_load_barycentric_at_sample.c diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index bf06f8385a5..db1cf5c7b79 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -602,6 +602,13 @@ barycentric("at_sample", [1]) # src[] = { offset.xy }. barycentric("at_offset", [2]) +# Load sample position: +# +# Takes a sample # and returns a sample position. Used for lowering +# interpolateAtSample() to interpolateAtOffset() +intrinsic("load_sample_pos_from_id", src_comp=[1], dest_comp=2, + flags=[CAN_ELIMINATE, CAN_REORDER]) + # Load operations pull data from some piece of GPU memory. All load # operations operate in terms of offsets into some piece of theoretical # memory. Loads from externally visible memory (UBO and SSBO) simply take a diff --git a/src/freedreno/ir3/ir3_nir.h b/src/freedreno/ir3/ir3_nir.h index 1fe0bb0d094..eefe5f32f8f 100644 --- a/src/freedreno/ir3/ir3_nir.h +++ b/src/freedreno/ir3/ir3_nir.h @@ -38,6 +38,7 @@ void ir3_nir_scan_driver_consts(nir_shader *shader, struct ir3_driver_const_layo bool ir3_nir_apply_trig_workarounds(nir_shader *shader); bool ir3_nir_lower_tg4_to_tex(nir_shader *shader); bool ir3_nir_lower_io_offsets(nir_shader *shader); +bool ir3_nir_lower_load_barycentric_at_sample(nir_shader *shader); bool ir3_nir_move_varying_inputs(nir_shader *shader); const nir_shader_compiler_options * ir3_get_compiler_options(struct ir3_compiler *compiler); diff --git a/src/freedreno/ir3/ir3_nir_lower_load_barycentric_at_sample.c b/src/freedreno/ir3/ir3_nir_lower_load_barycentric_at_sample.c new file mode 100644 index 00000000000..e27f4822e2c --- /dev/null +++ b/src/freedreno/ir3/ir3_nir_lower_load_barycentric_at_sample.c @@ -0,0 +1,130 @@ +/* + * Copyright © 2019 Google, Inc. + * + * 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. + */ + +#include "ir3_nir.h" +#include "compiler/nir/nir_builder.h" + +/** + * This pass lowers load_barycentric_at_sample to load_sample_pos_from_id + * plus load_barycentric_at_offset. + * + * It also lowers load_sample_pos to load_sample_pos_from_id, mostly because + * that needs to happen at the same early stage (before wpos_ytransform) + */ + +static nir_ssa_def * +load_sample_pos(nir_builder *b, nir_ssa_def *samp_id) +{ + nir_intrinsic_instr *load_sp = + nir_intrinsic_instr_create(b->shader, + nir_intrinsic_load_sample_pos_from_id); + load_sp->num_components = 2; + load_sp->src[0] = nir_src_for_ssa(samp_id); + nir_ssa_dest_init(&load_sp->instr, &load_sp->dest, 2, 32, NULL); + nir_builder_instr_insert(b, &load_sp->instr); + + return &load_sp->dest.ssa; +} + +static void +lower_load_barycentric_at_sample(nir_builder *b, nir_intrinsic_instr *intr) +{ + nir_ssa_def *pos = load_sample_pos(b, intr->src[0].ssa); + + nir_intrinsic_instr *load_bary_at_offset = + nir_intrinsic_instr_create(b->shader, + nir_intrinsic_load_barycentric_at_offset); + load_bary_at_offset->num_components = 2; + load_bary_at_offset->src[0] = nir_src_for_ssa(pos); + nir_ssa_dest_init(&load_bary_at_offset->instr, + &load_bary_at_offset->dest, 2, 32, NULL); + nir_builder_instr_insert(b, &load_bary_at_offset->instr); + + nir_ssa_def_rewrite_uses(&intr->dest.ssa, + nir_src_for_ssa(&load_bary_at_offset->dest.ssa)); +} + +static void +lower_load_sample_pos(nir_builder *b, nir_intrinsic_instr *intr) +{ + nir_ssa_def *pos = load_sample_pos(b, nir_load_sample_id(b)); + + /* Note that gl_SamplePosition is offset by +vec2(0.5, 0.5) vs the + * offset passed to interpolateAtOffset(). See + * dEQP-GLES31.functional.shaders.multisample_interpolation.interpolate_at_offset.at_sample_position.default_framebuffer + * for example. + */ + nir_ssa_def *half = nir_imm_float(b, 0.5); + pos = nir_fadd(b, pos, nir_vec2(b, half, half)); + + nir_ssa_def_rewrite_uses(&intr->dest.ssa, nir_src_for_ssa(pos)); +} + +bool +ir3_nir_lower_load_barycentric_at_sample(nir_shader *shader) +{ + bool progress = false; + + debug_assert(shader->info.stage == MESA_SHADER_FRAGMENT); + + nir_foreach_function (function, shader) { + if (!function->impl) + continue; + + nir_builder b; + nir_builder_init(&b, function->impl); + + nir_foreach_block (block, function->impl) { + nir_foreach_instr_safe(instr, block) { + if (instr->type != nir_instr_type_intrinsic) + continue; + + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + + if (intr->intrinsic != nir_intrinsic_load_barycentric_at_sample && + intr->intrinsic != nir_intrinsic_load_sample_pos) + continue; + + debug_assert(intr->dest.is_ssa); + + b.cursor = nir_before_instr(instr); + + if (intr->intrinsic == nir_intrinsic_load_sample_pos) { + lower_load_sample_pos(&b, intr); + } else { + debug_assert(intr->src[0].is_ssa); + lower_load_barycentric_at_sample(&b, intr); + } + + progress = true; + } + } + + if (progress) { + nir_metadata_preserve(function->impl, + nir_metadata_block_index | nir_metadata_dominance); + } + } + + return progress; +} diff --git a/src/freedreno/ir3/meson.build b/src/freedreno/ir3/meson.build index 24917facd6d..2ef1e54962c 100644 --- a/src/freedreno/ir3/meson.build +++ b/src/freedreno/ir3/meson.build @@ -51,6 +51,7 @@ libfreedreno_ir3_files = files( 'ir3_nir.c', 'ir3_nir.h', 'ir3_nir_analyze_ubo_ranges.c', + 'ir3_nir_lower_load_barycentric_at_sample.c', 'ir3_nir_lower_io_offsets.c', 'ir3_nir_lower_tg4_to_tex.c', 'ir3_nir_move_varying_inputs.c', -- 2.11.0