i965/vs: Unify URB entry size/read length calculations between backends.
authorKenneth Graunke <kenneth@whitecape.org>
Tue, 25 Aug 2015 23:59:12 +0000 (16:59 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Sat, 10 Oct 2015 18:40:19 +0000 (11:40 -0700)
Both the vec4 and scalar VS backends had virtually identical URB entry
size and read length calculations.  We can move those up a level to
backend-agnostic code and reuse it for both.

Unfortunately, the backends need to know nr_attributes to compute
first_non_payload_grf, so I had to store that in prog_data.  We could
use urb_read_length, but that's nr_attributes rounded up to a multiple
of two, so doing so would waste a register in some cases.

There's more code to be removed in the vec4 backend, but that will
come in a follow-on patch.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
src/mesa/drivers/dri/i965/brw_context.h
src/mesa/drivers/dri/i965/brw_fs.cpp
src/mesa/drivers/dri/i965/brw_vec4.cpp
src/mesa/drivers/dri/i965/brw_vs.c

index aa1284db3ce5bab9772c5f683c26ba97032faf85..9ad6b4d90cfefad5342d68d80957ad03b3fa0b0e 100644 (file)
@@ -699,6 +699,8 @@ struct brw_vs_prog_data {
 
    GLbitfield64 inputs_read;
 
+   unsigned nr_attributes;
+
    bool uses_vertexid;
    bool uses_instanceid;
 };
index ba62fdd4b86c6775be0d11115cdb1965dcf53d9e..65f2e68e62101060668e8f3560c2770c4289a3e7 100644 (file)
@@ -1508,21 +1508,12 @@ void
 fs_visitor::assign_vs_urb_setup()
 {
    brw_vs_prog_data *vs_prog_data = (brw_vs_prog_data *) prog_data;
-   int grf, count, slot, channel, attr;
+   int grf, slot, channel, attr;
 
    assert(stage == MESA_SHADER_VERTEX);
-   count = _mesa_bitcount_64(vs_prog_data->inputs_read);
-   if (vs_prog_data->uses_vertexid || vs_prog_data->uses_instanceid)
-      count++;
 
    /* Each attribute is 4 regs. */
-   this->first_non_payload_grf += count * 4;
-
-   unsigned vue_entries =
-      MAX2(count, vs_prog_data->base.vue_map.num_slots);
-
-   vs_prog_data->base.urb_entry_size = ALIGN(vue_entries, 4) / 4;
-   vs_prog_data->base.urb_read_length = (count + 1) / 2;
+   this->first_non_payload_grf += 4 * vs_prog_data->nr_attributes;
 
    assert(vs_prog_data->base.urb_read_length <= 15);
 
@@ -1532,7 +1523,7 @@ fs_visitor::assign_vs_urb_setup()
          if (inst->src[i].file == ATTR) {
 
             if (inst->src[i].reg == VERT_ATTRIB_MAX) {
-               slot = count - 1;
+               slot = vs_prog_data->nr_attributes - 1;
             } else {
                /* Attributes come in in a contiguous block, ordered by their
                 * gl_vert_attrib value.  That means we can compute the slot
index e966b96a5ca6153221ec69bfd59c80cebb30e8ba..08f3e9188ed000a08e1161c968b3f73ed8741a9a 100644 (file)
@@ -1632,28 +1632,11 @@ vec4_vs_visitor::setup_attributes(int payload_reg)
     */
    if (vs_prog_data->uses_vertexid || vs_prog_data->uses_instanceid) {
       attribute_map[VERT_ATTRIB_MAX] = payload_reg + nr_attributes;
-      nr_attributes++;
    }
 
    lower_attributes_to_hw_regs(attribute_map, false /* interleaved */);
 
-   /* The BSpec says we always have to read at least one thing from
-    * the VF, and it appears that the hardware wedges otherwise.
-    */
-   if (nr_attributes == 0)
-      nr_attributes = 1;
-
-   prog_data->urb_read_length = (nr_attributes + 1) / 2;
-
-   unsigned vue_entries =
-      MAX2(nr_attributes, prog_data->vue_map.num_slots);
-
-   if (devinfo->gen == 6)
-      prog_data->urb_entry_size = ALIGN(vue_entries, 8) / 8;
-   else
-      prog_data->urb_entry_size = ALIGN(vue_entries, 4) / 4;
-
-   return payload_reg + nr_attributes;
+   return payload_reg + vs_prog_data->nr_attributes;
 }
 
 int
index 38de98fab869406612aee7b2ae0174bee92d3ba9..17d3bc495800b41e84bc1cd3153a9691dffa521d 100644 (file)
@@ -159,6 +159,38 @@ brw_codegen_vs_prog(struct brw_context *brw,
                        &prog_data.base.vue_map, outputs_written,
                        prog ? prog->SeparateShader : false);
 
+   unsigned nr_attributes = _mesa_bitcount_64(prog_data.inputs_read);
+
+   /* gl_VertexID and gl_InstanceID are system values, but arrive via an
+    * incoming vertex attribute.  So, add an extra slot.
+    */
+   if (vp->program.Base.SystemValuesRead &
+       (BITFIELD64_BIT(SYSTEM_VALUE_VERTEX_ID_ZERO_BASE) |
+        BITFIELD64_BIT(SYSTEM_VALUE_INSTANCE_ID))) {
+      nr_attributes++;
+   }
+
+   /* The BSpec says we always have to read at least one thing from the VF,
+    * and it appears that the hardware wedges otherwise.
+    */
+   if (nr_attributes == 0 && !brw->intelScreen->compiler->scalar_vs)
+      nr_attributes = 1;
+
+   prog_data.nr_attributes = nr_attributes;
+   prog_data.base.urb_read_length = DIV_ROUND_UP(nr_attributes, 2);
+
+   /* Since vertex shaders reuse the same VUE entry for inputs and outputs
+    * (overwriting the original contents), we need to make sure the size is
+    * the larger of the two.
+    */
+   const unsigned vue_entries =
+      MAX2(nr_attributes, prog_data.base.vue_map.num_slots);
+
+   if (brw->gen == 6)
+      prog_data.base.urb_entry_size = DIV_ROUND_UP(vue_entries, 8);
+   else
+      prog_data.base.urb_entry_size = DIV_ROUND_UP(vue_entries, 4);
+
    if (0) {
       _mesa_fprint_program_opt(stderr, &vp->program.Base, PROG_PRINT_DEBUG,
                               true);