diff options
Diffstat (limited to 'src/gallium')
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_program.c | 33 | ||||
-rw-r--r-- | src/gallium/drivers/nvc0/nvc0_program.h | 2 | ||||
-rw-r--r-- | 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 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]; |