Mesa (master): nir: optimize nir_lower_discard_to_demote to lower discard/demote both ways
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Thu Nov 12 21:21:53 UTC 2020
Module: Mesa
Branch: master
Commit: cb20d58f45c22d48208805ed7df8b98aee525189
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=cb20d58f45c22d48208805ed7df8b98aee525189
Author: Marek Olšák <marek.olsak at amd.com>
Date: Mon Sep 21 21:16:02 2020 -0400
nir: optimize nir_lower_discard_to_demote to lower discard/demote both ways
This is smarter and also lowers demote to discard if helper invocations are
not needed.
Reviewed-by: Rhys Perry <pendingchaos02 at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7586>
---
src/amd/vulkan/radv_shader.c | 4 +-
src/compiler/Makefile.sources | 2 +-
src/compiler/nir/meson.build | 2 +-
src/compiler/nir/nir.h | 3 +-
src/compiler/nir/nir_lower_discard_or_demote.c | 127 +++++++++++++++++++++++++
src/compiler/nir/nir_lower_discard_to_demote.c | 70 --------------
src/gallium/drivers/radeonsi/si_shader_nir.c | 4 +-
7 files changed, 135 insertions(+), 77 deletions(-)
diff --git a/src/amd/vulkan/radv_shader.c b/src/amd/vulkan/radv_shader.c
index 5c830b2887e..fc3cf734e83 100644
--- a/src/amd/vulkan/radv_shader.c
+++ b/src/amd/vulkan/radv_shader.c
@@ -535,8 +535,8 @@ radv_shader_compile_to_nir(struct radv_device *device,
NIR_PASS_V(nir, nir_lower_clip_cull_distance_arrays);
- if (device->instance->debug_flags & RADV_DEBUG_DISCARD_TO_DEMOTE)
- NIR_PASS_V(nir, nir_lower_discard_to_demote);
+ NIR_PASS_V(nir, nir_lower_discard_or_demote,
+ device->instance->debug_flags & RADV_DEBUG_DISCARD_TO_DEMOTE);
nir_lower_doubles_options lower_doubles =
nir->options->lower_doubles_options;
diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources
index 931af638bf7..af0b97d5c85 100644
--- a/src/compiler/Makefile.sources
+++ b/src/compiler/Makefile.sources
@@ -253,7 +253,7 @@ NIR_FILES = \
nir/nir_lower_clip_halfz.c \
nir/nir_lower_convert_alu_types.c \
nir/nir_lower_variable_initializers.c \
- nir/nir_lower_discard_to_demote.c \
+ nir/nir_lower_discard_or_demote.c \
nir/nir_lower_double_ops.c \
nir/nir_lower_drawpixels.c \
nir/nir_lower_fb_read.c \
diff --git a/src/compiler/nir/meson.build b/src/compiler/nir/meson.build
index dad896dcf75..9297c7e1ea0 100644
--- a/src/compiler/nir/meson.build
+++ b/src/compiler/nir/meson.build
@@ -132,7 +132,7 @@ files_libnir = files(
'nir_lower_clip_halfz.c',
'nir_lower_convert_alu_types.c',
'nir_lower_variable_initializers.c',
- 'nir_lower_discard_to_demote.c',
+ 'nir_lower_discard_or_demote.c',
'nir_lower_double_ops.c',
'nir_lower_drawpixels.c',
'nir_lower_fb_read.c',
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index cc87d218ed3..aa124ba3b67 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -4980,7 +4980,8 @@ typedef enum {
bool nir_lower_interpolation(nir_shader *shader,
nir_lower_interpolation_options options);
-bool nir_lower_discard_to_demote(nir_shader *shader);
+bool nir_lower_discard_or_demote(nir_shader *shader,
+ bool force_correct_quad_ops_after_discard);
bool nir_lower_memory_model(nir_shader *shader);
diff --git a/src/compiler/nir/nir_lower_discard_or_demote.c b/src/compiler/nir/nir_lower_discard_or_demote.c
new file mode 100644
index 00000000000..adfb91438fc
--- /dev/null
+++ b/src/compiler/nir/nir_lower_discard_or_demote.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright © 2020 Valve Corporation
+ *
+ * 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 "nir.h"
+#include "nir_builder.h"
+
+static bool
+nir_lower_discard_to_demote_instr(nir_builder *b, nir_instr *instr, void *data)
+{
+ if (instr->type != nir_instr_type_intrinsic)
+ return false;
+
+ nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
+ switch (intrin->intrinsic) {
+ case nir_intrinsic_discard:
+ intrin->intrinsic = nir_intrinsic_demote;
+ return true;
+ case nir_intrinsic_discard_if:
+ intrin->intrinsic = nir_intrinsic_demote_if;
+ return true;
+ case nir_intrinsic_load_helper_invocation:
+ intrin->intrinsic = nir_intrinsic_is_helper_invocation;
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool
+nir_lower_demote_to_discard_instr(nir_builder *b, nir_instr *instr, void *data)
+{
+ if (instr->type != nir_instr_type_intrinsic)
+ return false;
+
+ nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
+ switch (intrin->intrinsic) {
+ case nir_intrinsic_demote:
+ intrin->intrinsic = nir_intrinsic_discard;
+ return true;
+ case nir_intrinsic_demote_if:
+ intrin->intrinsic = nir_intrinsic_discard_if;
+ return true;
+ case nir_intrinsic_is_helper_invocation:
+ intrin->intrinsic = nir_intrinsic_load_helper_invocation;
+ return true;
+ default:
+ return false;
+ }
+}
+
+/**
+ * Optimize discard and demote opcodes.
+ *
+ * If force_correct_quad_ops_after_discard is true and quad operations are
+ * used, discard() will be converted to demote() and gl_HelperInvocation will
+ * be lowered to helperInvocationEXT(). This is intended as workaround for
+ * game bugs to force correct derivatives after kill. This lowering is not
+ * valid in the general case as it might change the result of subgroup
+ * operations and loop behavior.
+ *
+ * Otherwise, if demote is used and no ops need helper invocations, demote()
+ * will be converted to discard() as an optimization.
+ */
+bool
+nir_lower_discard_or_demote(nir_shader *shader,
+ bool force_correct_quad_ops_after_discard)
+{
+ if (shader->info.stage != MESA_SHADER_FRAGMENT)
+ return false;
+
+ /* We need uses_discard/demote and needs_*_helper_invocations. */
+ nir_shader_gather_info(shader, nir_shader_get_entrypoint(shader));
+ /* Validate that if uses_demote is set, uses_discard is also be set. */
+ assert(!shader->info.fs.uses_demote || shader->info.fs.uses_discard);
+
+ /* Quick skip. */
+ if (!shader->info.fs.uses_discard)
+ return false;
+
+ bool progress = false;
+
+ if (force_correct_quad_ops_after_discard &&
+ shader->info.fs.needs_quad_helper_invocations) {
+ /* If we need correct derivatives, convert discard to demote only when
+ * derivatives are actually used.
+ */
+ progress = nir_shader_instructions_pass(shader,
+ nir_lower_discard_to_demote_instr,
+ nir_metadata_all,
+ NULL);
+ shader->info.fs.uses_demote = true;
+ } else if (!shader->info.fs.needs_quad_helper_invocations &&
+ !shader->info.fs.needs_all_helper_invocations &&
+ shader->info.fs.uses_demote) {
+ /* If we don't need any helper invocations, convert demote to discard. */
+ progress = nir_shader_instructions_pass(shader,
+ nir_lower_demote_to_discard_instr,
+ nir_metadata_all,
+ NULL);
+ shader->info.fs.uses_demote = false;
+ }
+
+ /* Validate again that if uses_demote is set, uses_discard is also be set. */
+ assert(!shader->info.fs.uses_demote || shader->info.fs.uses_discard);
+ return progress;
+}
diff --git a/src/compiler/nir/nir_lower_discard_to_demote.c b/src/compiler/nir/nir_lower_discard_to_demote.c
deleted file mode 100644
index 88bc9c940a2..00000000000
--- a/src/compiler/nir/nir_lower_discard_to_demote.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright © 2020 Valve Corporation
- *
- * 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 "nir.h"
-#include "nir_builder.h"
-
-static bool
-nir_lower_discard_to_demote_instr(nir_builder *b, nir_instr *instr, void *data)
-{
- if (instr->type != nir_instr_type_intrinsic)
- return false;
-
- nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
- switch (intrin->intrinsic) {
- case nir_intrinsic_discard:
- intrin->intrinsic = nir_intrinsic_demote;
- b->shader->info.fs.uses_demote = true;
- return true;
- case nir_intrinsic_discard_if:
- intrin->intrinsic = nir_intrinsic_demote_if;
- b->shader->info.fs.uses_demote = true;
- return true;
- case nir_intrinsic_load_helper_invocation:
- intrin->intrinsic = nir_intrinsic_is_helper_invocation;
- return true;
- default:
- return false;
- }
-}
-
-/**
- * This pass is intended as workaround for game bugs to force correct
- * derivatives after kill. This lowering is not valid in the general case
- * as it might change the result of subgroup operations and loop behavior.
- *
- * discard() will be lowered as demote() and gl_HelperInvocation
- * will be lowered as helperInvocationEXT().
- */
-bool
-nir_lower_discard_to_demote(nir_shader *shader)
-{
- if (shader->info.stage != MESA_SHADER_FRAGMENT)
- return false;
-
- return nir_shader_instructions_pass(shader,
- nir_lower_discard_to_demote_instr,
- nir_metadata_all,
- NULL);
-}
diff --git a/src/gallium/drivers/radeonsi/si_shader_nir.c b/src/gallium/drivers/radeonsi/si_shader_nir.c
index 8cec0badbeb..3400da04ef6 100644
--- a/src/gallium/drivers/radeonsi/si_shader_nir.c
+++ b/src/gallium/drivers/radeonsi/si_shader_nir.c
@@ -711,8 +711,8 @@ static void si_lower_nir(struct si_screen *sscreen, struct nir_shader *nir)
NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_function_temp, NULL);
- if (sscreen->debug_flags & DBG(FS_CORRECT_DERIVS_AFTER_KILL))
- NIR_PASS_V(nir, nir_lower_discard_to_demote);
+ NIR_PASS_V(nir, nir_lower_discard_or_demote,
+ sscreen->debug_flags & DBG(FS_CORRECT_DERIVS_AFTER_KILL));
}
void si_finalize_nir(struct pipe_screen *screen, void *nirptr, bool optimize)
More information about the mesa-commit
mailing list