Mesa (master): freedreno/a6xx: fix transform feedback resuming

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Jan 5 18:02:42 UTC 2021


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

Author: Danylo Piliaiev <dpiliaiev at igalia.com>
Date:   Thu Dec 31 14:49:12 2020 +0200

freedreno/a6xx: fix transform feedback resuming

Each transform feedback target should have a separate buffer
for an offset from which to resume, instead of just having
one buffer per binding point. Otherwise, if transform feedback
is paused and other tf object is bound - the offset of the
previous tf object would be lost.

Fixes Piglit tests:
 arb_transform_feedback2-change-objects-while-paused
 arb_transform_feedback2-change-objects-while-paused_gles3
 ext_transform_feedback-alignment 4
 ext_transform_feedback-alignment 8
 ext_transform_feedback-alignment 12
 ext_transform_feedback-change-size offset-grow
 ext_transform_feedback-change-size offset-shrink
 ext_transform_feedback-change-size range-grow
 ext_transform_feedback-change-size range-shrink
 ext_transform_feedback-immediate-reuse-uniform-buffer
 ext_transform_feedback-position *

Signed-off-by: Danylo Piliaiev <dpiliaiev at igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8281>

---

 .gitlab-ci/piglit/freedreno-a630-gl.txt           | 22 --------------------
 src/gallium/drivers/freedreno/a6xx/fd6_emit.c     | 22 +++++++++++++-------
 src/gallium/drivers/freedreno/freedreno_context.h | 11 ++++++++++
 src/gallium/drivers/freedreno/freedreno_state.c   | 25 +++++++++++++++--------
 4 files changed, 42 insertions(+), 38 deletions(-)

diff --git a/.gitlab-ci/piglit/freedreno-a630-gl.txt b/.gitlab-ci/piglit/freedreno-a630-gl.txt
index ec097eeea1f..81007b182a4 100644
--- a/.gitlab-ci/piglit/freedreno-a630-gl.txt
+++ b/.gitlab-ci/piglit/freedreno-a630-gl.txt
@@ -3097,8 +3097,6 @@ spec/arb_texture_view/rendering-formats/sample gl_rgba16_snorm as gl_rgba16ui: f
 spec/arb_texture_view/rendering-layers-image/layers rendering of image1darray: fail
 spec/arb_texture_view/rendering-layers-image/layers rendering of imagecubearray: fail
 spec/arb_timer_query/timestamp-get: fail
-spec/arb_transform_feedback2/change objects while paused: fail
-spec/arb_transform_feedback2/change objects while paused (gles3): fail
 spec/arb_transform_feedback3/arb_transform_feedback3-draw_using_invalid_stream_index: skip
 spec/arb_transform_feedback3/arb_transform_feedback3-ext_interleaved_two_bufs_gs: skip
 spec/arb_transform_feedback3/arb_transform_feedback3-ext_interleaved_two_bufs_gs_max: skip
@@ -3968,32 +3966,12 @@ spec/ext_texture_srgb/texwrap formats-s3tc bordercolor-swizzled/gl_compressed_sr
 spec/ext_texture_srgb/texwrap formats-s3tc bordercolor-swizzled/gl_compressed_srgb_alpha_s3tc_dxt5_ext, swizzled, border color only: fail
 spec/ext_texture_srgb/texwrap formats-s3tc bordercolor-swizzled/gl_compressed_srgb_s3tc_dxt1_ext, swizzled, border color only: fail
 spec/ext_transform_feedback2/draw-auto: crash
-spec/ext_transform_feedback/alignment 12: fail
-spec/ext_transform_feedback/alignment 4: fail
-spec/ext_transform_feedback/alignment 8: fail
-spec/ext_transform_feedback/change-size offset-grow: fail
-spec/ext_transform_feedback/change-size offset-shrink: fail
-spec/ext_transform_feedback/change-size range-grow: fail
-spec/ext_transform_feedback/change-size range-shrink: fail
 spec/ext_transform_feedback/geometry-shaders-basic: fail
 spec/ext_transform_feedback/immediate-reuse-index-buffer: fail
-spec/ext_transform_feedback/immediate-reuse-uniform-buffer: fail
 spec/ext_transform_feedback/intervening-read prims_generated: fail
 spec/ext_transform_feedback/intervening-read prims_generated use_gs: fail
 spec/ext_transform_feedback/overflow-edge-cases: fail
 spec/ext_transform_feedback/overflow-edge-cases use_gs: fail
-spec/ext_transform_feedback/position-readback-bufferoffset: fail
-spec/ext_transform_feedback/position-readback-bufferoffset-discard: fail
-spec/ext_transform_feedback/position-readback-bufferrange: fail
-spec/ext_transform_feedback/position-readback-bufferrange-discard: fail
-spec/ext_transform_feedback/position-render-bufferoffset: fail
-spec/ext_transform_feedback/position-render-bufferoffset-discard: fail
-spec/ext_transform_feedback/position-render-bufferrange: fail
-spec/ext_transform_feedback/position-render-bufferrange-discard: fail
-spec/ext_transform_feedback/query-primitives_written-bufferoffset: fail
-spec/ext_transform_feedback/query-primitives_written-bufferoffset-discard: fail
-spec/ext_transform_feedback/query-primitives_written-bufferrange: fail
-spec/ext_transform_feedback/query-primitives_written-bufferrange-discard: fail
 spec/ext_transform_feedback/structs struct-array-elem run: fail
 spec/ext_transform_feedback/structs struct-array-elem run interface: fail
 spec/ext_transform_feedback/tessellation triangle_fan flat_first: fail
diff --git a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
index e9ea494bd1a..1b773295bae 100644
--- a/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
+++ b/src/gallium/drivers/freedreno/a6xx/fd6_emit.c
@@ -732,30 +732,38 @@ fd6_emit_streamout(struct fd_ringbuffer *ring, struct fd6_emit *emit, struct ir3
 	emit->streamout_mask = 0;
 
 	for (unsigned i = 0; i < so->num_targets; i++) {
-		struct pipe_stream_output_target *target = so->targets[i];
+		struct fd_stream_output_target *target = fd_stream_output_target(so->targets[i]);
 
 		if (!target)
 			continue;
 
 		OUT_PKT4(ring, REG_A6XX_VPC_SO_BUFFER_BASE_LO(i), 3);
 		/* VPC_SO[i].BUFFER_BASE_LO: */
-		OUT_RELOC(ring, fd_resource(target->buffer)->bo, target->buffer_offset, 0, 0);
-		OUT_RING(ring, target->buffer_size - target->buffer_offset);
+		OUT_RELOC(ring, fd_resource(target->base.buffer)->bo, 0, 0, 0);
+		OUT_RING(ring, target->base.buffer_size + target->base.buffer_offset);
+
+		struct fd_bo *offset_bo = fd_resource(target->offset_buf)->bo;
 
 		if (so->reset & (1 << i)) {
-			unsigned offset = (so->offsets[i] * info->stride[i] * 4);
+			assert(so->offsets[i] == 0);
+
+			OUT_PKT7(ring, CP_MEM_WRITE, 3);
+			OUT_RELOC(ring, offset_bo, 0, 0, 0);
+			OUT_RING(ring, target->base.buffer_offset);
+
 			OUT_PKT4(ring, REG_A6XX_VPC_SO_BUFFER_OFFSET(i), 1);
-			OUT_RING(ring, offset);
+			OUT_RING(ring, target->base.buffer_offset);
 		} else {
 			OUT_PKT7(ring, CP_MEM_TO_REG, 3);
 			OUT_RING(ring, CP_MEM_TO_REG_0_REG(REG_A6XX_VPC_SO_BUFFER_OFFSET(i)) |
 					CP_MEM_TO_REG_0_SHIFT_BY_2 | CP_MEM_TO_REG_0_UNK31 |
 					CP_MEM_TO_REG_0_CNT(0));
-			OUT_RELOC(ring, control_ptr(fd6_context(ctx), flush_base[i].offset));
+			OUT_RELOC(ring, offset_bo, 0, 0, 0);
 		}
 
+		// After a draw HW would write the new offset to offset_bo
 		OUT_PKT4(ring, REG_A6XX_VPC_SO_FLUSH_BASE_LO(i), 2);
-		OUT_RELOC(ring, control_ptr(fd6_context(ctx), flush_base[i]));
+		OUT_RELOC(ring, offset_bo, 0, 0, 0);
 
 		so->reset &= ~(1 << i);
 
diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h
index 7aed573d10a..214b358f8ab 100644
--- a/src/gallium/drivers/freedreno/freedreno_context.h
+++ b/src/gallium/drivers/freedreno/freedreno_context.h
@@ -87,6 +87,11 @@ struct fd_vertex_stateobj {
 	unsigned num_elements;
 };
 
+struct fd_stream_output_target {
+	struct pipe_stream_output_target base;
+	struct pipe_resource *offset_buf;
+};
+
 struct fd_streamout_stateobj {
 	struct pipe_stream_output_target *targets[PIPE_MAX_SO_BUFFERS];
 	/* Bitmask of stream that should be reset. */
@@ -485,6 +490,12 @@ fd_context(struct pipe_context *pctx)
 	return (struct fd_context *)pctx;
 }
 
+static inline struct fd_stream_output_target *
+fd_stream_output_target(struct pipe_stream_output_target *target)
+{
+	return (struct fd_stream_output_target *)target;
+}
+
 /* mark all state dirty: */
 static inline void
 fd_context_all_dirty(struct fd_context *ctx)
diff --git a/src/gallium/drivers/freedreno/freedreno_state.c b/src/gallium/drivers/freedreno/freedreno_state.c
index 06c86ad97f0..eb5aada190d 100644
--- a/src/gallium/drivers/freedreno/freedreno_state.c
+++ b/src/gallium/drivers/freedreno/freedreno_state.c
@@ -481,32 +481,39 @@ fd_create_stream_output_target(struct pipe_context *pctx,
 		struct pipe_resource *prsc, unsigned buffer_offset,
 		unsigned buffer_size)
 {
-	struct pipe_stream_output_target *target;
+	struct fd_stream_output_target *target;
 	struct fd_resource *rsc = fd_resource(prsc);
 
-	target = CALLOC_STRUCT(pipe_stream_output_target);
+	target = CALLOC_STRUCT(fd_stream_output_target);
 	if (!target)
 		return NULL;
 
-	pipe_reference_init(&target->reference, 1);
-	pipe_resource_reference(&target->buffer, prsc);
+	pipe_reference_init(&target->base.reference, 1);
+	pipe_resource_reference(&target->base.buffer, prsc);
 
-	target->context = pctx;
-	target->buffer_offset = buffer_offset;
-	target->buffer_size = buffer_size;
+	target->base.context = pctx;
+	target->base.buffer_offset = buffer_offset;
+	target->base.buffer_size = buffer_size;
+
+	target->offset_buf = pipe_buffer_create(pctx->screen,
+			PIPE_BIND_CUSTOM, PIPE_USAGE_IMMUTABLE, sizeof(uint32_t));
 
 	assert(rsc->base.target == PIPE_BUFFER);
 	util_range_add(&rsc->base, &rsc->valid_buffer_range,
 		buffer_offset, buffer_offset + buffer_size);
 
-	return target;
+	return &target->base;
 }
 
 static void
 fd_stream_output_target_destroy(struct pipe_context *pctx,
 		struct pipe_stream_output_target *target)
 {
-	pipe_resource_reference(&target->buffer, NULL);
+	struct fd_stream_output_target *cso = fd_stream_output_target(target);
+
+	pipe_resource_reference(&cso->base.buffer, NULL);
+	pipe_resource_reference(&cso->offset_buf, NULL);
+
 	FREE(target);
 }
 



More information about the mesa-commit mailing list