i965: Add support for gl_VertexID and gl_InstanceID.
authorEric Anholt <eric@anholt.net>
Wed, 9 Nov 2011 02:50:09 +0000 (18:50 -0800)
committerEric Anholt <eric@anholt.net>
Fri, 11 Nov 2011 16:27:59 +0000 (08:27 -0800)
The compiler setup for these VF-uploaded attributes looks a little
cheesy with mixing system values and real VBO-sourced attributes.  It
would be nice if we could just compute the ATTR[] map to GRF index up
front and use it at visit time instead of using ir->location in the
ATTR file.  However, we don't know the reg_offset at
visit(ir_variable *) time, so we can't do the mapping that early.

Fixes piglit vertexid test.

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/mesa/drivers/dri/i965/brw_context.h
src/mesa/drivers/dri/i965/brw_draw_upload.c
src/mesa/drivers/dri/i965/brw_vec4_emit.cpp
src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp

index fb03208c627116dad628afe620f5fa65a63fcd81..e5d2d140b1e95e66c810a136f2510a8cffd3452e 100644 (file)
@@ -387,6 +387,7 @@ struct brw_vs_prog_data {
    const float *pull_param[MAX_UNIFORMS * 4];
 
    bool uses_new_param_layout;
+   bool uses_vertexid;
 };
 
 
index 52daed8ba58d2a168c65edd61c362fccc18d11a3..bd3d96914399c5d53f9e26f25741a2406a746916 100644 (file)
@@ -591,7 +591,7 @@ static void brw_emit_vertices(struct brw_context *brw)
 {
    struct gl_context *ctx = &brw->intel.ctx;
    struct intel_context *intel = intel_context(ctx);
-   GLuint i;
+   GLuint i, nr_elements;
 
    brw_prepare_vertices(brw);
 
@@ -667,17 +667,19 @@ static void brw_emit_vertices(struct brw_context *brw)
       ADVANCE_BATCH();
    }
 
+   nr_elements = brw->vb.nr_enabled + brw->vs.prog_data->uses_vertexid;
+
    /* The hardware allows one more VERTEX_ELEMENTS than VERTEX_BUFFERS, presumably
     * for VertexID/InstanceID.
     */
    if (intel->gen >= 6) {
-      assert(brw->vb.nr_enabled <= 34);
+      assert(nr_elements <= 34);
    } else {
-      assert(brw->vb.nr_enabled <= 18);
+      assert(nr_elements <= 18);
    }
 
-   BEGIN_BATCH(1 + brw->vb.nr_enabled * 2);
-   OUT_BATCH((_3DSTATE_VERTEX_ELEMENTS << 16) | (2*brw->vb.nr_enabled - 1));
+   BEGIN_BATCH(1 + nr_elements * 2);
+   OUT_BATCH((_3DSTATE_VERTEX_ELEMENTS << 16) | (2 * nr_elements - 1));
    for (i = 0; i < brw->vb.nr_enabled; i++) {
       struct brw_vertex_element *input = brw->vb.enabled[i];
       uint32_t format = get_surface_type(input->glarray->Type,
@@ -723,6 +725,30 @@ static void brw_emit_vertices(struct brw_context *brw)
                     (comp3 << BRW_VE1_COMPONENT_3_SHIFT) |
                     ((i * 4) << BRW_VE1_DST_OFFSET_SHIFT));
    }
+
+   if (brw->vs.prog_data->uses_vertexid) {
+      uint32_t dw0 = 0, dw1 = 0;
+
+      dw1 = ((BRW_VE1_COMPONENT_STORE_VID << BRW_VE1_COMPONENT_0_SHIFT) |
+            (BRW_VE1_COMPONENT_STORE_IID << BRW_VE1_COMPONENT_1_SHIFT) |
+            (BRW_VE1_COMPONENT_STORE_PID << BRW_VE1_COMPONENT_2_SHIFT) |
+            (BRW_VE1_COMPONENT_STORE_0 << BRW_VE1_COMPONENT_3_SHIFT));
+
+      if (intel->gen >= 6) {
+        dw0 |= GEN6_VE0_VALID;
+      } else {
+        dw0 |= BRW_VE0_VALID;
+        dw1 |= (i * 4) << BRW_VE1_DST_OFFSET_SHIFT;
+      }
+
+      /* Note that for gl_VertexID, gl_InstanceID, and gl_PrimitiveID values,
+       * the format is ignored and the value is always int.
+       */
+
+      OUT_BATCH(dw0);
+      OUT_BATCH(dw1);
+   }
+
    CACHED_BATCH();
 }
 
index dc39f17614a42ac2221060dfbd88bf9374ea40fb..54bbe1347b96e8b1ab707749056ed008c6734d4f 100644 (file)
@@ -35,7 +35,7 @@ int
 vec4_visitor::setup_attributes(int payload_reg)
 {
    int nr_attributes;
-   int attribute_map[VERT_ATTRIB_MAX];
+   int attribute_map[VERT_ATTRIB_MAX + 1];
 
    nr_attributes = 0;
    for (int i = 0; i < VERT_ATTRIB_MAX; i++) {
@@ -45,6 +45,15 @@ vec4_visitor::setup_attributes(int payload_reg)
       }
    }
 
+   /* VertexID is stored by the VF as the last vertex element, but we
+    * don't represent it with a flag in inputs_read, so we call it
+    * VERT_ATTRIB_MAX.
+    */
+   if (prog_data->uses_vertexid) {
+      attribute_map[VERT_ATTRIB_MAX] = payload_reg + nr_attributes;
+      nr_attributes++;
+   }
+
    foreach_list(node, &this->instructions) {
       vec4_instruction *inst = (vec4_instruction *)node;
 
index 5b80f559015510f267b701fc9bcc5847efeea30c..853c3eeca1391c98bf892fbd68f53e1787d57bb1 100644 (file)
@@ -880,6 +880,27 @@ vec4_visitor::visit(ir_variable *ir)
       }
       break;
 
+   case ir_var_system_value:
+      /* VertexID is stored by the VF as the last vertex element, but
+       * we don't represent it with a flag in inputs_read, so we call
+       * it VERT_ATTRIB_MAX, which setup_attributes() picks up on.
+       */
+      reg = new(mem_ctx) dst_reg(ATTR, VERT_ATTRIB_MAX);
+      prog_data->uses_vertexid = true;
+
+      switch (ir->location) {
+      case SYSTEM_VALUE_VERTEX_ID:
+        reg->writemask = WRITEMASK_X;
+        break;
+      case SYSTEM_VALUE_INSTANCE_ID:
+        reg->writemask = WRITEMASK_Y;
+        break;
+      default:
+        assert(!"not reached");
+        break;
+      }
+      break;
+
    default:
       assert(!"not reached");
    }