nir: remove nir_intrinsic_discard

The semantics of discard differ between GLSL and HLSL and
their various implementations. Subsequently, numerous application
bugs occurred and SPV_EXT_demote_to_helper_invocation was written
in order to clarify the behavior. In NIR, we now have 3 different
intrinsics for 2 things, and while demote and terminate have clear
semantics, discard still doesn't and can mean either of the two.

This patch entirely removes nir_intrinsic_discard and
nir_intrinsic_discard_if and replaces all occurences either with
nir_intrinsic_terminate{_if} or nir_intrinsic_demote{_if} in the
case that the NIR option 'discard_is_demote' is being set.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Reviewed-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Reviewed-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27617>
This commit is contained in:
Daniel Schürmann 2024-02-14 15:32:31 +01:00 committed by Marge Bot
parent 4a84725ebb
commit 9b1a748b5e
42 changed files with 77 additions and 316 deletions

View file

@ -8850,12 +8850,9 @@ visit_intrinsic(isel_context* ctx, nir_intrinsic_instr* instr)
break;
}
case nir_intrinsic_demote:
case nir_intrinsic_demote_if:
case nir_intrinsic_discard:
case nir_intrinsic_discard_if: {
case nir_intrinsic_demote_if: {
Operand cond = Operand::c32(-1u);
if (instr->intrinsic == nir_intrinsic_discard_if ||
instr->intrinsic == nir_intrinsic_demote_if) {
if (instr->intrinsic == nir_intrinsic_demote_if) {
Temp src = get_ssa_temp(ctx, instr->src[0].ssa);
assert(src.regClass() == bld.lm);
cond =

View file

@ -2501,12 +2501,10 @@ static void emit_demote(struct ac_nir_context *ctx, const nir_intrinsic_instr *i
{
LLVMValueRef cond;
if (instr->intrinsic == nir_intrinsic_discard_if ||
instr->intrinsic == nir_intrinsic_demote_if) {
if (instr->intrinsic == nir_intrinsic_demote_if) {
cond = LLVMBuildNot(ctx->ac.builder, get_src(ctx, instr->src[0]), "");
} else {
assert(instr->intrinsic == nir_intrinsic_discard ||
instr->intrinsic == nir_intrinsic_demote);
assert(instr->intrinsic == nir_intrinsic_demote);
cond = ctx->ac.i1false;
}
@ -3144,8 +3142,6 @@ static bool visit_intrinsic(struct ac_nir_context *ctx, nir_intrinsic_instr *ins
case nir_intrinsic_terminate_if:
emit_discard(ctx, instr);
break;
case nir_intrinsic_discard:
case nir_intrinsic_discard_if:
case nir_intrinsic_demote:
case nir_intrinsic_demote_if:
emit_demote(ctx, instr);

View file

@ -83,8 +83,8 @@ lower_zs_emit(nir_block *block, bool force_early_z)
static bool
lower_discard(nir_builder *b, nir_intrinsic_instr *intr, UNUSED void *data)
{
if (intr->intrinsic != nir_intrinsic_discard &&
intr->intrinsic != nir_intrinsic_discard_if &&
if (intr->intrinsic != nir_intrinsic_terminate &&
intr->intrinsic != nir_intrinsic_terminate_if &&
intr->intrinsic != nir_intrinsic_demote &&
intr->intrinsic != nir_intrinsic_demote_if)
return false;
@ -95,7 +95,7 @@ lower_discard(nir_builder *b, nir_intrinsic_instr *intr, UNUSED void *data)
nir_def *no_samples = nir_imm_intN_t(b, 0, 16);
nir_def *killed_samples = all_samples;
if (intr->intrinsic == nir_intrinsic_discard_if ||
if (intr->intrinsic == nir_intrinsic_terminate_if ||
intr->intrinsic == nir_intrinsic_demote_if)
killed_samples = nir_bcsel(b, intr->src[0].ssa, all_samples, no_samples);

View file

@ -3573,7 +3573,6 @@ ntq_emit_intrinsic(struct v3d_compile *c, nir_intrinsic_instr *instr)
* early termination by emitting a (maybe conditional) jump to the
* end section of the fragment shader for affected invocations.
*/
case nir_intrinsic_discard:
case nir_intrinsic_terminate:
c->emitted_discard = true;
FALLTHROUGH;
@ -3592,7 +3591,6 @@ ntq_emit_intrinsic(struct v3d_compile *c, nir_intrinsic_instr *instr)
}
break;
case nir_intrinsic_discard_if:
case nir_intrinsic_terminate_if:
c->emitted_discard = true;
FALLTHROUGH;

View file

@ -55,7 +55,8 @@ set_discard_global(nir_builder *b, nir_variable *discarded,
{
nir_deref_instr *lhs = nir_build_deref_var(b, discarded);
nir_def *rhs;
if (intrin->intrinsic == nir_intrinsic_discard_if) {
if (intrin->intrinsic == nir_intrinsic_terminate_if ||
intrin->intrinsic == nir_intrinsic_demote_if) {
/* discarded <- condition, use discarded as the condition */
rhs = intrin->src[0].ssa;
nir_src_rewrite(&intrin->src[0], &lhs->def);
@ -91,8 +92,10 @@ lower_discard_flow(nir_builder *b, nir_cf_node *cf_node,
}
} else if (instr->type == nir_instr_type_intrinsic) {
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
if (intrin->intrinsic == nir_intrinsic_discard_if ||
intrin->intrinsic == nir_intrinsic_discard) {
if (intrin->intrinsic == nir_intrinsic_terminate_if ||
intrin->intrinsic == nir_intrinsic_terminate ||
intrin->intrinsic == nir_intrinsic_demote_if ||
intrin->intrinsic == nir_intrinsic_demote) {
b->cursor = nir_before_instr(instr);
set_discard_global(b, discarded, intrin);
}

View file

@ -150,7 +150,6 @@ files_libnir = files(
'nir_lower_convert_alu_types.c',
'nir_lower_variable_initializers.c',
'nir_lower_discard_if.c',
'nir_lower_discard_or_demote.c',
'nir_lower_double_ops.c',
'nir_lower_drawpixels.c',
'nir_lower_fb_read.c',

View file

@ -6400,9 +6400,6 @@ typedef enum {
bool nir_lower_discard_if(nir_shader *shader, nir_lower_discard_if_options options);
bool nir_lower_discard_or_demote(nir_shader *shader,
bool force_correct_quad_ops_after_discard);
bool nir_lower_terminate_to_demote(nir_shader *nir);
bool nir_lower_memory_model(nir_shader *shader);

View file

@ -2137,6 +2137,24 @@ nir_build_call(nir_builder *build, nir_function *func, size_t count,
nir_builder_instr_insert(build, &call->instr);
}
static inline void
nir_discard(nir_builder *build)
{
if (build->shader->options->discard_is_demote)
nir_demote(build);
else
nir_terminate(build);
}
static inline void
nir_discard_if(nir_builder *build, nir_def *src)
{
if (build->shader->options->discard_is_demote)
nir_demote_if(build, src);
else
nir_terminate_if(build, src);
}
/*
* Call a given nir_function * with a variadic number of nir_def * arguments.
*

View file

@ -469,8 +469,6 @@ gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader,
case nir_intrinsic_demote_if:
shader->info.fs.uses_demote = true;
FALLTHROUGH; /* quads with helper lanes only might be discarded entirely */
case nir_intrinsic_discard:
case nir_intrinsic_discard_if:
case nir_intrinsic_terminate:
case nir_intrinsic_terminate_if:
/* Freedreno uses discard_if() to end GS invocations that don't produce

View file

@ -306,9 +306,7 @@ is_barrier(nir_instr *instr)
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
const char *name = nir_intrinsic_infos[intr->intrinsic].name;
if (intr->intrinsic == nir_intrinsic_discard ||
intr->intrinsic == nir_intrinsic_discard_if ||
intr->intrinsic == nir_intrinsic_terminate ||
if (intr->intrinsic == nir_intrinsic_terminate ||
intr->intrinsic == nir_intrinsic_terminate_if ||
/* TODO: nir_intrinsics.py could do this */
strstr(name, "barrier"))

View file

@ -414,8 +414,6 @@ intrinsic("is_sparse_resident_zink", dest_comp=1, src_comp=[0], bit_sizes=[1],
def barrier(name):
intrinsic(name)
barrier("discard")
# Demote fragment shader invocation to a helper invocation. Any stores to
# memory after this instruction are suppressed and the fragment does not write
# outputs to the framebuffer. Unlike discard, demote needs to ensure that
@ -480,8 +478,7 @@ intrinsic("inverse_ballot", src_comp=[0], dest_comp=1, flags=[CAN_ELIMINATE])
barrier("begin_invocation_interlock")
barrier("end_invocation_interlock")
# A conditional discard/demote/terminate, with a single boolean source.
intrinsic("discard_if", src_comp=[1])
# A conditional demote/terminate, with a single boolean source.
intrinsic("demote_if", src_comp=[1])
intrinsic("terminate_if", src_comp=[1])

View file

@ -30,10 +30,6 @@ lower_discard_if(nir_builder *b, nir_intrinsic_instr *instr, void *cb_data)
nir_lower_discard_if_options options = *(nir_lower_discard_if_options *)cb_data;
switch (instr->intrinsic) {
case nir_intrinsic_discard_if:
if (!(options & nir_lower_discard_if_to_cf))
return false;
break;
case nir_intrinsic_demote_if:
if (!(options & nir_lower_demote_if_to_cf))
return false;
@ -50,9 +46,6 @@ lower_discard_if(nir_builder *b, nir_intrinsic_instr *instr, void *cb_data)
nir_if *if_stmt = nir_push_if(b, instr->src[0].ssa);
switch (instr->intrinsic) {
case nir_intrinsic_discard_if:
nir_discard(b);
break;
case nir_intrinsic_demote_if:
nir_demote(b);
break;
@ -94,7 +87,7 @@ lower_discard_if(nir_builder *b, nir_intrinsic_instr *instr, void *cb_data)
} else {
block block_6:
/ preds: block_4 /
intrinsic discard () () <-- not last instruction
intrinsic terminate () () <-- not last instruction
vec1 32 ssa_23 = iadd ssa_50, ssa_31 <-- dead code loop itr increment
/ succs: block_7 /
}
@ -103,7 +96,7 @@ lower_discard_if(nir_builder *b, nir_intrinsic_instr *instr, void *cb_data)
which means that we can't assert like this:
assert(instr->intrinsic != nir_intrinsic_discard ||
assert(instr->intrinsic != nir_intrinsic_terminate ||
nir_block_last_instr(instr->instr.block) == &instr->instr);

View file

@ -1,187 +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
lower_discard_to_demote(nir_builder *b, nir_intrinsic_instr *intrin, void *data)
{
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
lower_demote_to_discard(nir_builder *b, nir_intrinsic_instr *intrin, void *data)
{
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:
case nir_intrinsic_load_helper_invocation: {
/* If the shader doesn't need helper invocations,
* we can assume there are none */
b->cursor = nir_before_instr(&intrin->instr);
nir_def *zero = nir_imm_false(b);
nir_def_rewrite_uses(&intrin->def, zero);
nir_instr_remove(&intrin->instr);
return true;
}
default:
return false;
}
}
static nir_def *
insert_is_helper(nir_builder *b, nir_instr *instr)
{
/* find best place to insert is_helper */
nir_cf_node *node = &instr->block->cf_node;
while (node->parent->type != nir_cf_node_function)
node = nir_cf_node_prev(node->parent);
nir_block *block = nir_cf_node_as_block(node);
if (block == instr->block) {
b->cursor = nir_before_instr(instr);
} else {
b->cursor = nir_after_block_before_jump(block);
}
return nir_is_helper_invocation(b, 1);
}
static bool
lower_load_helper_to_is_helper(nir_builder *b,
nir_intrinsic_instr *intrin, void *data)
{
nir_def *is_helper = *(nir_def **)data;
switch (intrin->intrinsic) {
case nir_intrinsic_demote:
case nir_intrinsic_demote_if:
/* insert is_helper at last top level occasion */
if (is_helper == NULL) {
is_helper = insert_is_helper(b, &intrin->instr);
*(nir_def **)data = is_helper;
return true;
} else {
return false;
}
case nir_intrinsic_load_helper_invocation:
/* Don't update data: as long as we didn't encounter any demote(),
* we can insert new is_helper() intrinsics. These are placed at
* top-level blocks to ensure correct behavior w.r.t. loops */
if (is_helper == NULL)
is_helper = insert_is_helper(b, &intrin->instr);
nir_def_rewrite_uses(&intrin->def, is_helper);
nir_instr_remove(&intrin->instr);
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_intrinsics_pass(shader, lower_discard_to_demote,
nir_metadata_block_index |
nir_metadata_dominance |
nir_metadata_live_defs |
nir_metadata_instr_index,
NULL);
shader->info.fs.uses_demote = true;
} else if (!shader->info.fs.needs_quad_helper_invocations &&
!shader->info.uses_wide_subgroup_intrinsics &&
shader->info.fs.uses_demote) {
/* If we don't need any helper invocations, convert demote to discard. */
progress = nir_shader_intrinsics_pass(shader, lower_demote_to_discard,
nir_metadata_block_index |
nir_metadata_dominance,
NULL);
shader->info.fs.uses_demote = false;
} else if (shader->info.fs.uses_demote &&
BITSET_TEST(shader->info.system_values_read,
nir_system_value_from_intrinsic(nir_intrinsic_load_helper_invocation))) {
/* load_helper needs to preserve the value (whether an invocation is
* a helper lane) from the beginning of the shader. */
nir_def *is_helper = NULL;
progress = nir_shader_intrinsics_pass(shader,
lower_load_helper_to_is_helper,
nir_metadata_block_index |
nir_metadata_dominance,
&is_helper);
BITSET_CLEAR(shader->info.system_values_read,
nir_system_value_from_intrinsic(nir_intrinsic_load_helper_invocation));
}
/* 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;
}

View file

@ -84,16 +84,12 @@ nir_opt_conditional_discard_block(nir_builder *b, nir_block *block)
b->cursor = nir_before_cf_node(prev_node);
switch (intrin->intrinsic) {
case nir_intrinsic_discard:
op = nir_intrinsic_discard_if;
break;
case nir_intrinsic_demote:
op = nir_intrinsic_demote_if;
break;
case nir_intrinsic_terminate:
op = nir_intrinsic_terminate_if;
break;
case nir_intrinsic_discard_if:
case nir_intrinsic_demote_if:
case nir_intrinsic_terminate_if:
cond = nir_iand(b, cond, intrin->src[0].ssa);

View file

@ -175,16 +175,12 @@ try_fold_intrinsic(nir_builder *b, nir_intrinsic_instr *intrin,
{
switch (intrin->intrinsic) {
case nir_intrinsic_demote_if:
case nir_intrinsic_discard_if:
case nir_intrinsic_terminate_if:
if (nir_src_is_const(intrin->src[0])) {
if (nir_src_as_bool(intrin->src[0])) {
b->cursor = nir_before_instr(&intrin->instr);
nir_intrinsic_op op;
switch (intrin->intrinsic) {
case nir_intrinsic_discard_if:
op = nir_intrinsic_discard;
break;
case nir_intrinsic_demote_if:
op = nir_intrinsic_demote;
break;

View file

@ -375,9 +375,7 @@ opt_intrinsics_impl(nir_function_impl *impl,
case nir_instr_type_intrinsic: {
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
if (intrin->intrinsic == nir_intrinsic_discard ||
intrin->intrinsic == nir_intrinsic_discard_if ||
intrin->intrinsic == nir_intrinsic_demote ||
if (intrin->intrinsic == nir_intrinsic_demote ||
intrin->intrinsic == nir_intrinsic_demote_if ||
intrin->intrinsic == nir_intrinsic_terminate ||
intrin->intrinsic == nir_intrinsic_terminate_if)

View file

@ -1310,8 +1310,6 @@ handle_barrier(struct vectorize_ctx *ctx, bool *progress, nir_function_impl *imp
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
switch (intrin->intrinsic) {
/* prevent speculative loads/stores */
case nir_intrinsic_discard_if:
case nir_intrinsic_discard:
case nir_intrinsic_terminate_if:
case nir_intrinsic_terminate:
case nir_intrinsic_launch_mesh_workgroups:

View file

@ -195,9 +195,9 @@ opt_move_discards_to_top_impl(nir_function_impl *impl)
case nir_intrinsic_masked_swizzle_amd:
instr->pass_flags = STOP_PROCESSING_INSTR_FLAG;
goto break_all;
case nir_intrinsic_discard_if:
case nir_intrinsic_terminate_if:
if (!consider_discards) {
/* assume that a shader either uses discard or demote, but not both */
/* assume that a shader either uses terminate or demote, but not both */
instr->pass_flags = STOP_PROCESSING_INSTR_FLAG;
goto break_all;
}

View file

@ -80,8 +80,6 @@ block_check_for_allowed_instrs(nir_block *block, unsigned *count,
switch (intr->intrinsic) {
case nir_intrinsic_terminate:
case nir_intrinsic_terminate_if:
case nir_intrinsic_discard:
case nir_intrinsic_discard_if:
/* For non-CF hardware, we need to be able to move discards up
* and flatten, so let them pass.
*/
@ -394,8 +392,7 @@ rewrite_discard_conds(nir_instr *instr, nir_def *if_cond, bool is_else)
return;
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
if (intr->intrinsic != nir_intrinsic_discard_if && intr->intrinsic != nir_intrinsic_discard &&
intr->intrinsic != nir_intrinsic_terminate_if && intr->intrinsic != nir_intrinsic_terminate)
if (intr->intrinsic != nir_intrinsic_terminate_if && intr->intrinsic != nir_intrinsic_terminate)
return;
nir_builder b = nir_builder_at(nir_before_instr(instr));
@ -403,8 +400,7 @@ rewrite_discard_conds(nir_instr *instr, nir_def *if_cond, bool is_else)
if (is_else)
if_cond = nir_inot(&b, if_cond);
if (intr->intrinsic == nir_intrinsic_discard_if ||
intr->intrinsic == nir_intrinsic_terminate_if) {
if (intr->intrinsic == nir_intrinsic_terminate_if) {
nir_src_rewrite(&intr->src[0], nir_iand(&b, intr->src[0].ssa, if_cond));
} else {
nir_discard_if(&b, if_cond);

View file

@ -349,8 +349,6 @@ nir_schedule_intrinsic_deps(nir_deps_state *state,
case nir_intrinsic_load_front_face:
break;
case nir_intrinsic_discard:
case nir_intrinsic_discard_if:
case nir_intrinsic_demote:
case nir_intrinsic_demote_if:
case nir_intrinsic_terminate:

View file

@ -2637,16 +2637,13 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr)
}
break;
}
case nir_intrinsic_discard_if:
case nir_intrinsic_discard:
case nir_intrinsic_demote:
case nir_intrinsic_demote_if:
case nir_intrinsic_terminate:
case nir_intrinsic_terminate_if: {
struct ir3_instruction *cond, *kill;
if (intr->intrinsic == nir_intrinsic_discard_if ||
intr->intrinsic == nir_intrinsic_demote_if ||
if (intr->intrinsic == nir_intrinsic_demote_if ||
intr->intrinsic == nir_intrinsic_terminate_if) {
/* conditional discard: */
src = ir3_get_src(ctx, &intr->src[0]);
@ -3969,8 +3966,6 @@ instr_can_be_predicated(nir_instr *instr)
case nir_intrinsic_ballot:
case nir_intrinsic_elect:
case nir_intrinsic_read_invocation_cond_ir3:
case nir_intrinsic_discard_if:
case nir_intrinsic_discard:
case nir_intrinsic_demote:
case nir_intrinsic_demote_if:
case nir_intrinsic_terminate:

View file

@ -1901,7 +1901,7 @@ visit_discard(struct lp_build_nir_context *bld_base,
nir_intrinsic_instr *instr)
{
LLVMValueRef cond = NULL;
if (instr->intrinsic == nir_intrinsic_discard_if) {
if (instr->intrinsic == nir_intrinsic_terminate_if) {
cond = get_src(bld_base, instr->src[0]);
cond = cast_type(bld_base, cond, nir_type_int, 32);
}
@ -2175,8 +2175,8 @@ visit_intrinsic(struct lp_build_nir_context *bld_base,
case nir_intrinsic_load_helper_invocation:
bld_base->helper_invocation(bld_base, &result[0]);
break;
case nir_intrinsic_discard_if:
case nir_intrinsic_discard:
case nir_intrinsic_terminate_if:
case nir_intrinsic_terminate:
visit_discard(bld_base, instr);
break;
case nir_intrinsic_emit_vertex:

View file

@ -2558,11 +2558,11 @@ ntt_emit_intrinsic(struct ntt_compile *c, nir_intrinsic_instr *instr)
ntt_DEMOTE(c);
break;
case nir_intrinsic_discard:
case nir_intrinsic_terminate:
ntt_KILL(c);
break;
case nir_intrinsic_discard_if: {
case nir_intrinsic_terminate_if: {
struct ureg_src cond = ureg_scalar(ntt_get_src(c, instr->src[0]), 0);
if (c->native_integers) {

View file

@ -561,10 +561,10 @@ emit_intrinsic(struct etna_compile *c, nir_intrinsic_instr * intr)
case nir_intrinsic_store_deref:
etna_emit_output(c, nir_src_as_deref(intr->src[0])->var, get_src(c, &intr->src[1]));
break;
case nir_intrinsic_discard_if:
case nir_intrinsic_terminate_if:
etna_emit_discard(c, get_src(c, &intr->src[0]));
break;
case nir_intrinsic_discard:
case nir_intrinsic_terminate:
etna_emit_discard(c, SRC_DISABLE);
break;
case nir_intrinsic_load_uniform: {

View file

@ -644,11 +644,11 @@ emit_intrinsic(struct ir2_context *ctx, nir_intrinsic_instr *intr)
instr = instr_create_alu_dest(ctx, nir_op_mov, &intr->def);
instr->src[0] = ir2_src(idx, 0, IR2_SRC_CONST);
break;
case nir_intrinsic_discard:
case nir_intrinsic_discard_if:
case nir_intrinsic_terminate:
case nir_intrinsic_terminate_if:
instr = ir2_instr_create(ctx, IR2_ALU);
instr->alu.vector_opc = VECTOR_NONE;
if (intr->intrinsic == nir_intrinsic_discard_if) {
if (intr->intrinsic == nir_intrinsic_terminate_if) {
instr->alu.scalar_opc = KILLNEs;
instr->src[0] = make_src(ctx, intr->src[0]);
} else {

View file

@ -437,12 +437,12 @@ static bool ppir_emit_intrinsic(ppir_block *block, nir_instr *ni)
return true;
}
case nir_intrinsic_discard:
case nir_intrinsic_terminate:
node = ppir_emit_discard(block, ni);
list_addtail(&node->list, &block->node_list);
return true;
case nir_intrinsic_discard_if:
case nir_intrinsic_terminate_if:
node = ppir_emit_discard_if(block, ni);
list_addtail(&node->list, &block->node_list);
return true;

View file

@ -1621,11 +1621,11 @@ ntr_emit_intrinsic(struct ntr_compile *c, nir_intrinsic_instr *instr)
ntr_emit_load_output(c, instr);
break;
case nir_intrinsic_discard:
case nir_intrinsic_terminate:
ntr_KILL(c);
break;
case nir_intrinsic_discard_if: {
case nir_intrinsic_terminate_if: {
struct ureg_src cond = ureg_scalar(ntr_get_src(c, instr->src[0]), 0);
/* For !native_integers, the bool got lowered to 1.0 or 0.0. */
ntr_KILL_IF(c, ureg_negate(cond));

View file

@ -137,7 +137,7 @@ FragmentShader::process_stage_intrinsic(nir_intrinsic_instr *intr)
return load_input(intr);
case nir_intrinsic_load_interpolated_input:
return load_interpolated_input(intr);
case nir_intrinsic_discard_if:
case nir_intrinsic_terminate_if:
m_uses_discard = true;
emit_instruction(new AluInstr(op2_killne_int,
nullptr,
@ -146,7 +146,7 @@ FragmentShader::process_stage_intrinsic(nir_intrinsic_instr *intr)
{AluInstr::last}));
return true;
case nir_intrinsic_discard:
case nir_intrinsic_terminate:
m_uses_discard = true;
emit_instruction(new AluInstr(op2_kille_int,
nullptr,

View file

@ -303,8 +303,6 @@ static void si_lower_nir(struct si_screen *sscreen, struct nir_shader *nir)
NIR_PASS_V(nir, nir_lower_subgroups, sscreen->nir_lower_subgroups_options);
NIR_PASS_V(nir, nir_lower_discard_or_demote, true);
/* Lower load constants to scalar and then clean up the mess */
NIR_PASS_V(nir, nir_lower_load_const_to_scalar);
NIR_PASS_V(nir, nir_lower_var_copies);

View file

@ -1815,7 +1815,7 @@ ntq_emit_intrinsic(struct vc4_compile *c, nir_intrinsic_instr *instr)
}
break;
case nir_intrinsic_discard:
case nir_intrinsic_terminate:
if (c->execute.file != QFILE_NULL) {
qir_SF(c, c->execute);
qir_MOV_cond(c, QPU_COND_ZS, c->discard,
@ -1825,7 +1825,7 @@ ntq_emit_intrinsic(struct vc4_compile *c, nir_intrinsic_instr *instr)
}
break;
case nir_intrinsic_discard_if: {
case nir_intrinsic_terminate_if: {
/* true (~0) if we're discarding */
struct qreg cond = ntq_get_src(c, instr->src[0], 0);

View file

@ -3228,7 +3228,7 @@ emit_intrinsic(struct ntv_context *ctx, nir_intrinsic_instr *intr)
emit_store_reg(ctx, intr);
break;
case nir_intrinsic_discard:
case nir_intrinsic_terminate:
emit_discard(ctx, intr);
break;

View file

@ -6228,10 +6228,6 @@ zink_shader_init(struct zink_screen *screen, struct zink_shader *zs)
NIR_PASS_V(nir, strip_tex_ms);
NIR_PASS_V(nir, nir_lower_frexp); /* TODO: Use the spirv instructions for this. */
if (screen->info.have_EXT_shader_demote_to_helper_invocation) {
NIR_PASS_V(nir, nir_lower_discard_or_demote, true);
}
if (screen->need_2D_zs)
NIR_PASS_V(nir, lower_1d_shadow, screen);

View file

@ -169,12 +169,12 @@ remove_barriers(nir_shader *nir, bool is_compute)
static bool
lower_demote_impl(nir_builder *b, nir_intrinsic_instr *intr, void *data)
{
if (intr->intrinsic == nir_intrinsic_demote || intr->intrinsic == nir_intrinsic_terminate) {
intr->intrinsic = nir_intrinsic_discard;
if (intr->intrinsic == nir_intrinsic_demote) {
intr->intrinsic = nir_intrinsic_terminate;
return true;
}
if (intr->intrinsic == nir_intrinsic_demote_if || intr->intrinsic == nir_intrinsic_terminate_if) {
intr->intrinsic = nir_intrinsic_discard_if;
if (intr->intrinsic == nir_intrinsic_demote_if) {
intr->intrinsic = nir_intrinsic_terminate_if;
return true;
}
return false;

View file

@ -3904,10 +3904,8 @@ fs_nir_emit_fs_intrinsic(nir_to_brw_state &ntb,
}
case nir_intrinsic_demote:
case nir_intrinsic_discard:
case nir_intrinsic_terminate:
case nir_intrinsic_demote_if:
case nir_intrinsic_discard_if:
case nir_intrinsic_terminate_if: {
/* We track our discarded pixels in f0.1/f1.0. By predicating on it, we
* can update just the flag bits that aren't yet discarded. If there's
@ -3916,7 +3914,6 @@ fs_nir_emit_fs_intrinsic(nir_to_brw_state &ntb,
*/
fs_inst *cmp = NULL;
if (instr->intrinsic == nir_intrinsic_demote_if ||
instr->intrinsic == nir_intrinsic_discard_if ||
instr->intrinsic == nir_intrinsic_terminate_if) {
nir_alu_instr *alu = nir_src_as_alu_instr(instr->src[0]);

View file

@ -3748,10 +3748,8 @@ fs_nir_emit_fs_intrinsic(nir_to_elk_state &ntb,
}
case nir_intrinsic_demote:
case nir_intrinsic_discard:
case nir_intrinsic_terminate:
case nir_intrinsic_demote_if:
case nir_intrinsic_discard_if:
case nir_intrinsic_terminate_if: {
/* We track our discarded pixels in f0.1/f1.0. By predicating on it, we
* can update just the flag bits that aren't yet discarded. If there's
@ -3760,7 +3758,6 @@ fs_nir_emit_fs_intrinsic(nir_to_elk_state &ntb,
*/
elk_fs_inst *cmp = NULL;
if (instr->intrinsic == nir_intrinsic_demote_if ||
instr->intrinsic == nir_intrinsic_discard_if ||
instr->intrinsic == nir_intrinsic_terminate_if) {
nir_alu_instr *alu = nir_src_as_alu_instr(instr->src[0]);

View file

@ -1826,17 +1826,14 @@ static bool
lower_kill(struct nir_builder *builder, nir_intrinsic_instr *intr,
void *_cb_data)
{
if (intr->intrinsic != nir_intrinsic_discard &&
intr->intrinsic != nir_intrinsic_terminate &&
intr->intrinsic != nir_intrinsic_discard_if &&
if (intr->intrinsic != nir_intrinsic_terminate &&
intr->intrinsic != nir_intrinsic_terminate_if)
return false;
builder->cursor = nir_instr_remove(&intr->instr);
nir_def *condition;
if (intr->intrinsic == nir_intrinsic_discard ||
intr->intrinsic == nir_intrinsic_terminate) {
if (intr->intrinsic == nir_intrinsic_terminate) {
nir_demote(builder);
condition = nir_imm_true(builder);
} else {

View file

@ -4833,10 +4833,10 @@ emit_intrinsic(struct ntd_context *ctx, nir_intrinsic_instr *intr)
return emit_load_sample_mask_in(ctx, intr);
case nir_intrinsic_load_tess_coord:
return emit_load_tess_coord(ctx, intr);
case nir_intrinsic_discard_if:
case nir_intrinsic_terminate_if:
case nir_intrinsic_demote_if:
return emit_discard_if(ctx, intr);
case nir_intrinsic_discard:
case nir_intrinsic_terminate:
case nir_intrinsic_demote:
return emit_discard(ctx);
case nir_intrinsic_emit_vertex:

View file

@ -972,12 +972,6 @@ dxil_spirv_nir_passes(nir_shader *nir,
.use_view_id_for_layer = !conf->lower_view_index,
});
/* This will lower load_helper to a memoized is_helper if needed; otherwise, load_helper
* will stay, but trivially translatable to IsHelperLane(), which will be known to be
* constant across the invocation since no demotion would have been used.
*/
NIR_PASS_V(nir, nir_lower_discard_or_demote, nir->info.use_legacy_math_rules);
NIR_PASS_V(nir, dxil_nir_lower_discard_and_terminate);
NIR_PASS_V(nir, nir_lower_returns);
NIR_PASS_V(nir, dxil_nir_lower_sample_pos);

View file

@ -1860,14 +1860,12 @@ Converter::visit(nir_intrinsic_instr *insn)
break;
}
case nir_intrinsic_demote:
case nir_intrinsic_discard:
mkOp(OP_DISCARD, TYPE_NONE, NULL);
break;
case nir_intrinsic_demote_if:
case nir_intrinsic_discard_if: {
case nir_intrinsic_demote_if: {
Value *pred = getSSA(1, FILE_PREDICATE);
if (insn->num_components > 1) {
ERROR("nir_intrinsic_discard_if only with 1 component supported!\n");
ERROR("nir_intrinsic_demote_if only with 1 component supported!\n");
assert(false);
return false;
}

View file

@ -2311,7 +2311,7 @@ impl<'a> ShaderFromNir<'a> {
b.push_op(OpFSOut { srcs: srcs });
}
nir_intrinsic_demote | nir_intrinsic_discard => {
nir_intrinsic_demote => {
if let ShaderIoInfo::Fragment(info) = &mut self.info.io {
info.uses_kill = true;
} else {
@ -2319,7 +2319,7 @@ impl<'a> ShaderFromNir<'a> {
}
b.push_op(OpKill {});
}
nir_intrinsic_demote_if | nir_intrinsic_discard_if => {
nir_intrinsic_demote_if => {
if let ShaderIoInfo::Fragment(info) = &mut self.info.io {
info.uses_kill = true;
} else {

View file

@ -1743,11 +1743,11 @@ bi_emit_intrinsic(bi_builder *b, nir_intrinsic_instr *instr)
bi_emit_ld_tile(b, instr);
break;
case nir_intrinsic_discard_if:
case nir_intrinsic_terminate_if:
bi_discard_b32(b, bi_src_index(&instr->src[0]));
break;
case nir_intrinsic_discard:
case nir_intrinsic_terminate:
bi_discard_f32(b, bi_zero(), bi_zero(), BI_CMPF_EQ);
break;

View file

@ -1570,9 +1570,9 @@ emit_intrinsic(compiler_context *ctx, nir_intrinsic_instr *instr)
break;
}
case nir_intrinsic_discard_if:
case nir_intrinsic_discard: {
bool conditional = instr->intrinsic == nir_intrinsic_discard_if;
case nir_intrinsic_terminate_if:
case nir_intrinsic_terminate: {
bool conditional = instr->intrinsic == nir_intrinsic_terminate_if;
struct midgard_instruction discard = v_branch(conditional, false);
discard.branch.target_type = TARGET_DISCARD;