i965: SF: New implementation of get_attr_override using the VUE map.
authorPaul Berry <stereotype441@gmail.com>
Tue, 30 Aug 2011 20:06:14 +0000 (13:06 -0700)
committerPaul Berry <stereotype441@gmail.com>
Tue, 6 Sep 2011 18:04:56 +0000 (11:04 -0700)
This patch changes get_attr_override() (which computes the
relationship between vertex shader outputs and fragment shader inputs)
to use the VUE map.

Reviewed-by: Eric Anholt <eric@anholt.net>
src/mesa/drivers/dri/i965/brw_state.h
src/mesa/drivers/dri/i965/gen6_sf_state.c
src/mesa/drivers/dri/i965/gen7_sf_state.c

index cede4e5c9167290fcf52fdc9539d1b7db41fa237..6fc95eb646e7e0a327f647af171c8b48169970b2 100644 (file)
@@ -206,7 +206,8 @@ void upload_default_color(struct brw_context *brw,
 
 /* gen6_sf_state.c */
 uint32_t
-get_attr_override(struct brw_context *brw, int fs_attr, int two_side_color);
+get_attr_override(struct brw_vue_map *vue_map, int urb_entry_read_offset,
+                  int fs_attr, bool two_side_color);
 
 /* gen7_misc_state.c */
 unsigned int
index 714914aa6bb8e52abec2ae7dc0cb669b4be491f1..886727987407c0682ee00d860523ff578f8c59f0 100644 (file)
 #include "main/macros.h"
 #include "intel_batchbuffer.h"
 
+/**
+ * Determine the appropriate attribute override value to store into the
+ * 3DSTATE_SF structure for a given fragment shader attribute.  The attribute
+ * override value contains two pieces of information: the location of the
+ * attribute in the VUE (relative to urb_entry_read_offset, see below), and a
+ * flag indicating whether to "swizzle" the attribute based on the direction
+ * the triangle is facing.
+ *
+ * If an attribute is "swizzled", then the given VUE location is used for
+ * front-facing triangles, and the VUE location that immediately follows is
+ * used for back-facing triangles.  We use this to implement the mapping from
+ * gl_FrontColor/gl_BackColor to gl_Color.
+ *
+ * urb_entry_read_offset is the offset into the VUE at which the SF unit is
+ * being instructed to begin reading attribute data.  It can be set to a
+ * nonzero value to prevent the SF unit from wasting time reading elements of
+ * the VUE that are not needed by the fragment shader.  It is measured in
+ * 256-bit increments.
+ */
 uint32_t
-get_attr_override(struct brw_context *brw, int fs_attr, int two_side_color)
+get_attr_override(struct brw_vue_map *vue_map, int urb_entry_read_offset,
+                  int fs_attr, bool two_side_color)
 {
-   int attr_index = 0, i;
-   int bfc = 0;
+   int attr_override, slot;
    int vs_attr = frag_attrib_to_vert_result(fs_attr);
+   if (vs_attr < 0 || vs_attr == VERT_RESULT_HPOS) {
+      /* These attributes will be overwritten by the fragment shader's
+       * interpolation code (see emit_interp() in brw_wm_fp.c), so just let
+       * them reference the first available attribute.
+       */
+      return 0;
+   }
 
-   if (vs_attr < 0)
-      vs_attr = 0;
-
-   /* Find the source index (0 = first attribute after the 4D position)
-    * for this output attribute.  attr is currently a VERT_RESULT_* but should
-    * be FRAG_ATTRIB_*.
-    */
-   for (i = 1; i < vs_attr; i++) {
-      if (i == VERT_RESULT_PSIZ)
-        continue;
-      if (brw->vs.prog_data->outputs_written & BITFIELD64_BIT(i))
-        attr_index++;
+   /* Find the VUE slot for this attribute. */
+   slot = vue_map->vert_result_to_slot[vs_attr];
+   if (slot == -1) {
+      /* This attribute does not exist in the VUE--that means that the vertex
+       * shader did not write to it.  Behavior is undefined in this case, so
+       * just reference the first available attribute.
+       */
+      return 0;
    }
 
-   assert(attr_index < 32);
+   /* Compute the location of the attribute relative to urb_entry_read_offset.
+    * Each increment of urb_entry_read_offset represents a 256-bit value, so
+    * it counts for two 128-bit VUE slots.
+    */
+   attr_override = slot - 2 * urb_entry_read_offset;
+   assert (attr_override >= 0 && attr_override < 32);
 
+   /* If we are doing two-sided color, and the VUE slot following this one
+    * represents a back-facing color, then we need to instruct the SF unit to
+    * do back-facing swizzling.
+    */
    if (two_side_color) {
-       if ((brw->vs.prog_data->outputs_written & BITFIELD64_BIT(VERT_RESULT_COL1)) &&
-           (brw->vs.prog_data->outputs_written & BITFIELD64_BIT(VERT_RESULT_BFC1))) {
-           assert(brw->vs.prog_data->outputs_written & BITFIELD64_BIT(VERT_RESULT_COL0));
-           assert(brw->vs.prog_data->outputs_written & BITFIELD64_BIT(VERT_RESULT_BFC0));
-           bfc = 2;
-       } else if ((brw->vs.prog_data->outputs_written & BITFIELD64_BIT(VERT_RESULT_COL0)) &&
-                (brw->vs.prog_data->outputs_written & BITFIELD64_BIT(VERT_RESULT_BFC0)))
-           bfc = 1;
-   }
-
-   if (bfc && (fs_attr <= FRAG_ATTRIB_TEX7 && fs_attr > FRAG_ATTRIB_WPOS)) {
-       if (fs_attr == FRAG_ATTRIB_COL0)
-           attr_index |= (ATTRIBUTE_SWIZZLE_INPUTATTR_FACING << ATTRIBUTE_SWIZZLE_SHIFT);
-       else if (fs_attr == FRAG_ATTRIB_COL1 && bfc == 2) {
-           attr_index++;
-           attr_index |= (ATTRIBUTE_SWIZZLE_INPUTATTR_FACING << ATTRIBUTE_SWIZZLE_SHIFT);
-       } else {
-           attr_index += bfc;
-       }
+      if (vue_map->slot_to_vert_result[slot] == VERT_RESULT_COL0 &&
+          vue_map->slot_to_vert_result[slot+1] == VERT_RESULT_BFC0)
+         attr_override |= (ATTRIBUTE_SWIZZLE_INPUTATTR_FACING << ATTRIBUTE_SWIZZLE_SHIFT);
+      else if (vue_map->slot_to_vert_result[slot] == VERT_RESULT_COL1 &&
+               vue_map->slot_to_vert_result[slot+1] == VERT_RESULT_BFC1)
+         attr_override |= (ATTRIBUTE_SWIZZLE_INPUTATTR_FACING << ATTRIBUTE_SWIZZLE_SHIFT);
    }
 
-   return attr_index;
+   return attr_override;
 }
 
 static void
@@ -85,6 +103,7 @@ upload_sf_state(struct brw_context *brw)
 {
    struct intel_context *intel = &brw->intel;
    struct gl_context *ctx = &intel->ctx;
+   struct brw_vue_map vue_map;
    /* CACHE_NEW_VS_PROG */
    uint32_t num_inputs = brw_count_bits(brw->vs.prog_data->outputs_written);
    /* BRW_NEW_FRAGMENT_PROGRAM */
@@ -94,22 +113,24 @@ upload_sf_state(struct brw_context *brw)
    /* _NEW_BUFFER */
    GLboolean render_to_fbo = brw->intel.ctx.DrawBuffer->Name != 0;
    int attr = 0, input_index = 0;
-   int urb_start;
+   int urb_entry_read_offset;
    int two_side_color = (ctx->Light.Enabled && ctx->Light.Model.TwoSide);
    float point_size;
    uint16_t attr_overrides[FRAG_ATTRIB_MAX];
+   int nr_userclip;
 
    /* _NEW_TRANSFORM */
    if (ctx->Transform.ClipPlanesEnabled)
-      urb_start = 2;
+      urb_entry_read_offset = 2;
    else
-      urb_start = 1;
+      urb_entry_read_offset = 1;
+   nr_userclip = brw_count_bits(ctx->Transform.ClipPlanesEnabled);
 
    dw1 =
       GEN6_SF_SWIZZLE_ENABLE |
       num_outputs << GEN6_SF_NUM_OUTPUTS_SHIFT |
       (num_inputs + 1) / 2 << GEN6_SF_URB_ENTRY_READ_LENGTH_SHIFT |
-      urb_start << GEN6_SF_URB_ENTRY_READ_OFFSET_SHIFT;
+      urb_entry_read_offset << GEN6_SF_URB_ENTRY_READ_OFFSET_SHIFT;
    dw2 = GEN6_SF_VIEWPORT_TRANSFORM_ENABLE |
       GEN6_SF_STATISTICS_ENABLE;
    dw3 = 0;
@@ -233,6 +254,8 @@ upload_sf_state(struct brw_context *brw)
    /* Create the mapping from the FS inputs we produce to the VS outputs
     * they source from.
     */
+   brw_compute_vue_map(&vue_map, intel, nr_userclip, two_side_color,
+                       brw->vs.prog_data->outputs_written);
    for (; attr < FRAG_ATTRIB_MAX; attr++) {
       if (!(brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(attr)))
         continue;
@@ -254,8 +277,9 @@ upload_sf_state(struct brw_context *brw)
        */
       assert(input_index < 16 || attr == input_index);
 
-      attr_overrides[input_index++] = get_attr_override(brw, attr,
-                                                       two_side_color);
+      attr_overrides[input_index++] =
+         get_attr_override(&vue_map, urb_entry_read_offset, attr,
+                           two_side_color);
    }
 
    for (; input_index < FRAG_ATTRIB_MAX; input_index++)
index 0f97cea652dfe32cf80f8fa9fd743a04a4324f74..4d1a2aa86848b05d16d5b38377a0c4f13caf0261 100644 (file)
@@ -33,6 +33,7 @@ upload_sbe_state(struct brw_context *brw)
 {
    struct intel_context *intel = &brw->intel;
    struct gl_context *ctx = &intel->ctx;
+   struct brw_vue_map vue_map;
    /* CACHE_NEW_VS_PROG */
    uint32_t num_inputs = brw_count_bits(brw->vs.prog_data->outputs_written);
    /* BRW_NEW_FRAGMENT_PROGRAM */
@@ -41,7 +42,9 @@ upload_sbe_state(struct brw_context *brw)
    int i;
    int attr = 0, input_index = 0;
    /* _NEW_TRANSFORM */
-   int urb_start = ctx->Transform.ClipPlanesEnabled ? 2 : 1;
+   int urb_entry_read_offset = ctx->Transform.ClipPlanesEnabled ? 2 : 1;
+   int nr_userclip = brw_count_bits(ctx->Transform.ClipPlanesEnabled);
+
    /* _NEW_LIGHT */
    int two_side_color = (ctx->Light.Enabled && ctx->Light.Model.TwoSide);
    uint16_t attr_overrides[FRAG_ATTRIB_MAX];
@@ -51,7 +54,7 @@ upload_sbe_state(struct brw_context *brw)
       GEN7_SBE_SWIZZLE_ENABLE |
       num_outputs << GEN7_SBE_NUM_OUTPUTS_SHIFT |
       (num_inputs + 1) / 2 << GEN7_SBE_URB_ENTRY_READ_LENGTH_SHIFT |
-      urb_start << GEN7_SBE_URB_ENTRY_READ_OFFSET_SHIFT;
+      urb_entry_read_offset << GEN7_SBE_URB_ENTRY_READ_OFFSET_SHIFT;
 
    /* _NEW_POINT */
    if (ctx->Point.SpriteOrigin == GL_LOWER_LEFT)
@@ -69,6 +72,8 @@ upload_sbe_state(struct brw_context *brw)
    /* Create the mapping from the FS inputs we produce to the VS outputs
     * they source from.
     */
+   brw_compute_vue_map(&vue_map, intel, nr_userclip, two_side_color,
+                       brw->vs.prog_data->outputs_written);
    for (; attr < FRAG_ATTRIB_MAX; attr++) {
       if (!(brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(attr)))
         continue;
@@ -89,8 +94,9 @@ upload_sbe_state(struct brw_context *brw)
        */
       assert(input_index < 16 || attr == input_index);
 
-      attr_overrides[input_index++] = get_attr_override(brw, attr,
-                                                       two_side_color);
+      attr_overrides[input_index++] =
+         get_attr_override(&vue_map, urb_entry_read_offset, attr,
+                           two_side_color);
    }
 
    for (; attr < FRAG_ATTRIB_MAX; attr++)