summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nvc0
diff options
context:
space:
mode:
authorChristoph Bumiller <[email protected]>2012-01-20 13:29:42 +0100
committerChristoph Bumiller <[email protected]>2012-01-20 19:24:31 +0100
commit0d27be3d7982d38d3c26e693be959a9e6b776e5f (patch)
tree830346916a58bbf7a9fedf951e91fc8da2b627be /src/gallium/drivers/nvc0
parentd540af554adfe302387014c0f46d6ac3aaa75121 (diff)
nvc0: handle discontiguous outputs in stream_output_info
Diffstat (limited to 'src/gallium/drivers/nvc0')
-rw-r--r--src/gallium/drivers/nvc0/nvc0_program.c33
-rw-r--r--src/gallium/drivers/nvc0/nvc0_program.h2
-rw-r--r--src/gallium/drivers/nvc0/nvc0_shader_state.c18
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 60abc224398..44c7a65e3c9 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 6eb8c96d60a..c90f364ab9f 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 630ad20c31d..9945b8e7b1f 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];