iris: Remap stream output indexes back to VARYING_SLOT_*.
authorKenneth Graunke <kenneth@whitecape.org>
Wed, 23 Jan 2019 07:28:39 +0000 (23:28 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Thu, 21 Feb 2019 18:26:11 +0000 (10:26 -0800)
Previously I had a hack in st/mesa to make it stop remapping
VARYING_SLOT_* into the naively compacted slots, which aren't
what we want.  But that wasn't very feasible, as we'd have to
update all drivers, or add capability bits, and it gets messy fast.

It turns out that I can map back to VARYING_SLOT_* in about 5 LOC,
so let's just do that.  It removes the need for hacks, and is easy.

This also fixes KHR-GL46.enhanced_layouts.xfb_capture_struct, which
apparently with my hack was still getting the wrong slot info.

src/gallium/drivers/iris/iris_program.c

index b7d626df7d367ee41a49ec1293419f9e0b49bfb1..b50ac9d74c488dc27e813332ffe9fd7c939fb9ab 100644 (file)
@@ -175,12 +175,35 @@ iris_lower_storage_image_derefs(nir_shader *nir)
 
 // XXX: need unify_interfaces() at link time...
 
+/**
+ * Fix an uncompiled shader's stream output info.
+ *
+ * Core Gallium stores output->register_index as a "slot" number, where
+ * slots are assigned consecutively to all outputs in info->outputs_written.
+ * This naive packing of outputs doesn't work for us - we too have slots,
+ * but the layout is defined by the VUE map, which we won't have until we
+ * compile a specific shader variant.  So, we remap these and simply store
+ * VARYING_SLOT_* in our copy's output->register_index fields.
+ *
+ * We also fix up VARYING_SLOT_{LAYER,VIEWPORT,PSIZ} to select the Y/Z/W
+ * components of our VUE header.  See brw_vue_map.c for the layout.
+ */
 static void
-update_so_info(struct pipe_stream_output_info *so_info)
+update_so_info(struct pipe_stream_output_info *so_info,
+               uint64_t outputs_written)
 {
+   uint8_t reverse_map[64] = {};
+   unsigned slot = 0;
+   while (outputs_written) {
+      reverse_map[slot++] = u_bit_scan64(&outputs_written);
+   }
+
    for (unsigned i = 0; i < so_info->num_outputs; i++) {
       struct pipe_stream_output *output = &so_info->output[i];
 
+      /* Map Gallium's condensed "slots" back to real VARYING_SLOT_* enums */
+      output->register_index = reverse_map[output->register_index];
+
       /* The VUE header contains three scalar fields packed together:
        * - gl_PointSize is stored in VARYING_SLOT_PSIZ.w
        * - gl_Layer is stored in VARYING_SLOT_PSIZ.y
@@ -237,7 +260,7 @@ iris_create_uncompiled_shader(struct pipe_context *ctx,
    ish->nir = nir;
    if (so_info) {
       memcpy(&ish->stream_output, so_info, sizeof(*so_info));
-      update_so_info(&ish->stream_output);
+      update_so_info(&ish->stream_output, nir->info.outputs_written);
    }
 
    return ish;