iris: Rework zeroing of stream output buffer offsets
The previous mechanism was a bit fragile. We stored the zero offset in the pre-baked packet, and used an flag to override 0xFFFFFFFF (append) offsets until our first emit - then prohibited anyone from trying to re-emit the packet by flagging IRIS_DIRTY_SO_BUFFERS, because that would re-emit the version with the zeroing of the offset. Now, we always store 0xFFFFFFFF in the pre-baked packet, and use a flag to override it to zero on the first emit. That way, we can re-emit that packet at any time, and it'll just keep appending. Reviewed-by: Zoltán Böszörményi <zboszor@gmail.com> Reviewed-by: Ian Romanick <ian.d.romanick@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8964>
This commit is contained in:
@@ -537,8 +537,8 @@ struct iris_stream_output_target {
|
|||||||
/** Stride (bytes-per-vertex) during this transform feedback operation */
|
/** Stride (bytes-per-vertex) during this transform feedback operation */
|
||||||
uint16_t stride;
|
uint16_t stride;
|
||||||
|
|
||||||
/** Has 3DSTATE_SO_BUFFER actually been emitted, zeroing the offsets? */
|
/** Does the next 3DSTATE_SO_BUFFER need to zero the offsets? */
|
||||||
bool zeroed;
|
bool zero_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -265,11 +265,8 @@ iris_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info,
|
|||||||
if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
|
if (ice->state.predicate == IRIS_PREDICATE_STATE_DONT_RENDER)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* We can't safely re-emit 3DSTATE_SO_BUFFERS because it may zero the
|
|
||||||
* write offsets, changing the behavior.
|
|
||||||
*/
|
|
||||||
if (INTEL_DEBUG & DEBUG_REEMIT) {
|
if (INTEL_DEBUG & DEBUG_REEMIT) {
|
||||||
ice->state.dirty |= IRIS_ALL_DIRTY_FOR_RENDER & ~IRIS_DIRTY_SO_BUFFERS;
|
ice->state.dirty |= IRIS_ALL_DIRTY_FOR_RENDER;
|
||||||
ice->state.stage_dirty |= IRIS_ALL_STAGE_DIRTY_FOR_RENDER;
|
ice->state.stage_dirty |= IRIS_ALL_STAGE_DIRTY_FOR_RENDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3809,13 +3809,18 @@ iris_set_stream_output_targets(struct pipe_context *ctx,
|
|||||||
*/
|
*/
|
||||||
assert(offset == 0 || offset == 0xFFFFFFFF);
|
assert(offset == 0 || offset == 0xFFFFFFFF);
|
||||||
|
|
||||||
/* We might be called by Begin (offset = 0), Pause, then Resume
|
/* When we're first called with an offset of 0, we want the next
|
||||||
* (offset = 0xFFFFFFFF) before ever drawing (where these commands
|
* 3DSTATE_SO_BUFFER packets to reset the offset to the beginning.
|
||||||
* will actually be sent to the GPU). In this case, we don't want
|
* Any further times we emit those packets, we want to use 0xFFFFFFFF
|
||||||
* to append - we still want to do our initial zeroing.
|
* to continue appending from the current offset.
|
||||||
|
*
|
||||||
|
* Note that 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)
|
if (offset == 0)
|
||||||
offset = 0;
|
tgt->zero_offset = true;
|
||||||
|
|
||||||
iris_pack_command(GENX(3DSTATE_SO_BUFFER), so_buffers, sob) {
|
iris_pack_command(GENX(3DSTATE_SO_BUFFER), so_buffers, sob) {
|
||||||
#if GEN_GEN < 12
|
#if GEN_GEN < 12
|
||||||
@@ -3833,10 +3838,10 @@ iris_set_stream_output_targets(struct pipe_context *ctx,
|
|||||||
sob.MOCS = iris_mocs(res->bo, &screen->isl_dev, 0);
|
sob.MOCS = iris_mocs(res->bo, &screen->isl_dev, 0);
|
||||||
|
|
||||||
sob.SurfaceSize = MAX2(tgt->base.buffer_size / 4, 1) - 1;
|
sob.SurfaceSize = MAX2(tgt->base.buffer_size / 4, 1) - 1;
|
||||||
sob.StreamOffset = offset;
|
|
||||||
sob.StreamOutputBufferOffsetAddress =
|
sob.StreamOutputBufferOffsetAddress =
|
||||||
rw_bo(NULL, iris_resource_bo(tgt->offset.res)->gtt_offset +
|
rw_bo(NULL, iris_resource_bo(tgt->offset.res)->gtt_offset +
|
||||||
tgt->offset.offset, IRIS_DOMAIN_OTHER_WRITE);
|
tgt->offset.offset, IRIS_DOMAIN_OTHER_WRITE);
|
||||||
|
sob.StreamOffset = 0xFFFFFFFF; /* not offset, see above */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6000,18 +6005,34 @@ iris_upload_dirty_render_state(struct iris_context *ice,
|
|||||||
|
|
||||||
if (ice->state.streamout_active) {
|
if (ice->state.streamout_active) {
|
||||||
if (dirty & IRIS_DIRTY_SO_BUFFERS) {
|
if (dirty & IRIS_DIRTY_SO_BUFFERS) {
|
||||||
iris_batch_emit(batch, genx->so_buffers,
|
|
||||||
4 * 4 * GENX(3DSTATE_SO_BUFFER_length));
|
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
struct iris_stream_output_target *tgt =
|
struct iris_stream_output_target *tgt =
|
||||||
(void *) ice->state.so_target[i];
|
(void *) ice->state.so_target[i];
|
||||||
|
const uint32_t dwords = GENX(3DSTATE_SO_BUFFER_length);
|
||||||
|
uint32_t *so_buffers = genx->so_buffers + i * dwords;
|
||||||
|
bool zero_offset = false;
|
||||||
|
|
||||||
if (tgt) {
|
if (tgt) {
|
||||||
tgt->zeroed = true;
|
zero_offset = tgt->zero_offset;
|
||||||
iris_use_pinned_bo(batch, iris_resource_bo(tgt->base.buffer),
|
iris_use_pinned_bo(batch, iris_resource_bo(tgt->base.buffer),
|
||||||
true, IRIS_DOMAIN_OTHER_WRITE);
|
true, IRIS_DOMAIN_OTHER_WRITE);
|
||||||
iris_use_pinned_bo(batch, iris_resource_bo(tgt->offset.res),
|
iris_use_pinned_bo(batch, iris_resource_bo(tgt->offset.res),
|
||||||
true, IRIS_DOMAIN_OTHER_WRITE);
|
true, IRIS_DOMAIN_OTHER_WRITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (zero_offset) {
|
||||||
|
/* Skip the last DWord which contains "Stream Offset" of
|
||||||
|
* 0xFFFFFFFF and instead emit a dword of zero directly.
|
||||||
|
*/
|
||||||
|
STATIC_ASSERT(GENX(3DSTATE_SO_BUFFER_StreamOffset_start) ==
|
||||||
|
32 * (dwords - 1));
|
||||||
|
const uint32_t zero = 0;
|
||||||
|
iris_batch_emit(batch, so_buffers, 4 * (dwords - 1));
|
||||||
|
iris_batch_emit(batch, &zero, sizeof(zero));
|
||||||
|
tgt->zero_offset = false;
|
||||||
|
} else {
|
||||||
|
iris_batch_emit(batch, so_buffers, 4 * dwords);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user