radv/gfx10: determine if a pipeline is eligible for NGG passthrough
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Thu, 9 Jan 2020 07:23:12 +0000 (08:23 +0100)
committerSamuel Pitoiset <samuel.pitoiset@gmail.com>
Mon, 13 Jan 2020 07:14:40 +0000 (08:14 +0100)
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>
src/amd/vulkan/radv_pipeline.c
src/amd/vulkan/radv_private.h
src/amd/vulkan/radv_shader.h
src/amd/vulkan/radv_shader_info.c

index a4cc840027a09e0c60d0e0c4bcd25a2f8120697f..12fea44bed853709a447c89125125035f0de5f44 100644 (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);
        }
 
index 4dccf23acc7a3a4f63708d638bf968c06c4b24e6..082a8451cc0b06656262e9ebd85941d98da0f34d 100644 (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,
index 7ffce47bdd8e1eeb28b001d1a220c68b741ea089..37b54c2f4947d92968c143d126eb25174170d2d0 100644 (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];
index 5384d1a0d17d826902467028598adbcb11fd37cd..613746c7ddef006c7bc1389c07beb64211c7f483 100644 (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;