turnip: Lower shaders for tessellation
authorBrian Ho <brian@brkho.com>
Fri, 24 Apr 2020 15:05:48 +0000 (08:05 -0700)
committerMarge Bot <eric+marge@anholt.net>
Mon, 22 Jun 2020 14:35:45 +0000 (14:35 +0000)
To enable lowering of tess-related shaders, this commit sets the
tessellation primitive field of the ir3_shader_key. In addition,
this commit sets various tessellation flags for
spirv_to_nir configuration.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5059>

src/freedreno/vulkan/tu_pipeline.c
src/freedreno/vulkan/tu_shader.c

index ef1422fa708bb0871239be0f663b71c28b34d947..6093881217e8973c345c45efd5527463231f894b 100644 (file)
@@ -1672,7 +1672,26 @@ tu_pipeline_shader_key_init(struct ir3_shader_key *key,
    if (msaa_info->sampleShadingEnable)
       key->sample_shading = true;
 
-   /* TODO: Populate the remaining fields of ir3_shader_key. */
+   /* We set this after we compile to NIR because we need the prim mode */
+   key->tessellation = IR3_TESS_NONE;
+}
+
+static uint32_t
+tu6_get_tessmode(struct tu_shader* shader)
+{
+   uint32_t primitive_mode = shader->ir3_shader->nir->info.tess.primitive_mode;
+   switch (primitive_mode) {
+   case GL_ISOLINES:
+      return IR3_TESS_ISOLINES;
+   case GL_TRIANGLES:
+      return IR3_TESS_TRIANGLES;
+   case GL_QUADS:
+      return IR3_TESS_QUADS;
+   case GL_NONE:
+      return IR3_TESS_NONE;
+   default:
+      unreachable("bad tessmode");
+   }
 }
 
 static VkResult
@@ -1702,6 +1721,14 @@ tu_pipeline_builder_compile_shaders(struct tu_pipeline_builder *builder)
       if (!shader)
          return VK_ERROR_OUT_OF_HOST_MEMORY;
 
+      /* In SPIR-V generated from GLSL, the primitive mode is specified in the
+       * tessellation evaluation shader, but in SPIR-V generated from HLSL,
+       * the mode is specified in the tessellation control shader. */
+      if ((stage == MESA_SHADER_TESS_EVAL || stage == MESA_SHADER_TESS_CTRL) &&
+          key.tessellation == IR3_TESS_NONE) {
+         key.tessellation = tu6_get_tessmode(shader);
+      }
+
       builder->shaders[stage] = shader;
    }
 
index 1a0772726f553d92ba87b489a700e9588e4451f2..b25a959b89ee7693057bada8c2dc683cbe379b45 100644 (file)
@@ -43,8 +43,11 @@ tu_spirv_to_nir(struct ir3_compiler *compiler,
    const struct spirv_to_nir_options spirv_options = {
       .frag_coord_is_sysval = true,
       .lower_ubo_ssbo_access_to_offsets = true,
+      .tess_levels_are_sysvals = true,
+      .lower_tess_levels_to_vec = true,
       .caps = {
-         .transform_feedback = compiler->gpu_id >= 600,
+         .transform_feedback = true,
+         .tessellation = true,
       },
    };
    const nir_shader_compiler_options *nir_options =
@@ -608,6 +611,11 @@ tu_shader_create(struct tu_device *dev,
    NIR_PASS_V(nir, nir_opt_combine_stores, nir_var_all);
 
    /* ir3 doesn't support indirect input/output */
+   /* TODO: We shouldn't perform this lowering pass on gl_TessLevelInner
+    * and gl_TessLevelOuter. Since the tess levels are actually stored in
+    * a global BO, they can be directly accessed via stg and ldg.
+    * nir_lower_indirect_derefs will instead generate a big if-ladder which
+    * isn't *incorrect* but is much less efficient. */
    NIR_PASS_V(nir, nir_lower_indirect_derefs, nir_var_shader_in | nir_var_shader_out);
 
    NIR_PASS_V(nir, nir_lower_io_arrays_to_elements_no_indirects, false);