r300: move shadow lowering to NIR

This means we now do fragment shader-variants at the NIR level and we
therefore need to run nir_to_rc translation later during the shader
variant creation.

This is a temporary instruction count as well as registers count
regression, due to NIR putting everything to x instead of w, this is
fixed in the next commit which also shows some nice shader-db stats
improvements in total.

Signed-off-by: Pavel Ondračka <pavel.ondracka@gmail.com>
Reviewed-by: Filip Gawin <None>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33066>
This commit is contained in:
Pavel Ondračka 2024-02-05 20:35:27 +01:00 committed by Marge Bot
parent ea41ecd130
commit 296da387c0
6 changed files with 78 additions and 26 deletions

View file

@ -739,7 +739,6 @@ spec@glsl-1.10@execution@interpolation@interpolation-none-other-smooth-vertex,Fa
# HW limitation (SM3 256 loop iters)
spec@glsl-1.10@execution@loops@glsl-fs-loop-300,Fail
spec@glsl-1.10@execution@loops@glsl-vs-loop-300,Fail
spec@glsl-1.10@execution@variable-indexing@vs-output-array-vec2-index-wr-no-unroll,Fail
# HW limitation (no support for gl_ClipVertex)

View file

@ -8,6 +8,10 @@
#include "compiler/nir/nir_deref.h"
#include "compiler/nir/nir_legacy.h"
#include "compiler/nir/nir_worklist.h"
#include "compiler/radeon_code.h"
#include "compiler/radeon_program_constants.h"
#include "r300_nir.h"
#include "r300_screen.h"
#include "pipe/p_screen.h"
#include "pipe/p_state.h"
#include "tgsi/tgsi_dump.h"
@ -803,8 +807,7 @@ ntr_setup_uniforms(struct ntr_compile *c)
const struct glsl_type *stype = glsl_without_array(var->type);
enum tgsi_texture_type target = tgsi_texture_type_from_sampler_dim(
glsl_get_sampler_dim(stype), glsl_sampler_type_is_array(stype),
glsl_sampler_type_is_shadow(stype));
glsl_get_sampler_dim(stype), glsl_sampler_type_is_array(stype), false);
enum tgsi_return_type ret_type =
tgsi_return_type_from_base_type(glsl_get_sampler_result_type(stype));
for (int i = 0; i < size; i++) {
@ -2240,7 +2243,8 @@ nir_to_rc_lower_txp(nir_shader *s)
* TGSI tokens instead. If you need to keep the NIR, then pass us a clone.
*/
const void *
nir_to_rc(struct nir_shader *s, struct pipe_screen *screen)
nir_to_rc(struct nir_shader *s, struct pipe_screen *screen,
struct r300_fragment_program_external_state state)
{
struct ntr_compile *c;
const void *tgsi_tokens;
@ -2286,8 +2290,27 @@ nir_to_rc(struct nir_shader *s, struct pipe_screen *screen)
NIR_PASS_V(s, nir_lower_io, nir_var_shader_in | nir_var_shader_out, type_size,
nir_lower_io_use_interpolated_input_intrinsics);
nir_to_rc_lower_txp(s);
NIR_PASS_V(s, nir_to_rc_lower_tex);
if (s->info.stage == MESA_SHADER_FRAGMENT) {
/* Shadow lowering. */
int num_texture_states = state.sampler_state_count;
if (num_texture_states > 0) {
nir_lower_tex_shadow_swizzle tex_swizzle[PIPE_MAX_SHADER_SAMPLER_VIEWS];
enum compare_func tex_compare_func[PIPE_MAX_SHADER_SAMPLER_VIEWS];
for (unsigned i = 0; i < num_texture_states; i++) {
tex_compare_func[i] = state.unit[i].texture_compare_func;
tex_swizzle[i].swizzle_r = GET_SWZ(state.unit[i].texture_swizzle, 0);
tex_swizzle[i].swizzle_g = GET_SWZ(state.unit[i].texture_swizzle, 1);
tex_swizzle[i].swizzle_b = GET_SWZ(state.unit[i].texture_swizzle, 2);
tex_swizzle[i].swizzle_a = GET_SWZ(state.unit[i].texture_swizzle, 3);
}
NIR_PASS_V(s, nir_lower_tex_shadow, num_texture_states, tex_compare_func,
tex_swizzle, true);
}
nir_to_rc_lower_txp(s);
NIR_PASS_V(s, nir_to_rc_lower_tex);
}
bool progress;
do {

View file

@ -11,7 +11,9 @@
struct nir_shader;
struct pipe_screen;
struct r300_fragment_program_external_state;
const void *nir_to_rc(struct nir_shader *s, struct pipe_screen *screen);
const void *nir_to_rc(struct nir_shader *s, struct pipe_screen *screen,
struct r300_fragment_program_external_state state);
#endif /* NIR_TO_RC_H */

View file

@ -160,6 +160,8 @@ struct r300_fragment_program_external_state {
} unit[16];
unsigned alpha_to_one : 1;
int sampler_state_count;
};
struct r300_fragment_program_node {

View file

@ -22,6 +22,8 @@
#include "r300_tgsi_to_rc.h"
#include "compiler/radeon_compiler.h"
#include "compiler/nir_to_rc.h"
#include "nir.h"
/* Convert info about FS input semantics to r300_shader_semantics. */
void r300_shader_read_fs_inputs(struct tgsi_shader_info* info,
@ -151,6 +153,7 @@ void r300_fragment_program_get_external_state(
unsigned i;
state->alpha_to_one = r300->alpha_to_one && r300->msaa_enable;
state->sampler_state_count = texstate->sampler_state_count;
for (i = 0; i < texstate->sampler_state_count; i++) {
struct r300_sampler_state *s = texstate->sampler_states[i];
@ -207,7 +210,7 @@ void r300_fragment_program_get_external_state(
static void r300_translate_fragment_shader(
struct r300_context* r300,
struct r300_fragment_shader_code* shader,
const struct tgsi_token *tokens);
struct pipe_shader_state state);
static void r300_dummy_fragment_shader(
struct r300_context* r300,
@ -229,7 +232,7 @@ static void r300_dummy_fragment_shader(
state.tokens = ureg_finalize(ureg);
shader->dummy = true;
r300_translate_fragment_shader(r300, shader, state.tokens);
r300_translate_fragment_shader(r300, shader, state);
ureg_destroy(ureg);
}
@ -416,14 +419,19 @@ static void r300_emit_fs_code_to_buffer(
static void r300_translate_fragment_shader(
struct r300_context* r300,
struct r300_fragment_shader_code* shader,
const struct tgsi_token *tokens)
struct pipe_shader_state state)
{
struct r300_fragment_program_compiler compiler;
struct tgsi_to_rc ttr;
int wpos, face;
unsigned i;
tgsi_scan_shader(tokens, &shader->info);
if (state.type == PIPE_SHADER_IR_NIR) {
nir_shader *clone = nir_shader_clone(NULL, state.ir.nir);
state.tokens = nir_to_rc(clone, (struct pipe_screen *)r300->screen, shader->compare_state);
}
tgsi_scan_shader(state.tokens, &shader->info);
r300_shader_read_fs_inputs(&shader->info, &shader->inputs);
wpos = shader->inputs.wpos;
@ -461,14 +469,18 @@ static void r300_translate_fragment_shader(
if (compiler.Base.Debug & RC_DBG_LOG) {
DBG(r300, DBG_FP, "r300: Initial fragment program\n");
tgsi_dump(tokens, 0);
tgsi_dump(state.tokens, 0);
}
/* Translate TGSI to our internal representation */
ttr.compiler = &compiler.Base;
ttr.info = &shader->info;
r300_tgsi_to_rc(&ttr, tokens);
r300_tgsi_to_rc(&ttr, state.tokens);
if (state.type == PIPE_SHADER_IR_NIR) {
FREE((void*)state.tokens);
}
if (ttr.error) {
fprintf(stderr, "r300 FP: Cannot translate a shader. "
@ -576,7 +588,7 @@ bool r300_pick_fragment_shader(struct r300_context *r300,
fs->first = fs->shader = CALLOC_STRUCT(r300_fragment_shader_code);
memcpy(&fs->shader->compare_state, state, sizeof(*state));
r300_translate_fragment_shader(r300, fs->shader, fs->state.tokens);
r300_translate_fragment_shader(r300, fs->shader, fs->state);
return true;
} else {
@ -603,7 +615,7 @@ bool r300_pick_fragment_shader(struct r300_context *r300,
fs->first = fs->shader = ptr;
memcpy(&ptr->compare_state, state, sizeof(*state));
r300_translate_fragment_shader(r300, ptr, fs->state.tokens);
r300_translate_fragment_shader(r300, ptr, fs->state);
return true;
}
}

View file

@ -1029,7 +1029,7 @@ static void* r300_create_fs_state(struct pipe_context* pipe,
fs->state = *shader;
if (fs->state.type == PIPE_SHADER_IR_NIR) {
fs->state.tokens = nir_to_rc(shader->ir.nir, pipe->screen);
//fs->state.tokens = nir_to_rc(shader->ir.nir, pipe->screen);
} else {
assert(fs->state.type == PIPE_SHADER_IR_TGSI);
/* we need to keep a local copy of the tokens */
@ -1042,14 +1042,23 @@ static void* r300_create_fs_state(struct pipe_context* pipe,
struct r300_fragment_program_external_state precompile_state;
memset(&precompile_state, 0, sizeof(precompile_state));
struct tgsi_shader_info info;
tgsi_scan_shader(fs->state.tokens, &info);
for (int i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) {
if (info.sampler_targets[i] == TGSI_TEXTURE_SHADOW1D ||
info.sampler_targets[i] == TGSI_TEXTURE_SHADOW2D ||
info.sampler_targets[i] == TGSI_TEXTURE_SHADOWRECT) {
precompile_state.unit[i].compare_mode_enabled = true;
precompile_state.unit[i].texture_compare_func = PIPE_FUNC_LESS;
if (fs->state.type == PIPE_SHADER_IR_NIR) {
/* Pick something for the shadow samplers so that we have somewhat reliable shader stats later. */
nir_foreach_function_impl(impl, shader->ir.nir) {
nir_foreach_block_safe(block, impl) {
nir_foreach_instr_safe(instr, block) {
if (instr->type != nir_instr_type_tex)
continue;
nir_tex_instr *tex = nir_instr_as_tex(instr);
if (tex->is_shadow) {
precompile_state.unit[tex->sampler_index].compare_mode_enabled = true;
precompile_state.unit[tex->sampler_index].texture_compare_func = PIPE_FUNC_LESS;
}
precompile_state.sampler_state_count = MAX2(tex->sampler_index + 1,
precompile_state.sampler_state_count);
}
}
}
}
r300_pick_fragment_shader(r300, fs, &precompile_state);
@ -1110,7 +1119,11 @@ static void r300_delete_fs_state(struct pipe_context* pipe, void* shader)
FREE(tmp->cb_code);
FREE(tmp);
}
FREE((void*)fs->state.tokens);
if (fs->state.type == PIPE_SHADER_IR_NIR) {
ralloc_free(fs->state.ir.nir);
} else {
FREE((void*)fs->state.tokens);
}
FREE(shader);
}
@ -1921,7 +1934,8 @@ static void* r300_create_vs_state(struct pipe_context* pipe,
vs->state = *shader;
if (vs->state.type == PIPE_SHADER_IR_NIR) {
vs->state.tokens = nir_to_rc(shader->ir.nir, pipe->screen);
struct r300_fragment_program_external_state state = {};
vs->state.tokens = nir_to_rc(shader->ir.nir, pipe->screen, state);
} else {
assert(vs->state.type == PIPE_SHADER_IR_TGSI);
/* we need to keep a local copy of the tokens */