Mesa (master): nvc0: handle discontiguous outputs in stream_output_info

Christoph Bumiller chrisbmr at kemper.freedesktop.org
Fri Jan 20 18:24:59 UTC 2012


Module: Mesa
Branch: master
Commit: 0d27be3d7982d38d3c26e693be959a9e6b776e5f
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=0d27be3d7982d38d3c26e693be959a9e6b776e5f

Author: Christoph Bumiller <e0425955 at student.tuwien.ac.at>
Date:   Fri Jan 20 13:29:42 2012 +0100

nvc0: handle discontiguous outputs in stream_output_info

---

 src/gallium/drivers/nvc0/nvc0_program.c      |   33 ++++++++++++++-----------
 src/gallium/drivers/nvc0/nvc0_program.h      |    2 +-
 src/gallium/drivers/nvc0/nvc0_shader_state.c |   18 ++++---------
 3 files changed, 25 insertions(+), 28 deletions(-)

diff --git a/src/gallium/drivers/nvc0/nvc0_program.c b/src/gallium/drivers/nvc0/nvc0_program.c
index 60abc22..44c7a65 100644
--- a/src/gallium/drivers/nvc0/nvc0_program.c
+++ b/src/gallium/drivers/nvc0/nvc0_program.c
@@ -492,28 +492,31 @@ nvc0_program_create_tfb_state(const struct nv50_ir_prog_info *info,
                               const struct pipe_stream_output_info *pso)
 {
    struct nvc0_transform_feedback_state *tfb;
-   int n = 0;
-   int i, c, b;
+   unsigned b, i, c;
 
-   tfb = MALLOC(sizeof(*tfb) + pso->num_outputs * 4 * sizeof(uint8_t));
+   tfb = MALLOC_STRUCT(nvc0_transform_feedback_state);
    if (!tfb)
       return NULL;
-
    for (b = 0; b < 4; ++b) {
+      tfb->stride[b] = pso->stride[b] * 4;
       tfb->varying_count[b] = 0;
+   }
+   memset(tfb->varying_index, 0xff, sizeof(tfb->varying_index)); /* = skip */
 
-      for (i = 0; i < pso->num_outputs; ++i) {
-         unsigned startc = pso->output[i].start_component;
-         if (pso->output[i].output_buffer != b)
-            continue;
-         for (c = 0; c < pso->output[i].num_components; ++c) {
-            tfb->varying_count[b]++;
-            tfb->varying_index[n++] =
-               info->out[pso->output[i].register_index].slot[startc + c];
-         }
-      }
-      tfb->stride[b] = pso->stride[b] * 4;
+   for (i = 0; i < pso->num_outputs; ++i) {
+      unsigned s = pso->output[i].start_component;
+      unsigned p = pso->output[i].dst_offset;
+      b = pso->output[i].output_buffer;
+
+      for (c = 0; c < pso->output[i].num_components; ++c)
+         tfb->varying_index[b][p++] =
+            info->out[pso->output[i].register_index].slot[s + c];
+
+      tfb->varying_count[b] = MAX2(tfb->varying_count[b], p);
    }
+   for (b = 0; b < 4; ++b) // zero unused indices (looks nicer)
+      for (c = tfb->varying_count[b]; c & 3; ++c)
+         tfb->varying_index[b][c] = 0;
 
    return tfb;
 }
diff --git a/src/gallium/drivers/nvc0/nvc0_program.h b/src/gallium/drivers/nvc0/nvc0_program.h
index 6eb8c96..c90f364 100644
--- a/src/gallium/drivers/nvc0/nvc0_program.h
+++ b/src/gallium/drivers/nvc0/nvc0_program.h
@@ -10,7 +10,7 @@
 struct nvc0_transform_feedback_state {
    uint32_t stride[4];
    uint8_t varying_count[4];
-   uint8_t varying_index[0];
+   uint8_t varying_index[4][128];
 };
 
 
diff --git a/src/gallium/drivers/nvc0/nvc0_shader_state.c b/src/gallium/drivers/nvc0/nvc0_shader_state.c
index 630ad20..9945b8e 100644
--- a/src/gallium/drivers/nvc0/nvc0_shader_state.c
+++ b/src/gallium/drivers/nvc0/nvc0_shader_state.c
@@ -207,7 +207,7 @@ nvc0_tfb_validate(struct nvc0_context *nvc0)
 {
    struct nouveau_channel *chan = nvc0->screen->base.channel;
    struct nvc0_transform_feedback_state *tfb;
-   unsigned b, n, i;
+   unsigned b;
 
    if (nvc0->gmtyprog) tfb = nvc0->gmtyprog->tfb;
    else
@@ -218,22 +218,16 @@ nvc0_tfb_validate(struct nvc0_context *nvc0)
    IMMED_RING(chan, RING_3D(TFB_ENABLE), (tfb && nvc0->num_tfbbufs) ? 1 : 0);
 
    if (tfb && tfb != nvc0->state.tfb) {
-      uint8_t var[128];
-
-      for (n = 0, b = 0; b < 4; n += tfb->varying_count[b++]) {
+      for (b = 0; b < 4; ++b) {
          if (tfb->varying_count[b]) {
+            unsigned n = (tfb->varying_count[b] + 3) / 4;
+
             BEGIN_RING(chan, RING_3D(TFB_STREAM(b)), 3);
             OUT_RING  (chan, 0);
             OUT_RING  (chan, tfb->varying_count[b]);
             OUT_RING  (chan, tfb->stride[b]);
-
-            for (i = 0; i < tfb->varying_count[b]; ++i)
-               var[i] = tfb->varying_index[n + i];
-            for (; i & 3; ++i)
-               var[i] = 0; /* zero rest of method word bits */
-
-            BEGIN_RING(chan, RING_3D(TFB_VARYING_LOCS(b, 0)), i / 4);
-            OUT_RINGp (chan, var, i / 4);
+            BEGIN_RING(chan, RING_3D(TFB_VARYING_LOCS(b, 0)), n);
+            OUT_RINGp (chan, tfb->varying_index[b], n);
 
             if (nvc0->tfbbuf[b])
                nvc0_so_target(nvc0->tfbbuf[b])->stride = tfb->stride[b];




More information about the mesa-commit mailing list