diff options
author | Kenneth Graunke <[email protected]> | 2019-04-27 00:24:05 -0700 |
---|---|---|
committer | Kenneth Graunke <[email protected]> | 2019-04-27 01:07:14 -0700 |
commit | 6bd4cb920e9c0b431df3ab2f5878b2b24182fd00 (patch) | |
tree | 9700be01ea7c367ddcd99ed71c6cb1e27ebcda7c | |
parent | edb04953c8b8520108f333b1e289f18719a7d597 (diff) |
iris: Fix zeroing of transform feedback offsets in strange cases.
Some of the dEQP.functional.transform_feedback tests end up doing
the following sequence of operations:
1. BeginTransformFeedback
2. PauseTransformFeedback
3. Draw
4. ResumeTransformFeedback
At step 1, we'd pack 3DSTATE_SO_BUFFER commands saying to zero the
SO_WRITE_OFFSET registers. At step 2, we disable streamout, so step 3
doesn't bother emitting those commands. Then, step 4 re-packs new
3DSTATE_SO_BUFFER commands with offset = 0xFFFFFFFF, saying to continue
appending at the existing offset. This loads the value from the BO as
the offsets - but we never actually zeroed it.
So, just maintain a flag saying "we actually emitted the commands",
and stomp offset back to zero until we emit some.
-rw-r--r-- | src/gallium/drivers/iris/iris_context.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/iris/iris_state.c | 19 |
2 files changed, 18 insertions, 4 deletions
diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h index 1153cb84bb9..51bbdb681e7 100644 --- a/src/gallium/drivers/iris/iris_context.h +++ b/src/gallium/drivers/iris/iris_context.h @@ -332,6 +332,9 @@ struct iris_stream_output_target { /** Stride (dwords-per-vertex) during this transform feedback operation */ uint16_t stride; + + /** Has 3DSTATE_SO_BUFFER actually been emitted, zeroing the offsets? */ + bool zeroed; }; /** diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c index 04766716bc0..479703f30fa 100644 --- a/src/gallium/drivers/iris/iris_state.c +++ b/src/gallium/drivers/iris/iris_state.c @@ -2984,20 +2984,30 @@ iris_set_stream_output_targets(struct pipe_context *ctx, for (unsigned i = 0; i < 4; i++, so_buffers += GENX(3DSTATE_SO_BUFFER_length)) { - if (i >= num_targets || !targets[i]) { + struct iris_stream_output_target *tgt = (void *) ice->state.so_target[i]; + unsigned offset = offsets[i]; + + if (!tgt) { iris_pack_command(GENX(3DSTATE_SO_BUFFER), so_buffers, sob) sob.SOBufferIndex = i; continue; } - struct iris_stream_output_target *tgt = (void *) targets[i]; struct iris_resource *res = (void *) tgt->base.buffer; /* Note that offsets[i] will either be 0, causing us to zero * the value in the buffer, or 0xFFFFFFFF, which happens to mean * "continue appending at the existing offset." */ - assert(offsets[i] == 0 || offsets[i] == 0xFFFFFFFF); + assert(offset == 0 || offset == 0xFFFFFFFF); + + /* We might be called by Begin (offset = 0), Pause, then Resume + * (offset = 0xFFFFFFFF) before ever drawing (where these commands + * will actually be sent to the GPU). In this case, we don't want + * to append - we still want to do our initial zeroing. + */ + if (!tgt->zeroed) + offset = 0; iris_pack_command(GENX(3DSTATE_SO_BUFFER), so_buffers, sob) { sob.SurfaceBaseAddress = @@ -3010,7 +3020,7 @@ iris_set_stream_output_targets(struct pipe_context *ctx, sob.SurfaceSize = MAX2(tgt->base.buffer_size / 4, 1) - 1; sob.SOBufferIndex = i; - sob.StreamOffset = offsets[i]; + sob.StreamOffset = offset; sob.StreamOutputBufferOffsetAddress = rw_bo(NULL, iris_resource_bo(tgt->offset.res)->gtt_offset + tgt->offset.offset); @@ -4717,6 +4727,7 @@ iris_upload_dirty_render_state(struct iris_context *ice, struct iris_stream_output_target *tgt = (void *) ice->state.so_target[i]; if (tgt) { + tgt->zeroed = true; iris_use_pinned_bo(batch, iris_resource_bo(tgt->base.buffer), true); iris_use_pinned_bo(batch, iris_resource_bo(tgt->offset.res), |