mesa/src/compiler/nir/nir_lower_helper_writes.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

111 lines
4 KiB
C
Raw Normal View History

nir: Add nir_lower_helper_writes pass This NIR pass lowers stores in fragment shaders to: if (!gl_HelperInvocaton) { store(); } This implements the API requirement that helper invocations do not have visible side effects, and the lowering is required on any hardware that cannot directly mask helper invocation's side effects. The pass was originally written for Midgard (which has this issue) but is also needed for Asahi. Let's share the code, and fix it while we're at it. Changes from the Midgard pass: 1. Add an option to only lower atomics. AGX hardware can mask helper invocations for "plain" stores but not for atomics. Accordingly, the AGX compiler wants this lowering for atomics but not store_global. By contrast, Midgard cannot mask any stores and needs the lowering for all store intrinsics. Add an option to the common pass to accommodate both cases. This is an optimization for AGX. It is not required for correctness, this lowering is always legal. 2. Fix dominance issues. It's invalid to have NIR like if ... { ssa_1 = ... } foo ssa_1 Instead we need to rewrite as if ... { ssa_1 = ... } else { ssa_2 = undef } ssa_3 = phi ssa_1, ssa_2 foo ssa_3 By default, neither nir_validate nor the backends check this, so this doesn't currently fix a (known) real bug. But it's still invalid and fails validation with NIR_DEBUG=validate_ssa_dominance. Fix this in lower_helper_writes for intrinsics that return data (atomics). 3. Assert that the pass is run only for fragment shaders. This encourages backends to be judicious about which passes they call instead of just throwing everything in a giant lower everything spaghetti. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Italo Nicola <italonicola@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21413>
2023-02-20 14:16:05 -05:00
/*
* Copyright (C) 2020-2021 Collabora, Ltd.
* 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 "compiler/nir/nir.h"
#include "compiler/nir/nir_builder.h"
static bool
lower(nir_builder *b, nir_intrinsic_instr *intr, void *data)
nir: Add nir_lower_helper_writes pass This NIR pass lowers stores in fragment shaders to: if (!gl_HelperInvocaton) { store(); } This implements the API requirement that helper invocations do not have visible side effects, and the lowering is required on any hardware that cannot directly mask helper invocation's side effects. The pass was originally written for Midgard (which has this issue) but is also needed for Asahi. Let's share the code, and fix it while we're at it. Changes from the Midgard pass: 1. Add an option to only lower atomics. AGX hardware can mask helper invocations for "plain" stores but not for atomics. Accordingly, the AGX compiler wants this lowering for atomics but not store_global. By contrast, Midgard cannot mask any stores and needs the lowering for all store intrinsics. Add an option to the common pass to accommodate both cases. This is an optimization for AGX. It is not required for correctness, this lowering is always legal. 2. Fix dominance issues. It's invalid to have NIR like if ... { ssa_1 = ... } foo ssa_1 Instead we need to rewrite as if ... { ssa_1 = ... } else { ssa_2 = undef } ssa_3 = phi ssa_1, ssa_2 foo ssa_3 By default, neither nir_validate nor the backends check this, so this doesn't currently fix a (known) real bug. But it's still invalid and fails validation with NIR_DEBUG=validate_ssa_dominance. Fix this in lower_helper_writes for intrinsics that return data (atomics). 3. Assert that the pass is run only for fragment shaders. This encourages backends to be judicious about which passes they call instead of just throwing everything in a giant lower everything spaghetti. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Italo Nicola <italonicola@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21413>
2023-02-20 14:16:05 -05:00
{
bool *lower_plain_stores = data;
switch (intr->intrinsic) {
case nir_intrinsic_global_atomic:
case nir_intrinsic_global_atomic_swap:
case nir_intrinsic_image_atomic:
case nir_intrinsic_image_atomic_swap:
case nir_intrinsic_bindless_image_atomic:
case nir_intrinsic_bindless_image_atomic_swap:
nir: Add nir_lower_helper_writes pass This NIR pass lowers stores in fragment shaders to: if (!gl_HelperInvocaton) { store(); } This implements the API requirement that helper invocations do not have visible side effects, and the lowering is required on any hardware that cannot directly mask helper invocation's side effects. The pass was originally written for Midgard (which has this issue) but is also needed for Asahi. Let's share the code, and fix it while we're at it. Changes from the Midgard pass: 1. Add an option to only lower atomics. AGX hardware can mask helper invocations for "plain" stores but not for atomics. Accordingly, the AGX compiler wants this lowering for atomics but not store_global. By contrast, Midgard cannot mask any stores and needs the lowering for all store intrinsics. Add an option to the common pass to accommodate both cases. This is an optimization for AGX. It is not required for correctness, this lowering is always legal. 2. Fix dominance issues. It's invalid to have NIR like if ... { ssa_1 = ... } foo ssa_1 Instead we need to rewrite as if ... { ssa_1 = ... } else { ssa_2 = undef } ssa_3 = phi ssa_1, ssa_2 foo ssa_3 By default, neither nir_validate nor the backends check this, so this doesn't currently fix a (known) real bug. But it's still invalid and fails validation with NIR_DEBUG=validate_ssa_dominance. Fix this in lower_helper_writes for intrinsics that return data (atomics). 3. Assert that the pass is run only for fragment shaders. This encourages backends to be judicious about which passes they call instead of just throwing everything in a giant lower everything spaghetti. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Italo Nicola <italonicola@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21413>
2023-02-20 14:16:05 -05:00
break;
case nir_intrinsic_store_global:
case nir_intrinsic_image_store:
case nir_intrinsic_bindless_image_store:
nir: Add nir_lower_helper_writes pass This NIR pass lowers stores in fragment shaders to: if (!gl_HelperInvocaton) { store(); } This implements the API requirement that helper invocations do not have visible side effects, and the lowering is required on any hardware that cannot directly mask helper invocation's side effects. The pass was originally written for Midgard (which has this issue) but is also needed for Asahi. Let's share the code, and fix it while we're at it. Changes from the Midgard pass: 1. Add an option to only lower atomics. AGX hardware can mask helper invocations for "plain" stores but not for atomics. Accordingly, the AGX compiler wants this lowering for atomics but not store_global. By contrast, Midgard cannot mask any stores and needs the lowering for all store intrinsics. Add an option to the common pass to accommodate both cases. This is an optimization for AGX. It is not required for correctness, this lowering is always legal. 2. Fix dominance issues. It's invalid to have NIR like if ... { ssa_1 = ... } foo ssa_1 Instead we need to rewrite as if ... { ssa_1 = ... } else { ssa_2 = undef } ssa_3 = phi ssa_1, ssa_2 foo ssa_3 By default, neither nir_validate nor the backends check this, so this doesn't currently fix a (known) real bug. But it's still invalid and fails validation with NIR_DEBUG=validate_ssa_dominance. Fix this in lower_helper_writes for intrinsics that return data (atomics). 3. Assert that the pass is run only for fragment shaders. This encourages backends to be judicious about which passes they call instead of just throwing everything in a giant lower everything spaghetti. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Italo Nicola <italonicola@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21413>
2023-02-20 14:16:05 -05:00
if (!(*lower_plain_stores))
return false;
else
break;
default:
return false;
}
b->cursor = nir_before_instr(&intr->instr);
nir: Add nir_lower_helper_writes pass This NIR pass lowers stores in fragment shaders to: if (!gl_HelperInvocaton) { store(); } This implements the API requirement that helper invocations do not have visible side effects, and the lowering is required on any hardware that cannot directly mask helper invocation's side effects. The pass was originally written for Midgard (which has this issue) but is also needed for Asahi. Let's share the code, and fix it while we're at it. Changes from the Midgard pass: 1. Add an option to only lower atomics. AGX hardware can mask helper invocations for "plain" stores but not for atomics. Accordingly, the AGX compiler wants this lowering for atomics but not store_global. By contrast, Midgard cannot mask any stores and needs the lowering for all store intrinsics. Add an option to the common pass to accommodate both cases. This is an optimization for AGX. It is not required for correctness, this lowering is always legal. 2. Fix dominance issues. It's invalid to have NIR like if ... { ssa_1 = ... } foo ssa_1 Instead we need to rewrite as if ... { ssa_1 = ... } else { ssa_2 = undef } ssa_3 = phi ssa_1, ssa_2 foo ssa_3 By default, neither nir_validate nor the backends check this, so this doesn't currently fix a (known) real bug. But it's still invalid and fails validation with NIR_DEBUG=validate_ssa_dominance. Fix this in lower_helper_writes for intrinsics that return data (atomics). 3. Assert that the pass is run only for fragment shaders. This encourages backends to be judicious about which passes they call instead of just throwing everything in a giant lower everything spaghetti. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Italo Nicola <italonicola@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21413>
2023-02-20 14:16:05 -05:00
bool has_dest = nir_intrinsic_infos[intr->intrinsic].has_dest;
nir_def *undef = NULL;
nir: Add nir_lower_helper_writes pass This NIR pass lowers stores in fragment shaders to: if (!gl_HelperInvocaton) { store(); } This implements the API requirement that helper invocations do not have visible side effects, and the lowering is required on any hardware that cannot directly mask helper invocation's side effects. The pass was originally written for Midgard (which has this issue) but is also needed for Asahi. Let's share the code, and fix it while we're at it. Changes from the Midgard pass: 1. Add an option to only lower atomics. AGX hardware can mask helper invocations for "plain" stores but not for atomics. Accordingly, the AGX compiler wants this lowering for atomics but not store_global. By contrast, Midgard cannot mask any stores and needs the lowering for all store intrinsics. Add an option to the common pass to accommodate both cases. This is an optimization for AGX. It is not required for correctness, this lowering is always legal. 2. Fix dominance issues. It's invalid to have NIR like if ... { ssa_1 = ... } foo ssa_1 Instead we need to rewrite as if ... { ssa_1 = ... } else { ssa_2 = undef } ssa_3 = phi ssa_1, ssa_2 foo ssa_3 By default, neither nir_validate nor the backends check this, so this doesn't currently fix a (known) real bug. But it's still invalid and fails validation with NIR_DEBUG=validate_ssa_dominance. Fix this in lower_helper_writes for intrinsics that return data (atomics). 3. Assert that the pass is run only for fragment shaders. This encourages backends to be judicious about which passes they call instead of just throwing everything in a giant lower everything spaghetti. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Italo Nicola <italonicola@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21413>
2023-02-20 14:16:05 -05:00
/* We need to use nir_is_helper_invocation instead of
* nir_load_helper_invocation, to correctly predicate stores after demote.
*/
nir_def *helper = nir_is_helper_invocation(b, 1);
nir: Add nir_lower_helper_writes pass This NIR pass lowers stores in fragment shaders to: if (!gl_HelperInvocaton) { store(); } This implements the API requirement that helper invocations do not have visible side effects, and the lowering is required on any hardware that cannot directly mask helper invocation's side effects. The pass was originally written for Midgard (which has this issue) but is also needed for Asahi. Let's share the code, and fix it while we're at it. Changes from the Midgard pass: 1. Add an option to only lower atomics. AGX hardware can mask helper invocations for "plain" stores but not for atomics. Accordingly, the AGX compiler wants this lowering for atomics but not store_global. By contrast, Midgard cannot mask any stores and needs the lowering for all store intrinsics. Add an option to the common pass to accommodate both cases. This is an optimization for AGX. It is not required for correctness, this lowering is always legal. 2. Fix dominance issues. It's invalid to have NIR like if ... { ssa_1 = ... } foo ssa_1 Instead we need to rewrite as if ... { ssa_1 = ... } else { ssa_2 = undef } ssa_3 = phi ssa_1, ssa_2 foo ssa_3 By default, neither nir_validate nor the backends check this, so this doesn't currently fix a (known) real bug. But it's still invalid and fails validation with NIR_DEBUG=validate_ssa_dominance. Fix this in lower_helper_writes for intrinsics that return data (atomics). 3. Assert that the pass is run only for fragment shaders. This encourages backends to be judicious about which passes they call instead of just throwing everything in a giant lower everything spaghetti. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Italo Nicola <italonicola@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21413>
2023-02-20 14:16:05 -05:00
nir_push_if(b, nir_inot(b, helper));
nir_instr_remove(&intr->instr);
nir_builder_instr_insert(b, &intr->instr);
nir: Add nir_lower_helper_writes pass This NIR pass lowers stores in fragment shaders to: if (!gl_HelperInvocaton) { store(); } This implements the API requirement that helper invocations do not have visible side effects, and the lowering is required on any hardware that cannot directly mask helper invocation's side effects. The pass was originally written for Midgard (which has this issue) but is also needed for Asahi. Let's share the code, and fix it while we're at it. Changes from the Midgard pass: 1. Add an option to only lower atomics. AGX hardware can mask helper invocations for "plain" stores but not for atomics. Accordingly, the AGX compiler wants this lowering for atomics but not store_global. By contrast, Midgard cannot mask any stores and needs the lowering for all store intrinsics. Add an option to the common pass to accommodate both cases. This is an optimization for AGX. It is not required for correctness, this lowering is always legal. 2. Fix dominance issues. It's invalid to have NIR like if ... { ssa_1 = ... } foo ssa_1 Instead we need to rewrite as if ... { ssa_1 = ... } else { ssa_2 = undef } ssa_3 = phi ssa_1, ssa_2 foo ssa_3 By default, neither nir_validate nor the backends check this, so this doesn't currently fix a (known) real bug. But it's still invalid and fails validation with NIR_DEBUG=validate_ssa_dominance. Fix this in lower_helper_writes for intrinsics that return data (atomics). 3. Assert that the pass is run only for fragment shaders. This encourages backends to be judicious about which passes they call instead of just throwing everything in a giant lower everything spaghetti. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Italo Nicola <italonicola@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21413>
2023-02-20 14:16:05 -05:00
/* Per the spec, it does not matter what we return for helper threads.
* Represent this by an ssa_undef in the hopes the backend will be clever
* enough to optimize out the phi.
*
* Fragment shader helper invocations execute the same shader code as
* non-helper invocations, but will not have side effects that modify the
* framebuffer or other shader-accessible memory. In particular:
*
* ...
*
* Atomic operations to image, buffer, or atomic counter variables
* performed by helper invocations have no effect on the underlying
* image or buffer memory. The values returned by such atomic
* operations are undefined.
*/
if (has_dest) {
nir_push_else(b, NULL);
undef = nir_undef(b, intr->def.num_components,
intr->def.bit_size);
nir: Add nir_lower_helper_writes pass This NIR pass lowers stores in fragment shaders to: if (!gl_HelperInvocaton) { store(); } This implements the API requirement that helper invocations do not have visible side effects, and the lowering is required on any hardware that cannot directly mask helper invocation's side effects. The pass was originally written for Midgard (which has this issue) but is also needed for Asahi. Let's share the code, and fix it while we're at it. Changes from the Midgard pass: 1. Add an option to only lower atomics. AGX hardware can mask helper invocations for "plain" stores but not for atomics. Accordingly, the AGX compiler wants this lowering for atomics but not store_global. By contrast, Midgard cannot mask any stores and needs the lowering for all store intrinsics. Add an option to the common pass to accommodate both cases. This is an optimization for AGX. It is not required for correctness, this lowering is always legal. 2. Fix dominance issues. It's invalid to have NIR like if ... { ssa_1 = ... } foo ssa_1 Instead we need to rewrite as if ... { ssa_1 = ... } else { ssa_2 = undef } ssa_3 = phi ssa_1, ssa_2 foo ssa_3 By default, neither nir_validate nor the backends check this, so this doesn't currently fix a (known) real bug. But it's still invalid and fails validation with NIR_DEBUG=validate_ssa_dominance. Fix this in lower_helper_writes for intrinsics that return data (atomics). 3. Assert that the pass is run only for fragment shaders. This encourages backends to be judicious about which passes they call instead of just throwing everything in a giant lower everything spaghetti. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Italo Nicola <italonicola@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21413>
2023-02-20 14:16:05 -05:00
}
nir_pop_if(b, NULL);
if (has_dest) {
nir_def *phi = nir_if_phi(b, &intr->def, undef);
nir: Add nir_lower_helper_writes pass This NIR pass lowers stores in fragment shaders to: if (!gl_HelperInvocaton) { store(); } This implements the API requirement that helper invocations do not have visible side effects, and the lowering is required on any hardware that cannot directly mask helper invocation's side effects. The pass was originally written for Midgard (which has this issue) but is also needed for Asahi. Let's share the code, and fix it while we're at it. Changes from the Midgard pass: 1. Add an option to only lower atomics. AGX hardware can mask helper invocations for "plain" stores but not for atomics. Accordingly, the AGX compiler wants this lowering for atomics but not store_global. By contrast, Midgard cannot mask any stores and needs the lowering for all store intrinsics. Add an option to the common pass to accommodate both cases. This is an optimization for AGX. It is not required for correctness, this lowering is always legal. 2. Fix dominance issues. It's invalid to have NIR like if ... { ssa_1 = ... } foo ssa_1 Instead we need to rewrite as if ... { ssa_1 = ... } else { ssa_2 = undef } ssa_3 = phi ssa_1, ssa_2 foo ssa_3 By default, neither nir_validate nor the backends check this, so this doesn't currently fix a (known) real bug. But it's still invalid and fails validation with NIR_DEBUG=validate_ssa_dominance. Fix this in lower_helper_writes for intrinsics that return data (atomics). 3. Assert that the pass is run only for fragment shaders. This encourages backends to be judicious about which passes they call instead of just throwing everything in a giant lower everything spaghetti. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Italo Nicola <italonicola@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21413>
2023-02-20 14:16:05 -05:00
/* We can't use nir_def_rewrite_uses_after on phis, so use the global
nir: Add nir_lower_helper_writes pass This NIR pass lowers stores in fragment shaders to: if (!gl_HelperInvocaton) { store(); } This implements the API requirement that helper invocations do not have visible side effects, and the lowering is required on any hardware that cannot directly mask helper invocation's side effects. The pass was originally written for Midgard (which has this issue) but is also needed for Asahi. Let's share the code, and fix it while we're at it. Changes from the Midgard pass: 1. Add an option to only lower atomics. AGX hardware can mask helper invocations for "plain" stores but not for atomics. Accordingly, the AGX compiler wants this lowering for atomics but not store_global. By contrast, Midgard cannot mask any stores and needs the lowering for all store intrinsics. Add an option to the common pass to accommodate both cases. This is an optimization for AGX. It is not required for correctness, this lowering is always legal. 2. Fix dominance issues. It's invalid to have NIR like if ... { ssa_1 = ... } foo ssa_1 Instead we need to rewrite as if ... { ssa_1 = ... } else { ssa_2 = undef } ssa_3 = phi ssa_1, ssa_2 foo ssa_3 By default, neither nir_validate nor the backends check this, so this doesn't currently fix a (known) real bug. But it's still invalid and fails validation with NIR_DEBUG=validate_ssa_dominance. Fix this in lower_helper_writes for intrinsics that return data (atomics). 3. Assert that the pass is run only for fragment shaders. This encourages backends to be judicious about which passes they call instead of just throwing everything in a giant lower everything spaghetti. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Italo Nicola <italonicola@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21413>
2023-02-20 14:16:05 -05:00
* version and fixup the phi manually
*/
nir_def_rewrite_uses(&intr->def, phi);
nir: Add nir_lower_helper_writes pass This NIR pass lowers stores in fragment shaders to: if (!gl_HelperInvocaton) { store(); } This implements the API requirement that helper invocations do not have visible side effects, and the lowering is required on any hardware that cannot directly mask helper invocation's side effects. The pass was originally written for Midgard (which has this issue) but is also needed for Asahi. Let's share the code, and fix it while we're at it. Changes from the Midgard pass: 1. Add an option to only lower atomics. AGX hardware can mask helper invocations for "plain" stores but not for atomics. Accordingly, the AGX compiler wants this lowering for atomics but not store_global. By contrast, Midgard cannot mask any stores and needs the lowering for all store intrinsics. Add an option to the common pass to accommodate both cases. This is an optimization for AGX. It is not required for correctness, this lowering is always legal. 2. Fix dominance issues. It's invalid to have NIR like if ... { ssa_1 = ... } foo ssa_1 Instead we need to rewrite as if ... { ssa_1 = ... } else { ssa_2 = undef } ssa_3 = phi ssa_1, ssa_2 foo ssa_3 By default, neither nir_validate nor the backends check this, so this doesn't currently fix a (known) real bug. But it's still invalid and fails validation with NIR_DEBUG=validate_ssa_dominance. Fix this in lower_helper_writes for intrinsics that return data (atomics). 3. Assert that the pass is run only for fragment shaders. This encourages backends to be judicious about which passes they call instead of just throwing everything in a giant lower everything spaghetti. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Italo Nicola <italonicola@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21413>
2023-02-20 14:16:05 -05:00
nir_phi_instr *phi_instr = nir_def_as_phi(phi);
nir_phi_src *phi_src = nir_phi_get_src_from_block(phi_instr,
intr->instr.block);
nir_src_rewrite(&phi_src->src, &intr->def);
nir: Add nir_lower_helper_writes pass This NIR pass lowers stores in fragment shaders to: if (!gl_HelperInvocaton) { store(); } This implements the API requirement that helper invocations do not have visible side effects, and the lowering is required on any hardware that cannot directly mask helper invocation's side effects. The pass was originally written for Midgard (which has this issue) but is also needed for Asahi. Let's share the code, and fix it while we're at it. Changes from the Midgard pass: 1. Add an option to only lower atomics. AGX hardware can mask helper invocations for "plain" stores but not for atomics. Accordingly, the AGX compiler wants this lowering for atomics but not store_global. By contrast, Midgard cannot mask any stores and needs the lowering for all store intrinsics. Add an option to the common pass to accommodate both cases. This is an optimization for AGX. It is not required for correctness, this lowering is always legal. 2. Fix dominance issues. It's invalid to have NIR like if ... { ssa_1 = ... } foo ssa_1 Instead we need to rewrite as if ... { ssa_1 = ... } else { ssa_2 = undef } ssa_3 = phi ssa_1, ssa_2 foo ssa_3 By default, neither nir_validate nor the backends check this, so this doesn't currently fix a (known) real bug. But it's still invalid and fails validation with NIR_DEBUG=validate_ssa_dominance. Fix this in lower_helper_writes for intrinsics that return data (atomics). 3. Assert that the pass is run only for fragment shaders. This encourages backends to be judicious about which passes they call instead of just throwing everything in a giant lower everything spaghetti. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Italo Nicola <italonicola@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21413>
2023-02-20 14:16:05 -05:00
}
return true;
}
bool
nir_lower_helper_writes(nir_shader *shader, bool lower_plain_stores)
{
assert(shader->info.stage == MESA_SHADER_FRAGMENT);
return nir_shader_intrinsics_pass(shader, lower, nir_metadata_none,
&lower_plain_stores);
nir: Add nir_lower_helper_writes pass This NIR pass lowers stores in fragment shaders to: if (!gl_HelperInvocaton) { store(); } This implements the API requirement that helper invocations do not have visible side effects, and the lowering is required on any hardware that cannot directly mask helper invocation's side effects. The pass was originally written for Midgard (which has this issue) but is also needed for Asahi. Let's share the code, and fix it while we're at it. Changes from the Midgard pass: 1. Add an option to only lower atomics. AGX hardware can mask helper invocations for "plain" stores but not for atomics. Accordingly, the AGX compiler wants this lowering for atomics but not store_global. By contrast, Midgard cannot mask any stores and needs the lowering for all store intrinsics. Add an option to the common pass to accommodate both cases. This is an optimization for AGX. It is not required for correctness, this lowering is always legal. 2. Fix dominance issues. It's invalid to have NIR like if ... { ssa_1 = ... } foo ssa_1 Instead we need to rewrite as if ... { ssa_1 = ... } else { ssa_2 = undef } ssa_3 = phi ssa_1, ssa_2 foo ssa_3 By default, neither nir_validate nor the backends check this, so this doesn't currently fix a (known) real bug. But it's still invalid and fails validation with NIR_DEBUG=validate_ssa_dominance. Fix this in lower_helper_writes for intrinsics that return data (atomics). 3. Assert that the pass is run only for fragment shaders. This encourages backends to be judicious about which passes they call instead of just throwing everything in a giant lower everything spaghetti. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Reviewed-by: Italo Nicola <italonicola@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21413>
2023-02-20 14:16:05 -05:00
}