panfrost: Add high-level varying emit
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Mon, 8 Jun 2020 19:29:05 +0000 (15:29 -0400)
committerMarge Bot <eric+marge@anholt.net>
Fri, 12 Jun 2020 14:45:50 +0000 (14:45 +0000)
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5423>

src/gallium/drivers/panfrost/pan_cmdstream.c

index 1b2e632cf1b971e8c9516038e98e18991e701282..1520283335eab3aa0b5f15b6cd6f65c3ac0f3ccd 100644 (file)
@@ -1944,6 +1944,100 @@ panfrost_xfb_captured(struct panfrost_shader_state *xfb,
         return o->output_buffer < max_xfb;
 }
 
+/* Higher-level wrapper around all of the above, classifying a varying into one
+ * of the above types */
+
+static struct mali_attr_meta
+panfrost_emit_varying(
+                struct panfrost_shader_state *stage,
+                struct panfrost_shader_state *other,
+                struct panfrost_shader_state *xfb,
+                unsigned present,
+                unsigned max_xfb,
+                unsigned *streamout_offsets,
+                unsigned quirks,
+                unsigned *gen_offsets,
+                unsigned *gen_stride,
+                unsigned idx,
+                bool should_alloc,
+                bool is_fragment)
+{
+        gl_varying_slot loc = stage->varyings_loc[idx];
+        enum mali_format format = stage->varyings[idx].format;
+
+        if (has_point_coord(stage->point_sprite_mask, loc)) {
+                return pan_emit_vary_special(present, PAN_VARY_PNTCOORD, quirks);
+        } else if (panfrost_xfb_captured(xfb, loc, max_xfb)) {
+                struct pipe_stream_output *o = pan_get_so(&xfb->stream_output, loc);
+                return pan_emit_vary_xfb(present, max_xfb, streamout_offsets, quirks, format, *o);
+        } else if (loc == VARYING_SLOT_POS) {
+                if (is_fragment)
+                        return pan_emit_vary_special(present, PAN_VARY_FRAGCOORD, quirks);
+                else
+                        return pan_emit_vary_special(present, PAN_VARY_POSITION, quirks);
+        } else if (loc == VARYING_SLOT_PSIZ) {
+                return pan_emit_vary_special(present, PAN_VARY_PSIZ, quirks);
+        } else if (loc == VARYING_SLOT_PNTC) {
+                return pan_emit_vary_special(present, PAN_VARY_PNTCOORD, quirks);
+        } else if (loc == VARYING_SLOT_FACE) {
+                return pan_emit_vary_special(present, PAN_VARY_FACE, quirks);
+        }
+
+        /* We've exhausted special cases, so it's otherwise a general varying. Check if we're linked */
+        signed other_idx = -1;
+
+        for (unsigned j = 0; j < other->varying_count; ++j) {
+                if (other->varyings_loc[j] == loc) {
+                        other_idx = j;
+                        break;
+                }
+        }
+
+        if (other_idx < 0)
+                return pan_emit_vary_only(present, quirks);
+
+        unsigned offset = gen_offsets[other_idx];
+
+        if (should_alloc) {
+                /* We're linked, so allocate a space via a watermark allocation */
+                gen_offsets[idx] = *gen_stride;
+                offset = *gen_stride;
+
+                /* If a varying is marked for XFB but not actually captured, we
+                 * should match the format to the format that would otherwise
+                 * be used for XFB, since dEQP checks for invariance here. It's
+                 * unclear if this is required by the spec. */
+
+                if (xfb->so_mask & (1ull << loc)) {
+                        struct pipe_stream_output *o = pan_get_so(&xfb->stream_output, loc);
+                        format = pan_xfb_format(format, o->num_components);
+                }
+
+                *gen_stride += pan_varying_size(format);
+        }
+
+        return pan_emit_vary(present, PAN_VARY_GENERAL,
+                        quirks, format, offset);
+}
+
+static void
+pan_emit_special_input(union mali_attr *varyings,
+                unsigned present,
+                enum pan_special_varying v,
+                mali_ptr addr)
+{
+        if (present & (1 << v)) {
+                /* Ensure we write exactly once for performance and with fields
+                 * zeroed appropriately to avoid flakes */
+
+                union mali_attr s = {
+                        .elements = addr
+                };
+
+                varyings[pan_varying_index(present, v)] = s;
+        }
+}
+
 void
 panfrost_emit_varying_descriptor(struct panfrost_batch *batch,
                                  unsigned vertex_count,