i965/nir: lower TES PatchVerticesIn to a constant when a TCS is present
authorIago Toral Quiroga <itoral@igalia.com>
Tue, 9 Jan 2018 10:14:01 +0000 (11:14 +0100)
committerIago Toral Quiroga <itoral@igalia.com>
Wed, 10 Jan 2018 07:21:02 +0000 (08:21 +0100)
When a TCS is present at link time we know the number of vertices in the
patch and we can lower gl_PatchVerticesIn in the TesEval stage directly
to a constant. We already have a pass for this that we use in the
Vulkan pipeline, so we just reuse that.

Notice that the GLSL linker also implements this optimization, which
we are not removing because other drivers may still depend on it, so
this should only be useful for OpenGL SPIR-V shaders for now.

Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
src/mesa/drivers/dri/i965/brw_program.c

index f6c7e45..7fae22c 100644 (file)
@@ -89,15 +89,33 @@ brw_create_nir(struct brw_context *brw,
    nir_validate_shader(nir);
 
    /* Lower PatchVerticesIn from system value to uniform. This needs to
-    * happen before brw_preprocess_nir, since that will lower system values.
+    * happen before brw_preprocess_nir, since that will lower system values
+    * to intrinsics.
+    *
+    * We only do this for TES if no TCS is present, since otherwise we know
+    * the number of vertices in the patch at link time and we can lower it
+    * directly to a constant. We do this in nir_lower_patch_vertices, which
+    * needs to run after brw_nir_preprocess has turned the system values
+    * into intrinsics.
     */
-   if ((stage == MESA_SHADER_TESS_CTRL && brw->screen->devinfo.gen >= 8) ||
-       stage == MESA_SHADER_TESS_EVAL) {
+   const bool lower_patch_vertices_in_to_uniform =
+      (stage == MESA_SHADER_TESS_CTRL && brw->screen->devinfo.gen >= 8) ||
+      (stage == MESA_SHADER_TESS_EVAL &&
+       !shader_prog->_LinkedShaders[MESA_SHADER_TESS_CTRL]);
+
+   if (lower_patch_vertices_in_to_uniform)
       brw_nir_lower_patch_vertices_in_to_uniform(nir);
-   }
 
    nir = brw_preprocess_nir(brw->screen->compiler, nir);
 
+   if (stage == MESA_SHADER_TESS_EVAL && !lower_patch_vertices_in_to_uniform) {
+      assert(shader_prog->_LinkedShaders[MESA_SHADER_TESS_CTRL]);
+      struct gl_linked_shader *linked_tcs =
+         shader_prog->_LinkedShaders[MESA_SHADER_TESS_CTRL];
+      uint32_t patch_vertices = linked_tcs->Program->info.tess.tcs_vertices_out;
+      nir_lower_tes_patch_vertices(nir, patch_vertices);
+   }
+
    if (stage == MESA_SHADER_FRAGMENT) {
       static const struct nir_lower_wpos_ytransform_options wpos_options = {
          .state_tokens = {STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM, 0, 0, 0},