summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <[email protected]>2018-11-27 09:03:16 +1000
committerKenneth Graunke <[email protected]>2019-02-21 10:26:10 -0800
commit7bbf3ff4a98c861a208e5a19005d35c93507aa39 (patch)
treee1a814e6a67054da6cb9486720867677650d03e6
parentdbe198d6bad2f7162e1dc082da3337278bf79c2d (diff)
iris: add conditional render support
-rw-r--r--src/gallium/drivers/iris/iris_blit.c3
-rw-r--r--src/gallium/drivers/iris/iris_clear.c2
-rw-r--r--src/gallium/drivers/iris/iris_context.h17
-rw-r--r--src/gallium/drivers/iris/iris_query.c98
-rw-r--r--src/gallium/drivers/iris/iris_state.c2
5 files changed, 119 insertions, 3 deletions
diff --git a/src/gallium/drivers/iris/iris_blit.c b/src/gallium/drivers/iris/iris_blit.c
index c50e7958d24..729d8f7b038 100644
--- a/src/gallium/drivers/iris/iris_blit.c
+++ b/src/gallium/drivers/iris/iris_blit.c
@@ -338,7 +338,8 @@ iris_blit(struct pipe_context *ctx, const struct pipe_blit_info *info)
struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
struct blorp_batch blorp_batch;
- blorp_batch_init(&ice->blorp, &blorp_batch, batch, 0);
+ blorp_batch_init(&ice->blorp, &blorp_batch, batch,
+ info->render_condition_enable ? BLORP_BATCH_PREDICATE_ENABLE : 0);
for (int slice = 0; slice < info->dst.box.depth; slice++) {
iris_batch_maybe_flush(batch, 1500);
diff --git a/src/gallium/drivers/iris/iris_clear.c b/src/gallium/drivers/iris/iris_clear.c
index c9c47afcaa6..7f113fa3657 100644
--- a/src/gallium/drivers/iris/iris_clear.c
+++ b/src/gallium/drivers/iris/iris_clear.c
@@ -56,7 +56,7 @@ iris_clear(struct pipe_context *ctx,
iris_batch_maybe_flush(batch, 1500);
struct blorp_batch blorp_batch;
- blorp_batch_init(&ice->blorp, &blorp_batch, batch, 0);
+ blorp_batch_init(&ice->blorp, &blorp_batch, batch, BLORP_BATCH_PREDICATE_ENABLE);
if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
struct pipe_surface *psurf = cso_fb->zsbuf;
diff --git a/src/gallium/drivers/iris/iris_context.h b/src/gallium/drivers/iris/iris_context.h
index 6cb07119efe..91c0c3afcc5 100644
--- a/src/gallium/drivers/iris/iris_context.h
+++ b/src/gallium/drivers/iris/iris_context.h
@@ -211,6 +211,22 @@ enum pipe_control_flags
PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE | \
PIPE_CONTROL_INSTRUCTION_INVALIDATE)
+enum iris_predicate_state {
+ /* The first two states are used if we can determine whether to draw
+ * without having to look at the values in the query object buffer. This
+ * will happen if there is no conditional render in progress, if the query
+ * object is already completed or if something else has already added
+ * samples to the preliminary result.
+ */
+ IRIS_PREDICATE_STATE_RENDER,
+ IRIS_PREDICATE_STATE_DONT_RENDER,
+
+ /* In this case whether to draw or not depends on the result of an
+ * MI_PREDICATE command so the predicate enable bit needs to be checked.
+ */
+ IRIS_PREDICATE_STATE_USE_BIT,
+};
+
/** @} */
/**
@@ -414,6 +430,7 @@ struct iris_context {
struct iris_bo *scratch_bos[1 << 4][MESA_SHADER_STAGES];
} shaders;
+ enum iris_predicate_state predicate;
struct {
uint64_t dirty;
uint64_t dirty_for_nos[IRIS_NOS_COUNT];
diff --git a/src/gallium/drivers/iris/iris_query.c b/src/gallium/drivers/iris/iris_query.c
index 62862927adc..27126d7f7bc 100644
--- a/src/gallium/drivers/iris/iris_query.c
+++ b/src/gallium/drivers/iris/iris_query.c
@@ -724,6 +724,103 @@ iris_set_active_query_state(struct pipe_context *ctx, boolean enable)
IRIS_DIRTY_WM;
}
+static void
+set_predicate_enable(struct iris_context *ice,
+ bool value)
+{
+ if (value)
+ ice->predicate = IRIS_PREDICATE_STATE_RENDER;
+ else
+ ice->predicate = IRIS_PREDICATE_STATE_DONT_RENDER;
+}
+
+static void
+set_predicate_for_overflow(struct iris_context *ice,
+ struct iris_query *q)
+{
+ struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
+ ice->predicate = IRIS_PREDICATE_STATE_USE_BIT;
+
+ /* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM
+ * command when loading the values into the predicate source registers for
+ * conditional rendering.
+ */
+ iris_emit_pipe_control_flush(batch, PIPE_CONTROL_FLUSH_ENABLE);
+
+ overflow_result_to_gpr0(ice, q);
+ ice->vtbl.load_register_reg64(batch, CS_GPR(0), MI_PREDICATE_SRC0);
+ ice->vtbl.load_register_imm64(batch, MI_PREDICATE_SRC1, 0ull);
+}
+
+static void
+set_predicate_for_occlusion(struct iris_context *ice,
+ struct iris_query *q)
+{
+ struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
+ ice->predicate = IRIS_PREDICATE_STATE_USE_BIT;
+
+ /* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM
+ * command when loading the values into the predicate source registers for
+ * conditional rendering.
+ */
+ iris_emit_pipe_control_flush(batch, PIPE_CONTROL_FLUSH_ENABLE);
+
+ ice->vtbl.load_register_mem64(batch, MI_PREDICATE_SRC0, q->bo, offsetof(struct iris_query_snapshots, start));
+ ice->vtbl.load_register_mem64(batch, MI_PREDICATE_SRC1, q->bo, offsetof(struct iris_query_snapshots, end));
+}
+
+static void
+set_predicate_for_result(struct iris_context *ice,
+ struct iris_query *q,
+ bool condition)
+{
+ struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
+ int load_op;
+
+ switch (q->type) {
+ case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
+ case PIPE_QUERY_SO_OVERFLOW_ANY_PREDICATE:
+ set_predicate_for_overflow(ice, q);
+ break;
+ default:
+ set_predicate_for_occlusion(ice, q);
+ break;
+ }
+
+ if (ice->predicate == IRIS_PREDICATE_STATE_USE_BIT) {
+ if (condition)
+ load_op = MI_PREDICATE_LOADOP_LOAD;
+ else
+ load_op = MI_PREDICATE_LOADOP_LOADINV;
+
+ // batch emit
+ uint32_t predicate = MI_PREDICATE | load_op |
+ MI_PREDICATE_COMBINEOP_SET |
+ MI_PREDICATE_COMPAREOP_SRCS_EQUAL;
+ iris_batch_emit(batch, &predicate, sizeof(uint32_t));
+ }
+}
+
+static void
+iris_render_condition(struct pipe_context *ctx,
+ struct pipe_query *query,
+ boolean condition,
+ enum pipe_render_cond_flag mode)
+{
+ struct iris_context *ice = (void *) ctx;
+ struct iris_query *q = (void *) query;
+
+ if (!q) {
+ ice->predicate = IRIS_PREDICATE_STATE_RENDER;
+ return;
+ }
+
+ if (q->result || q->ready)
+ set_predicate_enable(ice, (q->result != 0) ^ condition);
+ else
+ set_predicate_for_result(ice, q, condition);
+}
+
void
iris_init_query_functions(struct pipe_context *ctx)
{
@@ -734,4 +831,5 @@ iris_init_query_functions(struct pipe_context *ctx)
ctx->get_query_result = iris_get_query_result;
ctx->get_query_result_resource = iris_get_query_result_resource;
ctx->set_active_query_state = iris_set_active_query_state;
+ ctx->render_condition = iris_render_condition;
}
diff --git a/src/gallium/drivers/iris/iris_state.c b/src/gallium/drivers/iris/iris_state.c
index ba7c98a6fd2..99073088b00 100644
--- a/src/gallium/drivers/iris/iris_state.c
+++ b/src/gallium/drivers/iris/iris_state.c
@@ -4542,7 +4542,7 @@ iris_upload_render_state(struct iris_context *ice,
prim.InstanceCount = draw->instance_count;
prim.VertexCountPerInstance = draw->count;
prim.VertexAccessType = draw->index_size > 0 ? RANDOM : SEQUENTIAL;
-
+ prim.PredicateEnable = ice->predicate == IRIS_PREDICATE_STATE_USE_BIT ? 1 : 0;
// XXX: this is probably bonkers.
prim.StartVertexLocation = draw->start;