radv/gfx10: determine if a pipeline is eligible for NGG passthrough

It can't be enabled for geometry shaders, for NGG streamout and
for vertex shaders that export the primitive ID. NGG passthrough
requires that LDS isn't used.

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
This commit is contained in:
Samuel Pitoiset 2020-01-09 08:23:12 +01:00
parent c65015f83c
commit 0758f645d0
4 changed files with 59 additions and 12 deletions

View File

@ -149,6 +149,22 @@ bool radv_pipeline_has_ngg(const struct radv_pipeline *pipeline)
return variant->info.is_ngg;
}
bool radv_pipeline_has_ngg_passthrough(const struct radv_pipeline *pipeline)
{
assert(radv_pipeline_has_ngg(pipeline));
struct radv_shader_variant *variant = NULL;
if (pipeline->shaders[MESA_SHADER_GEOMETRY])
variant = pipeline->shaders[MESA_SHADER_GEOMETRY];
else if (pipeline->shaders[MESA_SHADER_TESS_EVAL])
variant = pipeline->shaders[MESA_SHADER_TESS_EVAL];
else if (pipeline->shaders[MESA_SHADER_VERTEX])
variant = pipeline->shaders[MESA_SHADER_VERTEX];
else
return false;
return variant->info.is_ngg_passthrough;
}
bool radv_pipeline_has_gs_copy_shader(const struct radv_pipeline *pipeline)
{
if (!radv_pipeline_has_gs(pipeline))
@ -2434,20 +2450,35 @@ radv_fill_shader_keys(struct radv_device *device,
keys[MESA_SHADER_VERTEX].vs_common_out.as_ngg = false;
}
if (!device->physical_device->use_ngg_streamout) {
gl_shader_stage last_xfb_stage = MESA_SHADER_VERTEX;
gl_shader_stage last_xfb_stage = MESA_SHADER_VERTEX;
for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_GEOMETRY; i++) {
if (nir[i])
last_xfb_stage = i;
}
for (int i = MESA_SHADER_VERTEX; i <= MESA_SHADER_GEOMETRY; i++) {
if (nir[i])
last_xfb_stage = i;
}
if (nir[last_xfb_stage] &&
radv_nir_stage_uses_xfb(nir[last_xfb_stage])) {
if (nir[MESA_SHADER_TESS_CTRL])
keys[MESA_SHADER_TESS_EVAL].vs_common_out.as_ngg = false;
else
keys[MESA_SHADER_VERTEX].vs_common_out.as_ngg = false;
bool uses_xfb = nir[last_xfb_stage] &&
radv_nir_stage_uses_xfb(nir[last_xfb_stage]);
if (!device->physical_device->use_ngg_streamout && uses_xfb) {
if (nir[MESA_SHADER_TESS_CTRL])
keys[MESA_SHADER_TESS_EVAL].vs_common_out.as_ngg = false;
else
keys[MESA_SHADER_VERTEX].vs_common_out.as_ngg = false;
}
/* Determine if the pipeline is eligible for the NGG passthrough
* mode. It can't be enabled for geometry shaders, for NGG
* streamout or for vertex shaders that export the primitive ID
* (this is checked later because we don't have the info here.)
*/
if (!nir[MESA_SHADER_GEOMETRY] && !uses_xfb) {
if (nir[MESA_SHADER_TESS_CTRL] &&
keys[MESA_SHADER_TESS_EVAL].vs_common_out.as_ngg) {
keys[MESA_SHADER_TESS_EVAL].vs_common_out.as_ngg_passthrough = true;
} else if (nir[MESA_SHADER_VERTEX] &&
keys[MESA_SHADER_VERTEX].vs_common_out.as_ngg) {
keys[MESA_SHADER_VERTEX].vs_common_out.as_ngg_passthrough = true;
}
}
}
@ -2523,6 +2554,16 @@ radv_fill_shader_info(struct radv_pipeline *pipeline,
keys[MESA_SHADER_TESS_EVAL].vs_common_out.export_clip_dists =
!!infos[MESA_SHADER_FRAGMENT].ps.num_input_clips_culls;
/* NGG passthrough mode can't be enabled for vertex shaders
* that export the primitive ID.
*
* TODO: I should really refactor the keys logic.
*/
if (nir[MESA_SHADER_VERTEX] &&
keys[MESA_SHADER_VERTEX].vs_common_out.export_prim_id) {
keys[MESA_SHADER_VERTEX].vs_common_out.as_ngg_passthrough = false;
}
filled_stages |= (1 << MESA_SHADER_FRAGMENT);
}

View File

@ -1656,6 +1656,8 @@ static inline bool radv_pipeline_has_tess(const struct radv_pipeline *pipeline)
bool radv_pipeline_has_ngg(const struct radv_pipeline *pipeline);
bool radv_pipeline_has_ngg_passthrough(const struct radv_pipeline *pipeline);
bool radv_pipeline_has_gs_copy_shader(const struct radv_pipeline *pipeline);
struct radv_userdata_info *radv_lookup_user_sgpr(struct radv_pipeline *pipeline,

View File

@ -55,6 +55,7 @@ struct radv_vs_out_key {
uint32_t as_es:1;
uint32_t as_ls:1;
uint32_t as_ngg:1;
uint32_t as_ngg_passthrough:1;
uint32_t export_prim_id:1;
uint32_t export_layer_id:1;
uint32_t export_clip_dists:1;
@ -241,6 +242,7 @@ struct radv_shader_info {
unsigned private_mem_vgprs;
bool need_indirect_descriptor_sets;
bool is_ngg;
bool is_ngg_passthrough;
struct {
uint64_t ls_outputs_written;
uint8_t input_usage_mask[VERT_ATTRIB_MAX];

View File

@ -755,6 +755,7 @@ radv_nir_shader_info_pass(const struct nir_shader *nir,
info->tes.as_es = key->vs_common_out.as_es;
info->tes.export_prim_id = key->vs_common_out.export_prim_id;
info->is_ngg = key->vs_common_out.as_ngg;
info->is_ngg_passthrough = key->vs_common_out.as_ngg_passthrough;
break;
case MESA_SHADER_TESS_CTRL:
info->tcs.tcs_vertices_out = nir->info.tess.tcs_vertices_out;
@ -764,6 +765,7 @@ radv_nir_shader_info_pass(const struct nir_shader *nir,
info->vs.as_ls = key->vs_common_out.as_ls;
info->vs.export_prim_id = key->vs_common_out.export_prim_id;
info->is_ngg = key->vs_common_out.as_ngg;
info->is_ngg_passthrough = key->vs_common_out.as_ngg_passthrough;
break;
default:
break;