mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 13:58:04 +02:00
radeonsi,aco: remove the VS prolog
The upside is that this removes 600 lines of code. The downside is that if instance divisors are used, we will compile the VS on demand. Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27120>
This commit is contained in:
parent
0496cd5e5a
commit
72948d9ff9
21 changed files with 73 additions and 670 deletions
|
|
@ -12114,55 +12114,6 @@ store_tess_factor_to_tess_ring(isel_context* ctx, Temp tess_ring_desc, Temp fact
|
|||
memory_sync_info(storage_vmem_output), true, false, false);
|
||||
}
|
||||
|
||||
Temp
|
||||
build_fast_udiv_nuw(isel_context* ctx, Temp num, Temp multiplier, Temp pre_shift, Temp post_shift,
|
||||
Temp increment)
|
||||
{
|
||||
Builder bld(ctx->program, ctx->block);
|
||||
|
||||
num = bld.vop2(aco_opcode::v_lshrrev_b32, bld.def(v1), pre_shift, num);
|
||||
num = bld.nuw().vadd32(bld.def(v1), num, increment);
|
||||
num = bld.vop3(aco_opcode::v_mul_hi_u32, bld.def(v1), num, multiplier);
|
||||
return bld.vop2(aco_opcode::v_lshrrev_b32, bld.def(v1), post_shift, num);
|
||||
}
|
||||
|
||||
Temp
|
||||
get_gl_vs_prolog_vertex_index(isel_context* ctx, const struct aco_gl_vs_prolog_info* vinfo,
|
||||
unsigned input_index, Temp instance_divisor_constbuf)
|
||||
{
|
||||
bool divisor_is_one = vinfo->instance_divisor_is_one & (1u << input_index);
|
||||
bool divisor_is_fetched = vinfo->instance_divisor_is_fetched & (1u << input_index);
|
||||
|
||||
Builder bld(ctx->program, ctx->block);
|
||||
|
||||
Temp index;
|
||||
if (divisor_is_one) {
|
||||
index = get_arg(ctx, ctx->args->instance_id);
|
||||
} else if (divisor_is_fetched) {
|
||||
Temp instance_id = get_arg(ctx, ctx->args->instance_id);
|
||||
|
||||
Temp udiv_factors = bld.smem(aco_opcode::s_buffer_load_dwordx4, bld.def(s4),
|
||||
instance_divisor_constbuf, Operand::c32(input_index * 16));
|
||||
emit_split_vector(ctx, udiv_factors, 4);
|
||||
|
||||
index = build_fast_udiv_nuw(ctx, instance_id, emit_extract_vector(ctx, udiv_factors, 0, s1),
|
||||
emit_extract_vector(ctx, udiv_factors, 1, s1),
|
||||
emit_extract_vector(ctx, udiv_factors, 2, s1),
|
||||
emit_extract_vector(ctx, udiv_factors, 3, s1));
|
||||
}
|
||||
|
||||
if (divisor_is_one || divisor_is_fetched) {
|
||||
Temp start_instance = get_arg(ctx, ctx->args->start_instance);
|
||||
index = bld.vadd32(bld.def(v1), index, start_instance);
|
||||
} else {
|
||||
Temp base_vertex = get_arg(ctx, ctx->args->base_vertex);
|
||||
Temp vertex_id = get_arg(ctx, ctx->args->vertex_id);
|
||||
index = bld.vadd32(bld.def(v1), base_vertex, vertex_id);
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void
|
||||
emit_polygon_stipple(isel_context* ctx, const struct aco_ps_prolog_info* finfo)
|
||||
{
|
||||
|
|
@ -13348,56 +13299,6 @@ select_tcs_epilog(Program* program, void* pinfo, ac_shader_config* config,
|
|||
finish_program(&ctx);
|
||||
}
|
||||
|
||||
void
|
||||
select_gl_vs_prolog(Program* program, void* pinfo, ac_shader_config* config,
|
||||
const struct aco_compiler_options* options, const struct aco_shader_info* info,
|
||||
const struct ac_shader_args* args)
|
||||
{
|
||||
const struct aco_gl_vs_prolog_info* vinfo = (const struct aco_gl_vs_prolog_info*)pinfo;
|
||||
isel_context ctx =
|
||||
setup_isel_context(program, 0, NULL, config, options, info, args, SWStage::VS);
|
||||
|
||||
ctx.block->fp_mode = program->next_fp_mode;
|
||||
|
||||
add_startpgm(&ctx);
|
||||
append_logical_start(ctx.block);
|
||||
|
||||
Builder bld(ctx.program, ctx.block);
|
||||
|
||||
bld.sopp(aco_opcode::s_setprio, -1u, 0x3u);
|
||||
|
||||
if (vinfo->as_ls && options->has_ls_vgpr_init_bug)
|
||||
fix_ls_vgpr_init_bug(&ctx);
|
||||
|
||||
std::vector<Operand> regs;
|
||||
passthrough_all_args(&ctx, regs);
|
||||
|
||||
Temp instance_divisor_constbuf;
|
||||
|
||||
if (vinfo->instance_divisor_is_fetched) {
|
||||
Temp list = get_arg(&ctx, vinfo->internal_bindings);
|
||||
list = convert_pointer_to_64_bit(&ctx, list);
|
||||
|
||||
instance_divisor_constbuf = bld.smem(aco_opcode::s_load_dwordx4, bld.def(s4), list,
|
||||
Operand::c32(vinfo->instance_diviser_buf_offset));
|
||||
}
|
||||
|
||||
unsigned vgpr = 256 + ctx.args->num_vgprs_used;
|
||||
|
||||
for (unsigned i = 0; i < vinfo->num_inputs; i++) {
|
||||
Temp index = get_gl_vs_prolog_vertex_index(&ctx, vinfo, i, instance_divisor_constbuf);
|
||||
regs.emplace_back(Operand(index, PhysReg{vgpr + i}));
|
||||
}
|
||||
|
||||
program->config->float_mode = program->blocks[0].fp_mode.val;
|
||||
|
||||
append_logical_end(ctx.block);
|
||||
|
||||
build_end_with_regs(&ctx, regs);
|
||||
|
||||
finish_program(&ctx);
|
||||
}
|
||||
|
||||
void
|
||||
select_ps_prolog(Program* program, void* pinfo, ac_shader_config* config,
|
||||
const struct aco_compiler_options* options, const struct aco_shader_info* info,
|
||||
|
|
|
|||
|
|
@ -417,17 +417,6 @@ aco_compile_tcs_epilog(const struct aco_compiler_options* options,
|
|||
binary);
|
||||
}
|
||||
|
||||
void
|
||||
aco_compile_gl_vs_prolog(const struct aco_compiler_options* options,
|
||||
const struct aco_shader_info* info,
|
||||
const struct aco_gl_vs_prolog_info* pinfo,
|
||||
const struct ac_shader_args* args, aco_shader_part_callback* build_prolog,
|
||||
void** binary)
|
||||
{
|
||||
aco_compile_shader_part(options, info, args, aco::select_gl_vs_prolog, (void*)pinfo,
|
||||
build_prolog, binary, true);
|
||||
}
|
||||
|
||||
void
|
||||
aco_compile_ps_prolog(const struct aco_compiler_options* options,
|
||||
const struct aco_shader_info* info, const struct aco_ps_prolog_info* pinfo,
|
||||
|
|
|
|||
|
|
@ -88,12 +88,6 @@ void aco_compile_tcs_epilog(const struct aco_compiler_options* options,
|
|||
const struct ac_shader_args* args,
|
||||
aco_shader_part_callback* build_epilog, void** binary);
|
||||
|
||||
void aco_compile_gl_vs_prolog(const struct aco_compiler_options* options,
|
||||
const struct aco_shader_info* info,
|
||||
const struct aco_gl_vs_prolog_info* pinfo,
|
||||
const struct ac_shader_args* args,
|
||||
aco_shader_part_callback* build_prolog, void** binary);
|
||||
|
||||
void aco_compile_ps_prolog(const struct aco_compiler_options* options,
|
||||
const struct aco_shader_info* info,
|
||||
const struct aco_ps_prolog_info* pinfo,
|
||||
|
|
|
|||
|
|
@ -2203,10 +2203,6 @@ void select_tcs_epilog(Program* program, void* pinfo, ac_shader_config* config,
|
|||
const struct aco_compiler_options* options,
|
||||
const struct aco_shader_info* info, const struct ac_shader_args* args);
|
||||
|
||||
void select_gl_vs_prolog(Program* program, void* pinfo, ac_shader_config* config,
|
||||
const struct aco_compiler_options* options,
|
||||
const struct aco_shader_info* info, const struct ac_shader_args* args);
|
||||
|
||||
void select_ps_prolog(Program* program, void* pinfo, ac_shader_config* config,
|
||||
const struct aco_compiler_options* options,
|
||||
const struct aco_shader_info* info, const struct ac_shader_args* args);
|
||||
|
|
|
|||
|
|
@ -105,16 +105,6 @@ struct aco_tcs_epilog_info {
|
|||
struct ac_arg tcs_offchip_layout;
|
||||
};
|
||||
|
||||
struct aco_gl_vs_prolog_info {
|
||||
uint16_t instance_divisor_is_one;
|
||||
uint16_t instance_divisor_is_fetched;
|
||||
unsigned instance_diviser_buf_offset;
|
||||
unsigned num_inputs;
|
||||
bool as_ls;
|
||||
|
||||
struct ac_arg internal_bindings;
|
||||
};
|
||||
|
||||
struct aco_ps_prolog_info {
|
||||
bool poly_stipple;
|
||||
unsigned poly_stipple_buf_offset;
|
||||
|
|
|
|||
|
|
@ -140,8 +140,8 @@ retry_select_mode:
|
|||
bool uses_primitive_id = gs_sel->info.uses_primid;
|
||||
if (gs_stage == MESA_SHADER_VERTEX) {
|
||||
uses_instance_id |=
|
||||
shader->key.ge.part.vs.prolog.instance_divisor_is_one ||
|
||||
shader->key.ge.part.vs.prolog.instance_divisor_is_fetched;
|
||||
shader->key.ge.mono.instance_divisor_is_one ||
|
||||
shader->key.ge.mono.instance_divisor_is_fetched;
|
||||
} else {
|
||||
uses_primitive_id |= shader->key.ge.mono.u.vs_export_prim_id;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,7 +136,6 @@ if with_llvm
|
|||
'si_shader_llvm_gs.c',
|
||||
'si_shader_llvm_ps.c',
|
||||
'si_shader_llvm_tess.c',
|
||||
'si_shader_llvm_vs.c',
|
||||
)
|
||||
|
||||
radeonsi_include_dirs += [inc_amd_common_llvm]
|
||||
|
|
|
|||
|
|
@ -37,15 +37,14 @@ fast_udiv_nuw(nir_builder *b, nir_def *num, nir_def *divisor)
|
|||
}
|
||||
|
||||
static nir_def *
|
||||
get_vertex_index_for_mono_shader(nir_builder *b, int input_index,
|
||||
struct lower_vs_inputs_state *s)
|
||||
get_vertex_index(nir_builder *b, int input_index, struct lower_vs_inputs_state *s)
|
||||
{
|
||||
const union si_shader_key *key = &s->shader->key;
|
||||
|
||||
bool divisor_is_one =
|
||||
key->ge.part.vs.prolog.instance_divisor_is_one & (1u << input_index);
|
||||
key->ge.mono.instance_divisor_is_one & (1u << input_index);
|
||||
bool divisor_is_fetched =
|
||||
key->ge.part.vs.prolog.instance_divisor_is_fetched & (1u << input_index);
|
||||
key->ge.mono.instance_divisor_is_fetched & (1u << input_index);
|
||||
|
||||
if (divisor_is_one || divisor_is_fetched) {
|
||||
nir_def *instance_id = nir_load_instance_id(b);
|
||||
|
|
@ -77,13 +76,6 @@ get_vertex_index_for_mono_shader(nir_builder *b, int input_index,
|
|||
}
|
||||
}
|
||||
|
||||
static nir_def *
|
||||
get_vertex_index_for_part_shader(nir_builder *b, int input_index,
|
||||
struct lower_vs_inputs_state *s)
|
||||
{
|
||||
return ac_nir_load_arg_at_offset(b, &s->args->ac, s->args->vertex_index0, input_index);
|
||||
}
|
||||
|
||||
static void
|
||||
get_vertex_index_for_all_inputs(nir_shader *nir, struct lower_vs_inputs_state *s)
|
||||
{
|
||||
|
|
@ -95,16 +87,13 @@ get_vertex_index_for_all_inputs(nir_shader *nir, struct lower_vs_inputs_state *s
|
|||
const struct si_shader_selector *sel = s->shader->selector;
|
||||
const union si_shader_key *key = &s->shader->key;
|
||||
|
||||
if (key->ge.part.vs.prolog.instance_divisor_is_fetched) {
|
||||
if (key->ge.mono.instance_divisor_is_fetched) {
|
||||
s->instance_divisor_constbuf =
|
||||
si_nir_load_internal_binding(b, s->args, SI_VS_CONST_INSTANCE_DIVISORS, 4);
|
||||
}
|
||||
|
||||
for (int i = 0; i < sel->info.num_inputs; i++) {
|
||||
s->vertex_index[i] = s->shader->is_monolithic ?
|
||||
get_vertex_index_for_mono_shader(b, i, s) :
|
||||
get_vertex_index_for_part_shader(b, i, s);
|
||||
}
|
||||
for (int i = 0; i < sel->info.num_inputs; i++)
|
||||
s->vertex_index[i] = get_vertex_index(b, i, s);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -787,16 +787,11 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen, unsign
|
|||
if (sctx->gfx_level >= GFX9) {
|
||||
/* The LS output / HS input layout can be communicated
|
||||
* directly instead of via user SGPRs for merged LS-HS.
|
||||
* This also enables jumping over the VS prolog for HS-only waves.
|
||||
*
|
||||
* When the LS VGPR fix is needed, monolithic shaders can:
|
||||
* - avoid initializing EXEC in both the LS prolog
|
||||
* and the LS main part when !vs_needs_prolog
|
||||
* - remove the fixup for unused input VGPRs
|
||||
* This also enables jumping over the VS for HS-only waves.
|
||||
*/
|
||||
sctx->shader.tcs.key.ge.opt.prefer_mono = 1;
|
||||
|
||||
/* This enables jumping over the VS prolog for GS-only waves. */
|
||||
/* This enables jumping over the VS for GS-only waves. */
|
||||
sctx->shader.gs.key.ge.opt.prefer_mono = 1;
|
||||
}
|
||||
|
||||
|
|
@ -962,8 +957,8 @@ static struct pipe_context *si_pipe_create_context(struct pipe_screen *screen, v
|
|||
static void si_destroy_screen(struct pipe_screen *pscreen)
|
||||
{
|
||||
struct si_screen *sscreen = (struct si_screen *)pscreen;
|
||||
struct si_shader_part *parts[] = {sscreen->vs_prologs, sscreen->tcs_epilogs,
|
||||
sscreen->ps_prologs, sscreen->ps_epilogs};
|
||||
struct si_shader_part *parts[] = {sscreen->tcs_epilogs, sscreen->ps_prologs,
|
||||
sscreen->ps_epilogs};
|
||||
unsigned i;
|
||||
|
||||
if (!sscreen->ws->unref(sscreen->ws))
|
||||
|
|
|
|||
|
|
@ -670,7 +670,6 @@ struct si_screen {
|
|||
} barrier_flags;
|
||||
|
||||
simple_mtx_t shader_parts_mutex;
|
||||
struct si_shader_part *vs_prologs;
|
||||
struct si_shader_part *tcs_epilogs;
|
||||
struct si_shader_part *ps_prologs;
|
||||
struct si_shader_part *ps_epilogs;
|
||||
|
|
|
|||
|
|
@ -251,8 +251,7 @@ static void declare_vb_descriptor_input_sgprs(struct si_shader_args *args,
|
|||
}
|
||||
}
|
||||
|
||||
static void declare_vs_input_vgprs(struct si_shader_args *args, struct si_shader *shader,
|
||||
unsigned *num_prolog_vgprs)
|
||||
static void declare_vs_input_vgprs(struct si_shader_args *args, struct si_shader *shader)
|
||||
{
|
||||
ac_add_arg(&args->ac, AC_ARG_VGPR, 1, AC_ARG_INT, &args->ac.vertex_id);
|
||||
if (shader->key.ge.as_ls) {
|
||||
|
|
@ -280,16 +279,6 @@ static void declare_vs_input_vgprs(struct si_shader_args *args, struct si_shader
|
|||
ac_add_arg(&args->ac, AC_ARG_VGPR, 1, AC_ARG_INT, &args->ac.vs_prim_id);
|
||||
ac_add_arg(&args->ac, AC_ARG_VGPR, 1, AC_ARG_INT, NULL); /* unused */
|
||||
}
|
||||
|
||||
if (!shader->is_gs_copy_shader) {
|
||||
/* Vertex load indices. */
|
||||
if (shader->selector->info.num_inputs) {
|
||||
ac_add_arg(&args->ac, AC_ARG_VGPR, 1, AC_ARG_INT, &args->vertex_index0);
|
||||
for (unsigned i = 1; i < shader->selector->info.num_inputs; i++)
|
||||
ac_add_arg(&args->ac, AC_ARG_VGPR, 1, AC_ARG_INT, NULL);
|
||||
}
|
||||
*num_prolog_vgprs += shader->selector->info.num_inputs;
|
||||
}
|
||||
}
|
||||
|
||||
static void declare_vs_blit_inputs(struct si_shader *shader, struct si_shader_args *args)
|
||||
|
|
@ -394,7 +383,7 @@ void si_init_shader_args(struct si_shader *shader, struct si_shader_args *args)
|
|||
ac_add_arg(&args->ac, AC_ARG_SGPR, 1, AC_ARG_INT, &args->ac.scratch_offset);
|
||||
|
||||
/* VGPRs */
|
||||
declare_vs_input_vgprs(args, shader, &num_prolog_vgprs);
|
||||
declare_vs_input_vgprs(args, shader);
|
||||
|
||||
break;
|
||||
|
||||
|
|
@ -459,7 +448,7 @@ void si_init_shader_args(struct si_shader *shader, struct si_shader_args *args)
|
|||
ac_add_arg(&args->ac, AC_ARG_VGPR, 1, AC_ARG_INT, &args->ac.tcs_rel_ids);
|
||||
|
||||
if (stage == MESA_SHADER_VERTEX) {
|
||||
declare_vs_input_vgprs(args, shader, &num_prolog_vgprs);
|
||||
declare_vs_input_vgprs(args, shader);
|
||||
|
||||
/* Need to keep LS/HS arg index same for shared args when ACO,
|
||||
* so this is not able to be before shared VGPRs.
|
||||
|
|
@ -567,7 +556,7 @@ void si_init_shader_args(struct si_shader *shader, struct si_shader_args *args)
|
|||
ac_add_arg(&args->ac, AC_ARG_VGPR, 1, AC_ARG_INT, &args->ac.gs_vtx_offset[2]);
|
||||
|
||||
if (stage == MESA_SHADER_VERTEX) {
|
||||
declare_vs_input_vgprs(args, shader, &num_prolog_vgprs);
|
||||
declare_vs_input_vgprs(args, shader);
|
||||
|
||||
/* Need to keep ES/GS arg index same for shared args when ACO,
|
||||
* so this is not able to be before shared VGPRs.
|
||||
|
|
@ -1443,15 +1432,11 @@ void si_shader_dump(struct si_screen *sscreen, struct si_shader *shader,
|
|||
}
|
||||
}
|
||||
|
||||
static void si_dump_shader_key_vs(const union si_shader_key *key,
|
||||
const struct si_vs_prolog_bits *prolog, const char *prefix,
|
||||
FILE *f)
|
||||
static void si_dump_shader_key_vs(const union si_shader_key *key, FILE *f)
|
||||
{
|
||||
fprintf(f, " %s.instance_divisor_is_one = %u\n", prefix, prolog->instance_divisor_is_one);
|
||||
fprintf(f, " %s.instance_divisor_is_fetched = %u\n", prefix,
|
||||
prolog->instance_divisor_is_fetched);
|
||||
fprintf(f, " %s.ls_vgpr_fix = %u\n", prefix, prolog->ls_vgpr_fix);
|
||||
|
||||
fprintf(f, " mono.instance_divisor_is_one = %u\n", key->ge.mono.instance_divisor_is_one);
|
||||
fprintf(f, " mono.instance_divisor_is_fetched = %u\n",
|
||||
key->ge.mono.instance_divisor_is_fetched);
|
||||
fprintf(f, " mono.vs.fetch_opencode = %x\n", key->ge.mono.vs_fetch_opencode);
|
||||
fprintf(f, " mono.vs.fix_fetch = {");
|
||||
for (int i = 0; i < SI_MAX_ATTRIBS; i++) {
|
||||
|
|
@ -1479,7 +1464,7 @@ static void si_dump_shader_key(const struct si_shader *shader, FILE *f)
|
|||
|
||||
switch (stage) {
|
||||
case MESA_SHADER_VERTEX:
|
||||
si_dump_shader_key_vs(key, &key->ge.part.vs.prolog, "part.vs.prolog", f);
|
||||
si_dump_shader_key_vs(key, f);
|
||||
fprintf(f, " as_es = %u\n", key->ge.as_es);
|
||||
fprintf(f, " as_ls = %u\n", key->ge.as_ls);
|
||||
fprintf(f, " as_ngg = %u\n", key->ge.as_ngg);
|
||||
|
|
@ -1487,9 +1472,9 @@ static void si_dump_shader_key(const struct si_shader *shader, FILE *f)
|
|||
break;
|
||||
|
||||
case MESA_SHADER_TESS_CTRL:
|
||||
if (shader->selector->screen->info.gfx_level >= GFX9) {
|
||||
si_dump_shader_key_vs(key, &key->ge.part.tcs.ls_prolog, "part.tcs.ls_prolog", f);
|
||||
}
|
||||
if (shader->selector->screen->info.gfx_level >= GFX9)
|
||||
si_dump_shader_key_vs(key, f);
|
||||
|
||||
fprintf(f, " part.tcs.epilog.prim_mode = %u\n", key->ge.part.tcs.epilog.prim_mode);
|
||||
fprintf(f, " opt.prefer_mono = %u\n", key->ge.opt.prefer_mono);
|
||||
fprintf(f, " opt.same_patch_vertices = %u\n", key->ge.opt.same_patch_vertices);
|
||||
|
|
@ -1506,9 +1491,9 @@ static void si_dump_shader_key(const struct si_shader *shader, FILE *f)
|
|||
break;
|
||||
|
||||
if (shader->selector->screen->info.gfx_level >= GFX9 &&
|
||||
key->ge.part.gs.es->stage == MESA_SHADER_VERTEX) {
|
||||
si_dump_shader_key_vs(key, &key->ge.part.gs.vs_prolog, "part.gs.vs_prolog", f);
|
||||
}
|
||||
key->ge.part.gs.es->stage == MESA_SHADER_VERTEX)
|
||||
si_dump_shader_key_vs(key, f);
|
||||
|
||||
fprintf(f, " mono.u.gs_tri_strip_adj_fix = %u\n", key->ge.mono.u.gs_tri_strip_adj_fix);
|
||||
fprintf(f, " as_ngg = %u\n", key->ge.as_ngg);
|
||||
break;
|
||||
|
|
@ -1600,62 +1585,6 @@ static void si_dump_shader_key(const struct si_shader *shader, FILE *f)
|
|||
}
|
||||
}
|
||||
|
||||
bool si_vs_needs_prolog(const struct si_shader_selector *sel,
|
||||
const struct si_vs_prolog_bits *prolog_key)
|
||||
{
|
||||
assert(sel->stage == MESA_SHADER_VERTEX);
|
||||
|
||||
/* VGPR initialization fixup for Vega10 and Raven is always done in the
|
||||
* VS prolog. */
|
||||
return sel->info.vs_needs_prolog || prolog_key->ls_vgpr_fix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the VS prolog key, which contains all the information needed to
|
||||
* build the VS prolog function, and set shader->info bits where needed.
|
||||
*
|
||||
* \param info Shader info of the vertex shader.
|
||||
* \param num_input_sgprs Number of input SGPRs for the vertex shader.
|
||||
* \param prolog_key Key of the VS prolog
|
||||
* \param shader_out The vertex shader, or the next shader if merging LS+HS or ES+GS.
|
||||
* \param key Output shader part key.
|
||||
*/
|
||||
void si_get_vs_prolog_key(const struct si_shader_info *info, unsigned num_input_sgprs,
|
||||
const struct si_vs_prolog_bits *prolog_key,
|
||||
struct si_shader *shader_out, union si_shader_part_key *key)
|
||||
{
|
||||
memset(key, 0, sizeof(*key));
|
||||
key->vs_prolog.states = *prolog_key;
|
||||
key->vs_prolog.wave32 = shader_out->wave_size == 32;
|
||||
key->vs_prolog.num_input_sgprs = num_input_sgprs;
|
||||
key->vs_prolog.num_inputs = info->num_inputs;
|
||||
key->vs_prolog.as_ls = shader_out->key.ge.as_ls;
|
||||
key->vs_prolog.as_es = shader_out->key.ge.as_es;
|
||||
key->vs_prolog.as_ngg = shader_out->key.ge.as_ngg;
|
||||
|
||||
if (shader_out->selector->stage == MESA_SHADER_TESS_CTRL) {
|
||||
key->vs_prolog.as_ls = 1;
|
||||
key->vs_prolog.num_merged_next_stage_vgprs = 2;
|
||||
} else if (shader_out->selector->stage == MESA_SHADER_GEOMETRY) {
|
||||
key->vs_prolog.as_es = 1;
|
||||
key->vs_prolog.num_merged_next_stage_vgprs = 5;
|
||||
} else if (shader_out->key.ge.as_ngg) {
|
||||
key->vs_prolog.num_merged_next_stage_vgprs = 5;
|
||||
}
|
||||
|
||||
/* Only one of these combinations can be set. as_ngg can be set with as_es. */
|
||||
assert(key->vs_prolog.as_ls + key->vs_prolog.as_ngg +
|
||||
(key->vs_prolog.as_es && !key->vs_prolog.as_ngg) <= 1);
|
||||
|
||||
/* Enable loading the InstanceID VGPR. */
|
||||
uint16_t input_mask = u_bit_consecutive(0, info->num_inputs);
|
||||
|
||||
if ((key->vs_prolog.states.instance_divisor_is_one |
|
||||
key->vs_prolog.states.instance_divisor_is_fetched) &
|
||||
input_mask)
|
||||
shader_out->info.uses_instanceid = true;
|
||||
}
|
||||
|
||||
/* TODO: convert to nir_shader_instructions_pass */
|
||||
static bool si_nir_kill_outputs(nir_shader *nir, const union si_shader_key *key)
|
||||
{
|
||||
|
|
@ -1951,9 +1880,8 @@ static void si_lower_ngg(struct si_shader *shader, nir_shader *nir)
|
|||
unsigned instance_rate_inputs = 0;
|
||||
|
||||
if (nir->info.stage == MESA_SHADER_VERTEX) {
|
||||
instance_rate_inputs =
|
||||
key->ge.part.vs.prolog.instance_divisor_is_one |
|
||||
key->ge.part.vs.prolog.instance_divisor_is_fetched;
|
||||
instance_rate_inputs = key->ge.mono.instance_divisor_is_one |
|
||||
key->ge.mono.instance_divisor_is_fetched;
|
||||
|
||||
/* Manually mark the instance ID used, so the shader can repack it. */
|
||||
if (instance_rate_inputs)
|
||||
|
|
@ -3125,35 +3053,6 @@ si_get_shader_part(struct si_screen *sscreen, struct si_shader_part **list,
|
|||
return result;
|
||||
}
|
||||
|
||||
static bool si_get_vs_prolog(struct si_screen *sscreen, struct ac_llvm_compiler *compiler,
|
||||
struct si_shader *shader, struct util_debug_callback *debug,
|
||||
struct si_shader *main_part, const struct si_vs_prolog_bits *key)
|
||||
{
|
||||
struct si_shader_selector *vs = main_part->selector;
|
||||
|
||||
if (!si_vs_needs_prolog(vs, key))
|
||||
return true;
|
||||
|
||||
/* Get the prolog. */
|
||||
union si_shader_part_key prolog_key;
|
||||
si_get_vs_prolog_key(&vs->info, main_part->info.num_input_sgprs, key, shader,
|
||||
&prolog_key);
|
||||
|
||||
shader->prolog =
|
||||
si_get_shader_part(sscreen, &sscreen->vs_prologs, MESA_SHADER_VERTEX, true, &prolog_key,
|
||||
compiler, debug, "Vertex Shader Prolog");
|
||||
return shader->prolog != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select and compile (or reuse) vertex shader parts (prolog & epilog).
|
||||
*/
|
||||
static bool si_shader_select_vs_parts(struct si_screen *sscreen, struct ac_llvm_compiler *compiler,
|
||||
struct si_shader *shader, struct util_debug_callback *debug)
|
||||
{
|
||||
return si_get_vs_prolog(sscreen, compiler, shader, debug, shader, &shader->key.ge.part.vs.prolog);
|
||||
}
|
||||
|
||||
void si_get_tcs_epilog_key(struct si_shader *shader, union si_shader_part_key *key)
|
||||
{
|
||||
memset(key, 0, sizeof(*key));
|
||||
|
|
@ -3171,15 +3070,8 @@ void si_get_tcs_epilog_key(struct si_shader *shader, union si_shader_part_key *k
|
|||
static bool si_shader_select_tcs_parts(struct si_screen *sscreen, struct ac_llvm_compiler *compiler,
|
||||
struct si_shader *shader, struct util_debug_callback *debug)
|
||||
{
|
||||
if (sscreen->info.gfx_level >= GFX9) {
|
||||
struct si_shader *ls_main_part = shader->key.ge.part.tcs.ls->main_shader_part_ls;
|
||||
|
||||
if (!si_get_vs_prolog(sscreen, compiler, shader, debug, ls_main_part,
|
||||
&shader->key.ge.part.tcs.ls_prolog))
|
||||
return false;
|
||||
|
||||
shader->previous_stage = ls_main_part;
|
||||
}
|
||||
if (sscreen->info.gfx_level >= GFX9)
|
||||
shader->previous_stage = shader->key.ge.part.tcs.ls->main_shader_part_ls;
|
||||
|
||||
/* Get the epilog. */
|
||||
union si_shader_part_key epilog_key;
|
||||
|
|
@ -3198,19 +3090,10 @@ static bool si_shader_select_gs_parts(struct si_screen *sscreen, struct ac_llvm_
|
|||
struct si_shader *shader, struct util_debug_callback *debug)
|
||||
{
|
||||
if (sscreen->info.gfx_level >= GFX9) {
|
||||
struct si_shader *es_main_part;
|
||||
|
||||
if (shader->key.ge.as_ngg)
|
||||
es_main_part = shader->key.ge.part.gs.es->main_shader_part_ngg_es;
|
||||
shader->previous_stage = shader->key.ge.part.gs.es->main_shader_part_ngg_es;
|
||||
else
|
||||
es_main_part = shader->key.ge.part.gs.es->main_shader_part_es;
|
||||
|
||||
if (shader->key.ge.part.gs.es->stage == MESA_SHADER_VERTEX &&
|
||||
!si_get_vs_prolog(sscreen, compiler, shader, debug, es_main_part,
|
||||
&shader->key.ge.part.gs.vs_prolog))
|
||||
return false;
|
||||
|
||||
shader->previous_stage = es_main_part;
|
||||
shader->previous_stage = shader->key.ge.part.gs.es->main_shader_part_es;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -3479,16 +3362,10 @@ bool si_create_shader_variant(struct si_screen *sscreen, struct ac_llvm_compiler
|
|||
|
||||
/* Select prologs and/or epilogs. */
|
||||
switch (sel->stage) {
|
||||
case MESA_SHADER_VERTEX:
|
||||
if (!si_shader_select_vs_parts(sscreen, compiler, shader, debug))
|
||||
return false;
|
||||
break;
|
||||
case MESA_SHADER_TESS_CTRL:
|
||||
if (!si_shader_select_tcs_parts(sscreen, compiler, shader, debug))
|
||||
return false;
|
||||
break;
|
||||
case MESA_SHADER_TESS_EVAL:
|
||||
break;
|
||||
case MESA_SHADER_GEOMETRY:
|
||||
if (!si_shader_select_gs_parts(sscreen, compiler, shader, debug))
|
||||
return false;
|
||||
|
|
@ -3593,18 +3470,18 @@ bool si_create_shader_variant(struct si_screen *sscreen, struct ac_llvm_compiler
|
|||
|
||||
if (sel->stage == MESA_SHADER_VERTEX) {
|
||||
shader->uses_base_instance = sel->info.uses_base_instance ||
|
||||
shader->key.ge.part.vs.prolog.instance_divisor_is_one ||
|
||||
shader->key.ge.part.vs.prolog.instance_divisor_is_fetched;
|
||||
shader->key.ge.mono.instance_divisor_is_one ||
|
||||
shader->key.ge.mono.instance_divisor_is_fetched;
|
||||
} else if (sel->stage == MESA_SHADER_TESS_CTRL) {
|
||||
shader->uses_base_instance = shader->previous_stage_sel &&
|
||||
(shader->previous_stage_sel->info.uses_base_instance ||
|
||||
shader->key.ge.part.tcs.ls_prolog.instance_divisor_is_one ||
|
||||
shader->key.ge.part.tcs.ls_prolog.instance_divisor_is_fetched);
|
||||
shader->key.ge.mono.instance_divisor_is_one ||
|
||||
shader->key.ge.mono.instance_divisor_is_fetched);
|
||||
} else if (sel->stage == MESA_SHADER_GEOMETRY) {
|
||||
shader->uses_base_instance = shader->previous_stage_sel &&
|
||||
(shader->previous_stage_sel->info.uses_base_instance ||
|
||||
shader->key.ge.part.gs.vs_prolog.instance_divisor_is_one ||
|
||||
shader->key.ge.part.gs.vs_prolog.instance_divisor_is_fetched);
|
||||
shader->key.ge.mono.instance_divisor_is_one ||
|
||||
shader->key.ge.mono.instance_divisor_is_fetched);
|
||||
}
|
||||
|
||||
si_fix_resource_usage(sscreen, shader);
|
||||
|
|
@ -3659,13 +3536,11 @@ nir_shader *si_get_prev_stage_nir_shader(struct si_shader *shader,
|
|||
struct si_shader_selector *ls = key->ge.part.tcs.ls;
|
||||
|
||||
prev_shader->selector = ls;
|
||||
prev_shader->key.ge.part.vs.prolog = key->ge.part.tcs.ls_prolog;
|
||||
prev_shader->key.ge.as_ls = 1;
|
||||
} else {
|
||||
struct si_shader_selector *es = key->ge.part.gs.es;
|
||||
|
||||
prev_shader->selector = es;
|
||||
prev_shader->key.ge.part.vs.prolog = key->ge.part.gs.vs_prolog;
|
||||
prev_shader->key.ge.as_es = 1;
|
||||
prev_shader->key.ge.as_ngg = key->ge.as_ngg;
|
||||
}
|
||||
|
|
@ -3754,50 +3629,6 @@ void si_get_tcs_epilog_args(enum amd_gfx_level gfx_level,
|
|||
ac_add_arg(&args->ac, AC_ARG_VGPR, 1, AC_ARG_INT, &tess_factors[i]);
|
||||
}
|
||||
|
||||
void si_get_vs_prolog_args(enum amd_gfx_level gfx_level,
|
||||
struct si_shader_args *args,
|
||||
const union si_shader_part_key *key)
|
||||
{
|
||||
memset(args, 0, sizeof(*args));
|
||||
|
||||
unsigned num_input_sgprs = key->vs_prolog.num_input_sgprs;
|
||||
unsigned num_input_vgprs = key->vs_prolog.num_merged_next_stage_vgprs + 4;
|
||||
|
||||
struct ac_arg input_sgprs[num_input_sgprs];
|
||||
for (unsigned i = 0; i < num_input_sgprs; i++)
|
||||
ac_add_arg(&args->ac, AC_ARG_SGPR, 1, AC_ARG_INT, input_sgprs + i);
|
||||
|
||||
struct ac_arg input_vgprs[num_input_vgprs];
|
||||
for (unsigned i = 0; i < num_input_vgprs; i++)
|
||||
ac_add_arg(&args->ac, AC_ARG_VGPR, 1, AC_ARG_INT, input_vgprs + i);
|
||||
|
||||
if (key->vs_prolog.num_merged_next_stage_vgprs)
|
||||
args->ac.merged_wave_info = input_sgprs[3];
|
||||
|
||||
unsigned first_vs_vgpr = key->vs_prolog.num_merged_next_stage_vgprs;
|
||||
unsigned vertex_id_vgpr = first_vs_vgpr;
|
||||
unsigned instance_id_vgpr = gfx_level >= GFX10 ?
|
||||
first_vs_vgpr + 3 : first_vs_vgpr + (key->vs_prolog.as_ls ? 2 : 1);
|
||||
|
||||
args->ac.vertex_id = input_vgprs[vertex_id_vgpr];
|
||||
args->ac.instance_id = input_vgprs[instance_id_vgpr];
|
||||
|
||||
if (key->vs_prolog.as_ls) {
|
||||
if (gfx_level < GFX11)
|
||||
args->ac.vs_rel_patch_id = input_vgprs[first_vs_vgpr + 1];
|
||||
|
||||
if (gfx_level >= GFX9) {
|
||||
args->ac.tcs_patch_id = input_vgprs[0];
|
||||
args->ac.tcs_rel_ids = input_vgprs[1];
|
||||
}
|
||||
}
|
||||
|
||||
unsigned user_sgpr_base = key->vs_prolog.num_merged_next_stage_vgprs ? 8 : 0;
|
||||
args->internal_bindings = input_sgprs[user_sgpr_base + SI_SGPR_INTERNAL_BINDINGS];
|
||||
args->ac.start_instance = input_sgprs[user_sgpr_base + SI_SGPR_START_INSTANCE];
|
||||
args->ac.base_vertex = input_sgprs[user_sgpr_base + SI_SGPR_BASE_VERTEX];
|
||||
}
|
||||
|
||||
void si_get_ps_prolog_args(struct si_shader_args *args,
|
||||
const union si_shader_part_key *key)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -66,7 +66,6 @@
|
|||
* shader parts per shader increased. The complete new list of shader parts is:
|
||||
* - 1st shader: prolog part
|
||||
* - 1st shader: main part
|
||||
* - 2nd shader: prolog part
|
||||
* - 2nd shader: main part
|
||||
* - 2nd shader: epilog part
|
||||
*/
|
||||
|
|
@ -482,7 +481,6 @@ struct si_shader_info {
|
|||
uint8_t colors_read; /**< which color components are read by the FS */
|
||||
uint8_t colors_written;
|
||||
uint16_t output_color_types; /**< Each bit pair is enum si_color_output_type */
|
||||
bool vs_needs_prolog;
|
||||
bool color0_writes_all_cbufs; /**< gl_FragColor */
|
||||
bool reads_samplemask; /**< does fragment shader read sample mask? */
|
||||
bool reads_tess_factors; /**< If TES reads TESSINNER or TESSOUTER */
|
||||
|
|
@ -626,19 +624,6 @@ struct si_shader_selector {
|
|||
*/
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/* Common VS bits between the shader key and the prolog key. */
|
||||
struct si_vs_prolog_bits {
|
||||
/* - If neither "is_one" nor "is_fetched" has a bit set, the instance
|
||||
* divisor is 0.
|
||||
* - If "is_one" has a bit set, the instance divisor is 1.
|
||||
* - If "is_fetched" has a bit set, the instance divisor will be loaded
|
||||
* from the constant buffer.
|
||||
*/
|
||||
uint16_t instance_divisor_is_one; /* bitmask of inputs */
|
||||
uint16_t instance_divisor_is_fetched; /* bitmask of inputs */
|
||||
unsigned ls_vgpr_fix : 1;
|
||||
};
|
||||
|
||||
/* Common TCS bits between the shader key and the epilog key. */
|
||||
struct si_tcs_epilog_bits {
|
||||
unsigned prim_mode : 3;
|
||||
|
|
@ -676,17 +661,6 @@ struct si_ps_epilog_bits {
|
|||
};
|
||||
|
||||
union si_shader_part_key {
|
||||
struct {
|
||||
struct si_vs_prolog_bits states;
|
||||
unsigned wave32 : 1;
|
||||
unsigned num_input_sgprs : 6;
|
||||
/* For merged stages such as LS-HS, HS input VGPRs are first. */
|
||||
unsigned num_merged_next_stage_vgprs : 3;
|
||||
unsigned num_inputs : 5;
|
||||
unsigned as_ls : 1;
|
||||
unsigned as_es : 1;
|
||||
unsigned as_ngg : 1;
|
||||
} vs_prolog;
|
||||
struct {
|
||||
struct si_tcs_epilog_bits states;
|
||||
unsigned wave32 : 1;
|
||||
|
|
@ -721,15 +695,10 @@ struct si_shader_key_ge {
|
|||
/* Prolog and epilog flags. */
|
||||
union {
|
||||
struct {
|
||||
struct si_vs_prolog_bits prolog;
|
||||
} vs;
|
||||
struct {
|
||||
struct si_vs_prolog_bits ls_prolog; /* for merged LS-HS */
|
||||
struct si_shader_selector *ls; /* for merged LS-HS */
|
||||
struct si_tcs_epilog_bits epilog;
|
||||
} tcs; /* tessellation control shader */
|
||||
struct {
|
||||
struct si_vs_prolog_bits vs_prolog; /* for merged ES-GS */
|
||||
struct si_shader_selector *es; /* for merged ES-GS */
|
||||
} gs;
|
||||
} part;
|
||||
|
|
@ -744,6 +713,15 @@ struct si_shader_key_ge {
|
|||
|
||||
/* Flags for monolithic compilation only. */
|
||||
struct {
|
||||
/* - If neither "is_one" nor "is_fetched" has a bit set, the instance
|
||||
* divisor is 0.
|
||||
* - If "is_one" has a bit set, the instance divisor is 1.
|
||||
* - If "is_fetched" has a bit set, the instance divisor will be loaded
|
||||
* from the constant buffer.
|
||||
*/
|
||||
uint16_t instance_divisor_is_one; /* bitmask of inputs */
|
||||
uint16_t instance_divisor_is_fetched; /* bitmask of inputs */
|
||||
|
||||
/* Whether fetch should be opencoded according to vs_fix_fetch.
|
||||
* Otherwise, if vs_fix_fetch is non-zero, buffer_load_format_xyzw
|
||||
* with minimal fixups is used. */
|
||||
|
|
|
|||
|
|
@ -85,16 +85,6 @@ si_fill_aco_shader_info(struct si_shader *shader, struct aco_shader_info *info,
|
|||
}
|
||||
|
||||
switch (stage) {
|
||||
case MESA_SHADER_VERTEX:
|
||||
/* Only part mode VS may have prolog, mono mode VS will embed prolog in nir.
|
||||
* But we don't know exactly if part mode VS needs prolog because it also depends
|
||||
* on shader select key ls_vgpr_fix which is not known when VS main part compile.
|
||||
* Now just assume ls_vgpr_fix is always false, which just cause ACO to add extra
|
||||
* s_setprio and exec init code when it's finally combined with prolog.
|
||||
*/
|
||||
if (!shader->is_gs_copy_shader && !shader->is_monolithic)
|
||||
info->vs.has_prolog = si_vs_needs_prolog(sel, &key->ge.part.vs.prolog);
|
||||
break;
|
||||
case MESA_SHADER_TESS_CTRL:
|
||||
info->vs.tcs_in_out_eq = key->ge.opt.same_patch_vertices;
|
||||
info->vs.tcs_temp_only_input_mask = sel->info.tcs_vgpr_only_inputs;
|
||||
|
|
@ -315,43 +305,6 @@ si_aco_build_tcs_epilog(struct si_screen *screen,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
si_aco_build_vs_prolog(struct si_screen *screen,
|
||||
struct aco_compiler_options *options,
|
||||
struct si_shader_part *result)
|
||||
{
|
||||
const union si_shader_part_key *key = &result->key;
|
||||
|
||||
struct si_shader_args args;
|
||||
si_get_vs_prolog_args(screen->info.gfx_level, &args, key);
|
||||
|
||||
struct aco_gl_vs_prolog_info pinfo = {
|
||||
.instance_divisor_is_one = key->vs_prolog.states.instance_divisor_is_one,
|
||||
.instance_divisor_is_fetched = key->vs_prolog.states.instance_divisor_is_fetched,
|
||||
.instance_diviser_buf_offset = SI_VS_CONST_INSTANCE_DIVISORS * 16,
|
||||
.num_inputs = key->vs_prolog.num_inputs,
|
||||
.as_ls = key->vs_prolog.as_ls,
|
||||
|
||||
.internal_bindings = args.internal_bindings,
|
||||
};
|
||||
|
||||
struct aco_shader_info info = {0};
|
||||
info.workgroup_size = info.wave_size = key->vs_prolog.wave32 ? 32 : 64;
|
||||
|
||||
if (key->vs_prolog.as_ngg)
|
||||
info.hw_stage = AC_HW_NEXT_GEN_GEOMETRY_SHADER;
|
||||
else if (key->vs_prolog.as_es)
|
||||
info.hw_stage = options->gfx_level >= GFX9 ? AC_HW_LEGACY_GEOMETRY_SHADER : AC_HW_EXPORT_SHADER;
|
||||
else if (key->vs_prolog.as_ls)
|
||||
info.hw_stage = options->gfx_level >= GFX9 ? AC_HW_HULL_SHADER : AC_HW_LOCAL_SHADER;
|
||||
else
|
||||
info.hw_stage = AC_HW_VERTEX_SHADER;
|
||||
|
||||
aco_compile_gl_vs_prolog(options, &info, &pinfo, &args.ac,
|
||||
si_aco_build_shader_part_binary, (void **)result);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
si_aco_build_ps_prolog(struct aco_compiler_options *options,
|
||||
struct si_shader_part *result)
|
||||
|
|
@ -437,8 +390,6 @@ si_aco_build_shader_part(struct si_screen *screen, gl_shader_stage stage, bool p
|
|||
si_fill_aco_options(screen, stage, &options, debug);
|
||||
|
||||
switch (stage) {
|
||||
case MESA_SHADER_VERTEX:
|
||||
return si_aco_build_vs_prolog(screen, &options, result);
|
||||
case MESA_SHADER_TESS_CTRL:
|
||||
return si_aco_build_tcs_epilog(screen, &options, result);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -794,9 +794,6 @@ void si_nir_scan_shader(struct si_screen *sscreen, const struct nir_shader *nir,
|
|||
nir->info.stage == MESA_SHADER_VERTEX && !info->base.vs.blit_sgprs_amd ? info->num_inputs : 0;
|
||||
unsigned num_vbos_in_sgprs = si_num_vbos_in_user_sgprs_inline(sscreen->info.gfx_level);
|
||||
info->num_vbos_in_user_sgprs = MIN2(info->num_vs_inputs, num_vbos_in_sgprs);
|
||||
|
||||
/* The prolog is a no-op if there are no inputs. */
|
||||
info->vs_needs_prolog = info->num_inputs && !info->base.vs.blit_sgprs_amd;
|
||||
}
|
||||
|
||||
if (nir->info.stage == MESA_SHADER_VERTEX ||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ struct si_shader_args {
|
|||
struct ac_arg gs_attr_address;
|
||||
/* API VS */
|
||||
struct ac_arg vb_descriptors[5];
|
||||
struct ac_arg vertex_index0;
|
||||
/* VS state bits. See the VS_STATE_* and GS_STATE_* definitions. */
|
||||
struct ac_arg vs_state_bits;
|
||||
struct ac_arg vs_blit_inputs;
|
||||
|
|
@ -94,11 +93,6 @@ void si_add_arg_checked(struct ac_shader_args *args, enum ac_arg_regfile file, u
|
|||
enum ac_arg_type type, struct ac_arg *arg, unsigned idx);
|
||||
void si_init_shader_args(struct si_shader *shader, struct si_shader_args *args);
|
||||
unsigned si_get_max_workgroup_size(const struct si_shader *shader);
|
||||
bool si_vs_needs_prolog(const struct si_shader_selector *sel,
|
||||
const struct si_vs_prolog_bits *prolog_key);
|
||||
void si_get_vs_prolog_key(const struct si_shader_info *info, unsigned num_input_sgprs,
|
||||
const struct si_vs_prolog_bits *prolog_key,
|
||||
struct si_shader *shader_out, union si_shader_part_key *key);
|
||||
struct nir_shader *si_get_nir_shader(struct si_shader *shader, struct si_shader_args *args,
|
||||
bool *free_nir, uint64_t tcs_vgpr_only_inputs,
|
||||
ac_nir_gs_output_info *output_info);
|
||||
|
|
@ -119,9 +113,6 @@ void si_get_tcs_epilog_args(enum amd_gfx_level gfx_level,
|
|||
struct ac_arg *invocation_id,
|
||||
struct ac_arg *tf_lds_offset,
|
||||
struct ac_arg tess_factors[6]);
|
||||
void si_get_vs_prolog_args(enum amd_gfx_level gfx_level,
|
||||
struct si_shader_args *args,
|
||||
const union si_shader_part_key *key);
|
||||
void si_get_ps_prolog_args(struct si_shader_args *args,
|
||||
const union si_shader_part_key *key);
|
||||
void si_get_ps_epilog_args(struct si_shader_args *args,
|
||||
|
|
|
|||
|
|
@ -223,10 +223,8 @@ void si_llvm_create_main_func(struct si_shader_context *ctx)
|
|||
if (ctx->args->ac.vs_rel_patch_id.used)
|
||||
ctx->abi.vs_rel_patch_id = ac_get_arg(&ctx->ac, ctx->args->ac.vs_rel_patch_id);
|
||||
|
||||
/* Non-monolithic shaders apply the LS-HS input VGPR hw bug workaround in
|
||||
* the VS prolog, while monolithic shaders apply it here.
|
||||
*/
|
||||
if (shader->is_monolithic && shader->key.ge.part.vs.prolog.ls_vgpr_fix)
|
||||
/* Apply the LS-HS input VGPR hw bug workaround. */
|
||||
if (shader->key.ge.as_ls && ctx->screen->info.has_ls_vgpr_init_bug)
|
||||
ac_fixup_ls_hs_input_vgprs(&ctx->ac, &ctx->abi, &ctx->args->ac);
|
||||
}
|
||||
}
|
||||
|
|
@ -655,9 +653,7 @@ static bool si_llvm_translate_nir(struct si_shader_context *ctx, struct si_shade
|
|||
if (!shader->key.ge.as_ls && !shader->key.ge.as_es)
|
||||
ac_init_exec_full_mask(&ctx->ac);
|
||||
} else {
|
||||
/* If the prolog is present, EXEC is set there instead. */
|
||||
if (!si_vs_needs_prolog(sel, &shader->key.ge.part.vs.prolog))
|
||||
ac_init_exec_full_mask(&ctx->ac);
|
||||
ac_init_exec_full_mask(&ctx->ac);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -904,12 +900,6 @@ bool si_llvm_build_shader_part(struct si_screen *sscreen, gl_shader_stage stage,
|
|||
bool exports_mrtz = false;
|
||||
|
||||
switch (stage) {
|
||||
case MESA_SHADER_VERTEX:
|
||||
shader.key.ge.as_ls = key->vs_prolog.as_ls;
|
||||
shader.key.ge.as_es = key->vs_prolog.as_es;
|
||||
shader.key.ge.as_ngg = key->vs_prolog.as_ngg;
|
||||
wave32 = key->vs_prolog.wave32;
|
||||
break;
|
||||
case MESA_SHADER_TESS_CTRL:
|
||||
assert(!prolog);
|
||||
shader.key.ge.part.tcs.epilog = key->tcs_epilog.states;
|
||||
|
|
@ -947,9 +937,6 @@ bool si_llvm_build_shader_part(struct si_screen *sscreen, gl_shader_stage stage,
|
|||
void (*build)(struct si_shader_context *, union si_shader_part_key *);
|
||||
|
||||
switch (stage) {
|
||||
case MESA_SHADER_VERTEX:
|
||||
build = si_llvm_build_vs_prolog;
|
||||
break;
|
||||
case MESA_SHADER_TESS_CTRL:
|
||||
build = si_llvm_build_tcs_epilog;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -92,7 +92,4 @@ void si_llvm_build_ps_prolog(struct si_shader_context *ctx, union si_shader_part
|
|||
void si_llvm_build_ps_epilog(struct si_shader_context *ctx, union si_shader_part_key *key);
|
||||
void si_llvm_ps_build_end(struct si_shader_context *ctx);
|
||||
|
||||
/* si_shader_llvm_vs.c */
|
||||
void si_llvm_build_vs_prolog(struct si_shader_context *ctx, union si_shader_part_key *key);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,158 +0,0 @@
|
|||
/*
|
||||
* Copyright 2020 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "si_pipe.h"
|
||||
#include "si_shader_internal.h"
|
||||
#include "si_shader_llvm.h"
|
||||
#include "sid.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "ac_nir.h"
|
||||
|
||||
static LLVMValueRef get_vertex_index(struct si_shader_context *ctx,
|
||||
struct si_vs_prolog_bits *key, unsigned input_index,
|
||||
LLVMValueRef instance_divisor_constbuf)
|
||||
{
|
||||
LLVMValueRef instance_id = ctx->abi.instance_id;
|
||||
LLVMValueRef vertex_id = ctx->abi.vertex_id;
|
||||
|
||||
bool divisor_is_one = key->instance_divisor_is_one & (1u << input_index);
|
||||
bool divisor_is_fetched =key->instance_divisor_is_fetched & (1u << input_index);
|
||||
|
||||
LLVMValueRef index = NULL;
|
||||
if (divisor_is_one)
|
||||
index = instance_id;
|
||||
else if (divisor_is_fetched) {
|
||||
LLVMValueRef udiv_factors[4];
|
||||
|
||||
for (unsigned j = 0; j < 4; j++) {
|
||||
udiv_factors[j] = si_buffer_load_const(
|
||||
ctx, instance_divisor_constbuf,
|
||||
LLVMConstInt(ctx->ac.i32, input_index * 16 + j * 4, 0));
|
||||
udiv_factors[j] = ac_to_integer(&ctx->ac, udiv_factors[j]);
|
||||
}
|
||||
|
||||
/* The faster NUW version doesn't work when InstanceID == UINT_MAX.
|
||||
* Such InstanceID might not be achievable in a reasonable time though.
|
||||
*/
|
||||
index = ac_build_fast_udiv_nuw(
|
||||
&ctx->ac, instance_id, udiv_factors[0],
|
||||
udiv_factors[1], udiv_factors[2], udiv_factors[3]);
|
||||
}
|
||||
|
||||
if (divisor_is_one || divisor_is_fetched) {
|
||||
/* Add StartInstance. */
|
||||
LLVMValueRef start_instance = ac_get_arg(&ctx->ac, ctx->args->ac.start_instance);
|
||||
index = LLVMBuildAdd(ctx->ac.builder, index, start_instance, "");
|
||||
} else {
|
||||
/* VertexID + BaseVertex */
|
||||
LLVMValueRef base_vertex = ac_get_arg(&ctx->ac, ctx->args->ac.base_vertex);
|
||||
index = LLVMBuildAdd(ctx->ac.builder, vertex_id, base_vertex, "");
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the vertex shader prolog function.
|
||||
*
|
||||
* The inputs are the same as VS (a lot of SGPRs and 4 VGPR system values).
|
||||
* All inputs are returned unmodified. The vertex load indices are
|
||||
* stored after them, which will be used by the API VS for fetching inputs.
|
||||
*
|
||||
* For example, the expected outputs for instance_divisors[] = {0, 1, 2} are:
|
||||
* input_v0,
|
||||
* input_v1,
|
||||
* input_v2,
|
||||
* input_v3,
|
||||
* (VertexID + BaseVertex),
|
||||
* (InstanceID + StartInstance),
|
||||
* (InstanceID / 2 + StartInstance)
|
||||
*/
|
||||
void si_llvm_build_vs_prolog(struct si_shader_context *ctx, union si_shader_part_key *key)
|
||||
{
|
||||
struct si_shader_args *args = ctx->args;
|
||||
si_get_vs_prolog_args(ctx->screen->info.gfx_level, args, key);
|
||||
|
||||
const unsigned num_input_sgprs = args->ac.num_sgprs_used;
|
||||
const unsigned num_input_vgprs = args->ac.num_vgprs_used;
|
||||
|
||||
/* 4 preloaded VGPRs + vertex load indices as prolog outputs */
|
||||
const unsigned num_output_gprs =
|
||||
num_input_sgprs + num_input_vgprs + key->vs_prolog.num_inputs;
|
||||
LLVMTypeRef returns[num_output_gprs];
|
||||
int num_returns = 0;
|
||||
|
||||
/* Output SGPRs. */
|
||||
for (int i = 0; i < num_input_sgprs; i++)
|
||||
returns[num_returns++] = ctx->ac.i32;
|
||||
|
||||
/* Output VGPRs */
|
||||
for (int i = 0; i < num_input_vgprs; i++)
|
||||
returns[num_returns++] = ctx->ac.f32;
|
||||
|
||||
/* Vertex load indices. */
|
||||
for (int i = 0; i < key->vs_prolog.num_inputs; i++)
|
||||
returns[num_returns++] = ctx->ac.f32;
|
||||
|
||||
/* Create the function. */
|
||||
si_llvm_create_func(ctx, "vs_prolog", returns, num_returns, 0);
|
||||
LLVMValueRef func = ctx->main_fn.value;
|
||||
|
||||
LLVMValueRef input_vgprs[num_input_vgprs];
|
||||
for (int i = 0; i < num_input_vgprs; i++)
|
||||
input_vgprs[i] = LLVMGetParam(func, num_input_sgprs + i);
|
||||
|
||||
if (key->vs_prolog.num_merged_next_stage_vgprs) {
|
||||
ac_init_exec_full_mask(&ctx->ac);
|
||||
|
||||
if (key->vs_prolog.as_ls && ctx->screen->info.has_ls_vgpr_init_bug) {
|
||||
/* If there are no HS threads, SPI loads the LS VGPRs
|
||||
* starting at VGPR 0. Shift them back to where they
|
||||
* belong.
|
||||
*/
|
||||
LLVMValueRef hs_thread_count =
|
||||
si_unpack_param(ctx, args->ac.merged_wave_info, 8, 8);
|
||||
LLVMValueRef has_hs_threads =
|
||||
LLVMBuildICmp(ctx->ac.builder, LLVMIntNE, hs_thread_count, ctx->ac.i32_0, "");
|
||||
|
||||
for (int i = 4; i > 0; --i) {
|
||||
input_vgprs[i + 1] = LLVMBuildSelect(ctx->ac.builder, has_hs_threads,
|
||||
input_vgprs[i + 1], input_vgprs[i - 1], "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->abi.vertex_id = input_vgprs[args->ac.vertex_id.arg_index - num_input_sgprs];
|
||||
ctx->abi.instance_id = input_vgprs[args->ac.instance_id.arg_index - num_input_sgprs];
|
||||
|
||||
/* Copy inputs to outputs. This should be no-op, as the registers match,
|
||||
* but it will prevent the compiler from overwriting them unintentionally.
|
||||
*/
|
||||
LLVMValueRef ret = ctx->return_value;
|
||||
for (int i = 0; i < num_input_sgprs; i++) {
|
||||
LLVMValueRef p = LLVMGetParam(func, i);
|
||||
ret = LLVMBuildInsertValue(ctx->ac.builder, ret, p, i, "");
|
||||
}
|
||||
for (int i = 0; i < num_input_vgprs; i++) {
|
||||
LLVMValueRef p = ac_to_float(&ctx->ac, input_vgprs[i]);
|
||||
ret = LLVMBuildInsertValue(ctx->ac.builder, ret, p, num_input_sgprs + i, "");
|
||||
}
|
||||
|
||||
/* Compute vertex load indices from instance divisors. */
|
||||
LLVMValueRef instance_divisor_constbuf =
|
||||
key->vs_prolog.states.instance_divisor_is_fetched ?
|
||||
si_prolog_get_internal_binding_slot(ctx, SI_VS_CONST_INSTANCE_DIVISORS) : NULL;
|
||||
|
||||
for (int i = 0; i < key->vs_prolog.num_inputs; i++) {
|
||||
LLVMValueRef index = get_vertex_index(ctx, &key->vs_prolog.states, i,
|
||||
instance_divisor_constbuf);
|
||||
|
||||
index = ac_to_float(&ctx->ac, index);
|
||||
ret = LLVMBuildInsertValue(ctx->ac.builder, ret, index, args->ac.arg_count + i, "");
|
||||
}
|
||||
|
||||
si_llvm_build_ret(ctx, ret);
|
||||
}
|
||||
|
|
@ -657,8 +657,6 @@ void si_get_active_slot_masks(struct si_screen *sscreen, const struct si_shader_
|
|||
uint64_t *const_and_shader_buffers, uint64_t *samplers_and_images);
|
||||
int si_shader_select(struct pipe_context *ctx, struct si_shader_ctx_state *state);
|
||||
void si_vs_key_update_inputs(struct si_context *sctx);
|
||||
void si_get_vs_key_inputs(struct si_context *sctx, union si_shader_key *key,
|
||||
struct si_vs_prolog_bits *prolog_key);
|
||||
void si_update_ps_inputs_read_or_disabled(struct si_context *sctx);
|
||||
void si_update_vrs_flat_shading(struct si_context *sctx);
|
||||
unsigned si_get_input_prim(const struct si_shader_selector *gs, const union si_shader_key *key);
|
||||
|
|
|
|||
|
|
@ -2131,13 +2131,12 @@ static void si_draw(struct pipe_context *ctx,
|
|||
|
||||
if (IS_DRAW_VERTEX_STATE) {
|
||||
/* draw_vertex_state doesn't use the current vertex buffers and vertex elements,
|
||||
* so disable any non-trivial VS prolog that is based on them, such as vertex
|
||||
* format lowering.
|
||||
* so disable all VS input lowering.
|
||||
*/
|
||||
if (!sctx->force_trivial_vs_inputs) {
|
||||
sctx->force_trivial_vs_inputs = true;
|
||||
|
||||
/* Update shaders to disable the non-trivial VS prolog. */
|
||||
/* Update shaders to disable VS input lowering. */
|
||||
if (sctx->uses_nontrivial_vs_inputs) {
|
||||
si_vs_key_update_inputs(sctx);
|
||||
sctx->do_update_shaders = true;
|
||||
|
|
@ -2147,7 +2146,7 @@ static void si_draw(struct pipe_context *ctx,
|
|||
if (sctx->force_trivial_vs_inputs) {
|
||||
sctx->force_trivial_vs_inputs = false;
|
||||
|
||||
/* Update shaders to enable the non-trivial VS prolog. */
|
||||
/* Update shaders to possibly enable VS input lowering. */
|
||||
if (sctx->uses_nontrivial_vs_inputs) {
|
||||
si_vs_key_update_inputs(sctx);
|
||||
sctx->do_update_shaders = true;
|
||||
|
|
|
|||
|
|
@ -2110,11 +2110,10 @@ static void si_shader_init_pm4_state(struct si_screen *sscreen, struct si_shader
|
|||
assert(!(sscreen->debug_flags & DBG(SQTT)) || shader->pm4.spi_shader_pgm_lo_reg != 0);
|
||||
}
|
||||
|
||||
static void si_clear_vs_key_inputs(struct si_context *sctx, union si_shader_key *key,
|
||||
struct si_vs_prolog_bits *prolog_key)
|
||||
static void si_clear_vs_key_inputs(union si_shader_key *key)
|
||||
{
|
||||
prolog_key->instance_divisor_is_one = 0;
|
||||
prolog_key->instance_divisor_is_fetched = 0;
|
||||
key->ge.mono.instance_divisor_is_one = 0;
|
||||
key->ge.mono.instance_divisor_is_fetched = 0;
|
||||
key->ge.mono.vs_fetch_opencode = 0;
|
||||
memset(key->ge.mono.vs_fix_fetch, 0, sizeof(key->ge.mono.vs_fix_fetch));
|
||||
}
|
||||
|
|
@ -2129,7 +2128,7 @@ void si_vs_key_update_inputs(struct si_context *sctx)
|
|||
return;
|
||||
|
||||
if (vs->info.base.vs.blit_sgprs_amd) {
|
||||
si_clear_vs_key_inputs(sctx, key, &key->ge.part.vs.prolog);
|
||||
si_clear_vs_key_inputs(key);
|
||||
key->ge.opt.prefer_mono = 0;
|
||||
sctx->uses_nontrivial_vs_inputs = false;
|
||||
return;
|
||||
|
|
@ -2140,8 +2139,8 @@ void si_vs_key_update_inputs(struct si_context *sctx)
|
|||
if (elts->instance_divisor_is_one || elts->instance_divisor_is_fetched)
|
||||
uses_nontrivial_vs_inputs = true;
|
||||
|
||||
key->ge.part.vs.prolog.instance_divisor_is_one = elts->instance_divisor_is_one;
|
||||
key->ge.part.vs.prolog.instance_divisor_is_fetched = elts->instance_divisor_is_fetched;
|
||||
key->ge.mono.instance_divisor_is_one = elts->instance_divisor_is_one;
|
||||
key->ge.mono.instance_divisor_is_fetched = elts->instance_divisor_is_fetched;
|
||||
key->ge.opt.prefer_mono = elts->instance_divisor_is_fetched;
|
||||
|
||||
unsigned count_mask = (1 << vs->info.num_inputs) - 1;
|
||||
|
|
@ -2179,25 +2178,22 @@ void si_vs_key_update_inputs(struct si_context *sctx)
|
|||
|
||||
sctx->uses_nontrivial_vs_inputs = uses_nontrivial_vs_inputs;
|
||||
|
||||
/* draw_vertex_state (display lists) requires a trivial VS prolog that ignores
|
||||
* the current vertex buffers and vertex elements.
|
||||
/* draw_vertex_state (display lists) requires that all VS input lowering is disabled
|
||||
* because its vertex elements never need any lowering.
|
||||
*
|
||||
* We just computed the prolog key because we needed to set uses_nontrivial_vs_inputs,
|
||||
* so that we know whether the VS prolog should be updated when we switch from
|
||||
* draw_vertex_state to draw_vbo. Now clear the VS prolog for draw_vertex_state.
|
||||
* This should happen rarely because the VS prolog should be trivial in most
|
||||
* cases.
|
||||
* We just computed the key because we needed to set uses_nontrivial_vs_inputs, so that we know
|
||||
* whether the VS should be updated when we switch from draw_vertex_state to draw_vbo. Now
|
||||
* clear the VS input bits for draw_vertex_state. This should happen rarely because VS inputs
|
||||
* don't usually need any lowering.
|
||||
*/
|
||||
if (uses_nontrivial_vs_inputs && sctx->force_trivial_vs_inputs)
|
||||
si_clear_vs_key_inputs(sctx, key, &key->ge.part.vs.prolog);
|
||||
si_clear_vs_key_inputs(key);
|
||||
}
|
||||
|
||||
void si_get_vs_key_inputs(struct si_context *sctx, union si_shader_key *key,
|
||||
struct si_vs_prolog_bits *prolog_key)
|
||||
static void si_get_vs_key_inputs(struct si_context *sctx, union si_shader_key *key)
|
||||
{
|
||||
prolog_key->instance_divisor_is_one = sctx->shader.vs.key.ge.part.vs.prolog.instance_divisor_is_one;
|
||||
prolog_key->instance_divisor_is_fetched = sctx->shader.vs.key.ge.part.vs.prolog.instance_divisor_is_fetched;
|
||||
|
||||
key->ge.mono.instance_divisor_is_one = sctx->shader.vs.key.ge.mono.instance_divisor_is_one;
|
||||
key->ge.mono.instance_divisor_is_fetched = sctx->shader.vs.key.ge.mono.instance_divisor_is_fetched;
|
||||
key->ge.mono.vs_fetch_opencode = sctx->shader.vs.key.ge.mono.vs_fetch_opencode;
|
||||
memcpy(key->ge.mono.vs_fix_fetch, sctx->shader.vs.key.ge.mono.vs_fix_fetch,
|
||||
sizeof(key->ge.mono.vs_fix_fetch));
|
||||
|
|
@ -2624,7 +2620,7 @@ static inline void si_shader_selector_key(struct pipe_context *ctx, struct si_sh
|
|||
break;
|
||||
case MESA_SHADER_TESS_CTRL:
|
||||
if (sctx->gfx_level >= GFX9) {
|
||||
si_get_vs_key_inputs(sctx, key, &key->ge.part.tcs.ls_prolog);
|
||||
si_get_vs_key_inputs(sctx, key);
|
||||
key->ge.part.tcs.ls = sctx->shader.vs.cso;
|
||||
}
|
||||
break;
|
||||
|
|
@ -2637,10 +2633,10 @@ static inline void si_shader_selector_key(struct pipe_context *ctx, struct si_sh
|
|||
case MESA_SHADER_GEOMETRY:
|
||||
if (sctx->gfx_level >= GFX9) {
|
||||
if (sctx->shader.tes.cso) {
|
||||
si_clear_vs_key_inputs(sctx, key, &key->ge.part.gs.vs_prolog);
|
||||
si_clear_vs_key_inputs(key);
|
||||
key->ge.part.gs.es = sctx->shader.tes.cso;
|
||||
} else {
|
||||
si_get_vs_key_inputs(sctx, key, &key->ge.part.gs.vs_prolog);
|
||||
si_get_vs_key_inputs(sctx, key);
|
||||
key->ge.part.gs.es = sctx->shader.vs.cso;
|
||||
}
|
||||
|
||||
|
|
@ -4451,28 +4447,12 @@ static void si_update_tess_in_out_patch_vertices(struct si_context *sctx)
|
|||
sctx->shader.tcs.key.ge.opt.same_patch_vertices = same_patch_vertices;
|
||||
sctx->do_update_shaders = true;
|
||||
}
|
||||
|
||||
if (sctx->gfx_level == GFX9 && sctx->screen->info.has_ls_vgpr_init_bug) {
|
||||
/* Determine whether the LS VGPR fix should be applied.
|
||||
*
|
||||
* It is only required when num input CPs > num output CPs,
|
||||
* which cannot happen with the fixed function TCS.
|
||||
*/
|
||||
bool ls_vgpr_fix =
|
||||
sctx->patch_vertices > tcs->info.base.tess.tcs_vertices_out;
|
||||
|
||||
if (ls_vgpr_fix != sctx->shader.tcs.key.ge.part.tcs.ls_prolog.ls_vgpr_fix) {
|
||||
sctx->shader.tcs.key.ge.part.tcs.ls_prolog.ls_vgpr_fix = ls_vgpr_fix;
|
||||
sctx->do_update_shaders = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* These fields are static for fixed function TCS. So no need to set
|
||||
* do_update_shaders between fixed-TCS draws. As fixed-TCS to user-TCS
|
||||
* or opposite, do_update_shaders should already be set by bind state.
|
||||
*/
|
||||
sctx->shader.tcs.key.ge.opt.same_patch_vertices = sctx->gfx_level >= GFX9;
|
||||
sctx->shader.tcs.key.ge.part.tcs.ls_prolog.ls_vgpr_fix = false;
|
||||
|
||||
/* User may only change patch vertices, needs to update fixed func TCS. */
|
||||
if (sctx->shader.tcs.cso &&
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue