diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index a4cc840027a..12fea44bed8 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -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); } diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index 4dccf23acc7..082a8451cc0 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -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, diff --git a/src/amd/vulkan/radv_shader.h b/src/amd/vulkan/radv_shader.h index 7ffce47bdd8..37b54c2f494 100644 --- a/src/amd/vulkan/radv_shader.h +++ b/src/amd/vulkan/radv_shader.h @@ -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]; diff --git a/src/amd/vulkan/radv_shader_info.c b/src/amd/vulkan/radv_shader_info.c index 5384d1a0d17..613746c7dde 100644 --- a/src/amd/vulkan/radv_shader_info.c +++ b/src/amd/vulkan/radv_shader_info.c @@ -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;