summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2018-06-15 17:08:29 -0700
committerEric Anholt <[email protected]>2018-06-18 14:54:16 -0700
commite636199c1c7dc9bc0525f5ae2a4eef05a8092180 (patch)
tree485997a7ae5431ecca305a2a1df9b68dcf759a33
parent94178044d5d34e5bf65601d0b5da70d91284ec56 (diff)
v3d: Set the SO offsets correctly if we have to re-emit.
This should fix TF across a glFlush() or TF pause/restart. Fixes dEQP-GLES3.functional.transform_feedback.array.interleaved.lines.highp_float and many, many others.
-rw-r--r--src/gallium/drivers/v3d/v3d_context.h2
-rw-r--r--src/gallium/drivers/v3d/v3d_program.c2
-rw-r--r--src/gallium/drivers/v3d/v3dx_draw.c6
-rw-r--r--src/gallium/drivers/v3d/v3dx_emit.c12
-rw-r--r--src/gallium/drivers/v3d/v3dx_state.c6
5 files changed, 24 insertions, 4 deletions
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);