zink: extend shadow swizzle pass to all zs textures

if needs_zs_shader_swizzle is used, apply constant swizzles to all
depth/stencil textures and not just shadow samplers.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21571>
This commit is contained in:
SoroushIMG
2023-02-26 17:48:53 +00:00
committed by Marge Bot
parent 79557c2747
commit cc15dbc4f8
+68 -15
View File
@@ -2922,14 +2922,26 @@ rewrite_tex_dest(nir_builder *b, nir_tex_instr *tex, nir_variable *var, void *da
return dest;
}
struct lower_zs_swizzle_state {
bool shadow_only;
unsigned base_sampler_id;
const struct zink_fs_shadow_key *swizzle;
};
static bool
lower_shadow_tex_instr(nir_builder *b, nir_instr *instr, void *data)
lower_zs_swizzle_tex_instr(nir_builder *b, nir_instr *instr, void *data)
{
struct zink_fs_shadow_key *shadow = data;
struct lower_zs_swizzle_state *state = data;
const struct zink_fs_shadow_key *swizzle_key = state->swizzle;
assert(state->shadow_only || swizzle_key);
if (instr->type != nir_instr_type_tex)
return false;
nir_tex_instr *tex = nir_instr_as_tex(instr);
if (tex->op == nir_texop_txs || tex->op == nir_texop_lod || !tex->is_shadow || tex->is_new_style_shadow)
if (tex->op == nir_texop_txs || tex->op == nir_texop_lod ||
(!tex->is_shadow && state->shadow_only) || tex->is_new_style_shadow)
return false;
if (tex->is_shadow && tex->op == nir_texop_tg4)
/* Will not even try to emulate the shadow comparison */
return false;
int handle = nir_tex_instr_src_index(tex, nir_tex_src_texture_handle);
nir_variable *var = NULL;
@@ -2947,31 +2959,66 @@ lower_shadow_tex_instr(nir_builder *b, nir_instr *instr, void *data)
}
}
assert(var);
uint32_t sampler_id = var->data.binding - (PIPE_MAX_SAMPLERS * MESA_SHADER_FRAGMENT);
uint32_t sampler_id = var->data.binding - state->base_sampler_id;
const struct glsl_type *type = glsl_without_array(var->type);
enum glsl_base_type ret_type = glsl_get_sampler_result_type(type);
bool is_int = glsl_base_type_is_integer(ret_type);
unsigned num_components = nir_dest_num_components(tex->dest);
if (tex->is_shadow)
tex->is_new_style_shadow = true;
nir_ssa_def *dest = rewrite_tex_dest(b, tex, var, NULL);
assert(!tex->is_new_style_shadow);
tex->dest.ssa.num_components = 1;
tex->is_new_style_shadow = true;
if (shadow && (shadow->mask & BITFIELD_BIT(sampler_id))) {
assert(dest || !state->shadow_only);
if (!dest && !(swizzle_key->mask & BITFIELD_BIT(sampler_id)))
return false;
else if (!dest)
dest = &tex->dest.ssa;
else
tex->dest.ssa.num_components = 1;
if (swizzle_key && (swizzle_key->mask & BITFIELD_BIT(sampler_id))) {
/* these require manual swizzles */
if (tex->op == nir_texop_tg4) {
assert(!tex->is_shadow);
nir_ssa_def *swizzle;
switch (swizzle_key->swizzle[sampler_id].s[tex->component]) {
case PIPE_SWIZZLE_0:
swizzle = nir_imm_zero(b, 4, nir_dest_bit_size(tex->dest));
break;
case PIPE_SWIZZLE_1:
if (is_int)
swizzle = nir_imm_intN_t(b, 4, nir_dest_bit_size(tex->dest));
else
swizzle = nir_imm_floatN_t(b, 4, nir_dest_bit_size(tex->dest));
break;
default:
if (!tex->component)
return false;
tex->component = 0;
return true;
}
nir_ssa_def_rewrite_uses_after(dest, swizzle, swizzle->parent_instr);
return true;
}
nir_ssa_def *vec[4];
for (unsigned i = 0; i < ARRAY_SIZE(vec); i++) {
switch (shadow->swizzle[sampler_id].s[i]) {
switch (swizzle_key->swizzle[sampler_id].s[i]) {
case PIPE_SWIZZLE_0:
vec[i] = nir_imm_zero(b, 1, nir_dest_bit_size(tex->dest));
break;
case PIPE_SWIZZLE_1:
vec[i] = nir_imm_floatN_t(b, 1, nir_dest_bit_size(tex->dest));
if (is_int)
vec[i] = nir_imm_intN_t(b, 1, nir_dest_bit_size(tex->dest));
else
vec[i] = nir_imm_floatN_t(b, 1, nir_dest_bit_size(tex->dest));
break;
default:
vec[i] = dest;
vec[i] = dest->num_components == 1 ? dest : nir_channel(b, dest, i);
break;
}
}
nir_ssa_def *swizzle = nir_vec(b, vec, num_components);
nir_ssa_def_rewrite_uses_after(dest, swizzle, swizzle->parent_instr);
} else {
assert(tex->is_shadow);
nir_ssa_def *vec[4] = {dest, dest, dest, dest};
nir_ssa_def *splat = nir_vec(b, vec, num_components);
nir_ssa_def_rewrite_uses_after(dest, splat, splat->parent_instr);
@@ -2980,9 +3027,11 @@ lower_shadow_tex_instr(nir_builder *b, nir_instr *instr, void *data)
}
static bool
lower_shadow_tex(nir_shader *nir, const void *shadow)
lower_zs_swizzle_tex(nir_shader *nir, const void *swizzle, bool shadow_only)
{
return nir_shader_instructions_pass(nir, lower_shadow_tex_instr, nir_metadata_dominance | nir_metadata_block_index, (void*)shadow);
unsigned base_sampler_id = gl_shader_stage_is_compute(nir->info.stage) ? 0 : PIPE_MAX_SAMPLERS * nir->info.stage;
struct lower_zs_swizzle_state state = {shadow_only, base_sampler_id, swizzle};
return nir_shader_instructions_pass(nir, lower_zs_swizzle_tex_instr, nir_metadata_dominance | nir_metadata_block_index, (void*)&state);
}
static bool
@@ -3165,8 +3214,8 @@ zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs,
nir->info.fs.uses_sample_qualifier = true;
nir->info.fs.uses_sample_shading = true;
}
if (zs->fs.legacy_shadow_mask)
NIR_PASS_V(nir, lower_shadow_tex, zink_fs_key_base(key)->shadow_needs_shader_swizzle ? extra_data : NULL);
if (zs->fs.legacy_shadow_mask && !key->base.needs_zs_shader_swizzle)
NIR_PASS(need_optimize, nir, lower_zs_swizzle_tex, zink_fs_key_base(key)->shadow_needs_shader_swizzle ? extra_data : NULL, true);
if (nir->info.fs.uses_fbfetch_output) {
nir_variable *fbfetch = NULL;
NIR_PASS_V(nir, lower_fbfetch, &fbfetch, zink_fs_key_base(key)->fbfetch_ms);
@@ -3192,6 +3241,10 @@ zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs,
break;
default: break;
}
if (key->base.needs_zs_shader_swizzle) {
assert(extra_data);
NIR_PASS(need_optimize, nir, lower_zs_swizzle_tex, extra_data, false);
}
if (key->base.nonseamless_cube_mask) {
NIR_PASS_V(nir, zink_lower_cubemap_to_array, key->base.nonseamless_cube_mask);
need_optimize = true;