From 4151d843236ab350a70d8e13e4e7c79d11ec7bb6 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Thu, 5 Dec 2019 14:49:12 +0200 Subject: [PATCH] iris: add support INTEL_blackhole_render v2: Use a software mechanism to manage blackhole state v3: s/iris_batchbuffer/iris_batch/ (Ken) v4: Fixup state transition mistake (Ken/Lionel) v5: Cleanup iris_batch_flush (Ken) Signed-off-by: Lionel Landwerlin Reviewed-by: Kenneth Graunke Tested-by: Marge Bot Part-of: --- src/gallium/drivers/iris/iris_batch.c | 43 ++++++++++++++++++++++++++ src/gallium/drivers/iris/iris_batch.h | 9 ++++++ src/gallium/drivers/iris/iris_screen.c | 3 ++ src/gallium/drivers/iris/iris_state.c | 14 +++++++++ 4 files changed, 69 insertions(+) diff --git a/src/gallium/drivers/iris/iris_batch.c b/src/gallium/drivers/iris/iris_batch.c index 120aaf9cbd9..ecc81b9c933 100644 --- a/src/gallium/drivers/iris/iris_batch.c +++ b/src/gallium/drivers/iris/iris_batch.c @@ -363,6 +363,24 @@ create_batch(struct iris_batch *batch) iris_use_pinned_bo(batch, batch->bo, false); } +static void +iris_batch_maybe_noop(struct iris_batch *batch) +{ + /* We only insert the NOOP at the beginning of the batch. */ + assert(iris_batch_bytes_used(batch) == 0); + + if (batch->noop_enabled) { + /* Emit MI_BATCH_BUFFER_END to prevent any further command to be + * executed. + */ + uint32_t *map = batch->map_next; + + map[0] = (0xA << 23); + + batch->map_next += 4; + } +} + static void iris_batch_reset(struct iris_batch *batch) { @@ -382,6 +400,8 @@ iris_batch_reset(struct iris_batch *batch) iris_syncpt_reference(screen, &syncpt, NULL); iris_cache_sets_clear(batch); + + iris_batch_maybe_noop(batch); } void @@ -725,3 +745,26 @@ iris_batch_references(struct iris_batch *batch, struct iris_bo *bo) { return find_validation_entry(batch, bo) != NULL; } + +/** + * Updates the state of the noop feature. + */ +uint64_t +iris_batch_prepare_noop(struct iris_batch *batch, bool noop_enable, uint64_t dirty_flags) +{ + if (batch->noop_enabled == noop_enable) + return 0; + + batch->noop_enabled = noop_enable; + + iris_batch_flush(batch); + + /* If the batch was empty, flush had no effect, so insert our noop. */ + if (iris_batch_bytes_used(batch) == 0) + iris_batch_maybe_noop(batch); + + /* We only need to update the entire state if we transition from noop -> + * not-noop. + */ + return !batch->noop_enabled ? dirty_flags : 0; +} diff --git a/src/gallium/drivers/iris/iris_batch.h b/src/gallium/drivers/iris/iris_batch.h index 42c0f3e787a..d8399d3cd34 100644 --- a/src/gallium/drivers/iris/iris_batch.h +++ b/src/gallium/drivers/iris/iris_batch.h @@ -85,6 +85,11 @@ struct iris_batch { int exec_count; int exec_array_size; + /** Whether INTEL_BLACKHOLE_RENDER is enabled in the batch (aka first + * instruction is a MI_BATCH_BUFFER_END). + */ + bool noop_enabled; + /** * A list of iris_syncpts associated with this batch. * @@ -149,6 +154,10 @@ void _iris_batch_flush(struct iris_batch *batch, const char *file, int line); bool iris_batch_references(struct iris_batch *batch, struct iris_bo *bo); +uint64_t iris_batch_prepare_noop(struct iris_batch *batch, + bool noop_enable, + uint64_t dirty_flags); + #define RELOC_WRITE EXEC_OBJECT_WRITE void iris_use_pinned_bo(struct iris_batch *batch, struct iris_bo *bo, diff --git a/src/gallium/drivers/iris/iris_screen.c b/src/gallium/drivers/iris/iris_screen.c index fd7f5f70165..561d9146aad 100644 --- a/src/gallium/drivers/iris/iris_screen.c +++ b/src/gallium/drivers/iris/iris_screen.c @@ -315,6 +315,9 @@ iris_get_param(struct pipe_screen *pscreen, enum pipe_cap param) PIPE_CONTEXT_PRIORITY_MEDIUM | PIPE_CONTEXT_PRIORITY_HIGH; + case PIPE_CAP_FRONTEND_NOOP: + return true; + // XXX: don't hardcode 00:00:02.0 PCI here case PIPE_CAP_PCI_GROUP: return 0; diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c index db4568c7777..d0e46486756 100644 --- a/src/gallium/drivers/iris/iris_state.c +++ b/src/gallium/drivers/iris/iris_state.c @@ -7415,6 +7415,19 @@ genX(emit_hashing_mode)(struct iris_context *ice, struct iris_batch *batch, #endif } +static void +iris_set_frontend_noop(struct pipe_context *ctx, bool enable) +{ + struct iris_context *ice = (struct iris_context *) ctx; + + ice->state.dirty |= iris_batch_prepare_noop(&ice->batches[IRIS_BATCH_RENDER], + enable, + IRIS_ALL_DIRTY_FOR_RENDER); + ice->state.dirty |= iris_batch_prepare_noop(&ice->batches[IRIS_BATCH_COMPUTE], + enable, + IRIS_ALL_DIRTY_FOR_COMPUTE); +} + void genX(init_state)(struct iris_context *ice) { @@ -7459,6 +7472,7 @@ genX(init_state)(struct iris_context *ice) ctx->create_stream_output_target = iris_create_stream_output_target; ctx->stream_output_target_destroy = iris_stream_output_target_destroy; ctx->set_stream_output_targets = iris_set_stream_output_targets; + ctx->set_frontend_noop = iris_set_frontend_noop; ice->vtbl.destroy_state = iris_destroy_state; ice->vtbl.init_render_context = iris_init_render_context; -- 2.30.2