i965: Add scalar GS input lowering code.
authorKenneth Graunke <kenneth@whitecape.org>
Thu, 24 Sep 2015 03:52:19 +0000 (20:52 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Tue, 3 Nov 2015 23:08:49 +0000 (15:08 -0800)
We really ought to compute the VUE map at link time and stash it, rather
than recomputing it here, but with the mess of program structures I
wasn't sure where to put it.  We can improve that later.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Kristian Høgsberg <krh@bitplanet.net>
src/mesa/drivers/dri/i965/brw_nir.c

index 11f111382f45c846e81ae1ba3ddebf0244a1bcbd..a7a5eb511cdc63ad4fa0912b4dbd4d682539f12e 100644 (file)
@@ -56,7 +56,8 @@ remap_vs_attrs(nir_block *block, void *closure)
 }
 
 static void
-brw_nir_lower_inputs(nir_shader *nir, bool is_scalar)
+brw_nir_lower_inputs(const struct brw_device_info *devinfo,
+                     nir_shader *nir, bool is_scalar)
 {
    switch (nir->stage) {
    case MESA_SHADER_VERTEX:
@@ -90,11 +91,43 @@ brw_nir_lower_inputs(nir_shader *nir, bool is_scalar)
          }
       }
       break;
-   case MESA_SHADER_GEOMETRY:
-      foreach_list_typed(nir_variable, var, node, &nir->inputs) {
-         var->data.driver_location = var->data.location;
+   case MESA_SHADER_GEOMETRY: {
+      if (!is_scalar) {
+         foreach_list_typed(nir_variable, var, node, &nir->inputs) {
+            var->data.driver_location = var->data.location;
+         }
+      } else {
+         /* The GLSL linker will have already matched up GS inputs and
+          * the outputs of prior stages.  The driver does extend VS outputs
+          * in some cases, but only for legacy OpenGL or Gen4-5 hardware,
+          * neither of which offer geometry shader support.  So we can
+          * safely ignore that.
+          *
+          * For SSO pipelines, we use a fixed VUE map layout based on variable
+          * locations, so we can rely on rendezvous-by-location to make this
+          * work.
+          *
+          * However, we need to ignore VARYING_SLOT_PRIMITIVE_ID, as it's not
+          * written by previous stages and shows up via payload magic.
+          */
+         struct brw_vue_map input_vue_map;
+         GLbitfield64 inputs_read =
+            nir->info.inputs_read & ~VARYING_BIT_PRIMITIVE_ID;
+         brw_compute_vue_map(devinfo, &input_vue_map, inputs_read,
+                             nir->info.separate_shader);
+
+         /* Start with the slot for the variable's base. */
+         foreach_list_typed(nir_variable, var, node, &nir->inputs) {
+            assert(input_vue_map.varying_to_slot[var->data.location] != -1);
+            var->data.driver_location =
+               input_vue_map.varying_to_slot[var->data.location];
+         }
+
+         /* Inputs are stored in vec4 slots, so use type_size_vec4(). */
+         nir_lower_io(nir, nir_var_shader_in, type_size_vec4);
       }
       break;
+   }
    case MESA_SHADER_FRAGMENT:
       assert(is_scalar);
       nir_assign_var_locations(&nir->inputs, &nir->num_inputs,
@@ -187,6 +220,7 @@ brw_create_nir(struct brw_context *brw,
                bool is_scalar)
 {
    struct gl_context *ctx = &brw->ctx;
+   const struct brw_device_info *devinfo = brw->intelScreen->devinfo;
    const nir_shader_compiler_options *options =
       ctx->Const.ShaderCompilerOptions[stage].NirOptions;
    static const nir_lower_tex_options tex_options = {
@@ -230,7 +264,7 @@ brw_create_nir(struct brw_context *brw,
    /* Get rid of split copies */
    nir_optimize(nir, is_scalar);
 
-   brw_nir_lower_inputs(nir, is_scalar);
+   brw_nir_lower_inputs(devinfo, nir, is_scalar);
    brw_nir_lower_outputs(nir, is_scalar);
    nir_assign_var_locations(&nir->uniforms,
                             &nir->num_uniforms,