diff --git a/src/gallium/drivers/v3d/v3d_context.h b/src/gallium/drivers/v3d/v3d_context.h index c0de05d3630..7c920dbc3db 100644 --- a/src/gallium/drivers/v3d/v3d_context.h +++ b/src/gallium/drivers/v3d/v3d_context.h @@ -189,6 +189,8 @@ struct v3d_vertex_stateobj { struct v3d_streamout_stateobj { struct pipe_stream_output_target *targets[PIPE_MAX_SO_BUFFERS]; + /* Number of vertices we've written into the buffer so far. */ + uint32_t offsets[PIPE_MAX_SO_BUFFERS]; unsigned num_targets; }; diff --git a/src/gallium/drivers/v3d/v3d_program.c b/src/gallium/drivers/v3d/v3d_program.c index 036f7c6e672..ef7dd375bf7 100644 --- a/src/gallium/drivers/v3d/v3d_program.c +++ b/src/gallium/drivers/v3d/v3d_program.c @@ -152,6 +152,8 @@ v3d_set_transform_feedback_outputs(struct v3d_uncompiled_shader *so, vpm_start_offset += write_size; vpm_size -= write_size; } + so->base.stream_output.stride[buffer] = + stream_output->stride[buffer]; } so->num_tf_outputs = slot_count; diff --git a/src/gallium/drivers/v3d/v3dx_draw.c b/src/gallium/drivers/v3d/v3dx_draw.c index 17719738056..eb3afaa026d 100644 --- a/src/gallium/drivers/v3d/v3dx_draw.c +++ b/src/gallium/drivers/v3d/v3dx_draw.c @@ -557,6 +557,12 @@ v3d_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) } job->draw_calls_queued++; + /* Increment the TF offsets by how many verts we wrote. XXX: This + * needs some clamping to the buffer size. + */ + for (int i = 0; i < v3d->streamout.num_targets; i++) + v3d->streamout.offsets[i] += info->count; + if (v3d->zsa && job->zsbuf && (v3d->zsa->base.depth.enabled || v3d->zsa->base.stencil[0].enabled)) { diff --git a/src/gallium/drivers/v3d/v3dx_emit.c b/src/gallium/drivers/v3d/v3dx_emit.c index 344f9e464f2..e0bb95efb21 100644 --- a/src/gallium/drivers/v3d/v3dx_emit.c +++ b/src/gallium/drivers/v3d/v3dx_emit.c @@ -694,6 +694,10 @@ v3dX(emit_state)(struct pipe_context *pctx) so->targets[i]; struct v3d_resource *rsc = target ? v3d_resource(target->buffer) : NULL; + struct pipe_shader_state *vs = &v3d->prog.bind_vs->base; + struct pipe_stream_output_info *info = &vs->stream_output; + uint32_t offset = (v3d->streamout.offsets[i] * + info->stride[i] * 4); #if V3D_VERSION >= 40 if (!target) @@ -702,9 +706,10 @@ v3dX(emit_state)(struct pipe_context *pctx) cl_emit(&job->bcl, TRANSFORM_FEEDBACK_BUFFER, output) { output.buffer_address = cl_address(rsc->bo, - target->buffer_offset); + target->buffer_offset + + offset); output.buffer_size_in_32_bit_words = - target->buffer_size >> 2; + (target->buffer_size - offset) >> 2; output.buffer_number = i; } #else /* V3D_VERSION < 40 */ @@ -712,7 +717,8 @@ v3dX(emit_state)(struct pipe_context *pctx) if (target) { output.address = cl_address(rsc->bo, - target->buffer_offset); + target->buffer_offset + + offset); } }; #endif /* V3D_VERSION < 40 */ diff --git a/src/gallium/drivers/v3d/v3dx_state.c b/src/gallium/drivers/v3d/v3dx_state.c index ec6e8ebfef9..70c596855f9 100644 --- a/src/gallium/drivers/v3d/v3dx_state.c +++ b/src/gallium/drivers/v3d/v3dx_state.c @@ -902,8 +902,12 @@ v3d_set_stream_output_targets(struct pipe_context *pctx, assert(num_targets <= ARRAY_SIZE(so->targets)); - for (i = 0; i < num_targets; i++) + for (i = 0; i < num_targets; i++) { + if (offsets[i] != -1) + so->offsets[i] = offsets[i]; + pipe_so_target_reference(&so->targets[i], targets[i]); + } for (; i < so->num_targets; i++) pipe_so_target_reference(&so->targets[i], NULL);