iris: Bracket batch operations which access memory within sync regions.
[mesa.git] / src / gallium / drivers / iris / iris_query.c
index c5ebf6b59bd9a74e0062117733d07569e0f79d08..aaed40e5e08f8c9931d759c50e22687a6f356327 100644 (file)
@@ -33,7 +33,6 @@
 
 #include <stdio.h>
 #include <errno.h>
-#include "perf/gen_perf.h"
 #include "pipe/p_defines.h"
 #include "pipe/p_state.h"
 #include "pipe/p_context.h"
@@ -64,11 +63,14 @@ struct iris_query {
 
    struct iris_state_ref query_state_ref;
    struct iris_query_snapshots *map;
-   struct iris_syncpt *syncpt;
+   struct iris_syncobj *syncobj;
 
    int batch_idx;
 
    struct iris_monitor_object *monitor;
+
+   /* Fence for PIPE_QUERY_GPU_FINISHED. */
+   struct pipe_fence_handle *fence;
 };
 
 struct iris_query_snapshots {
@@ -134,7 +136,7 @@ mark_available(struct iris_context *ice, struct iris_query *q)
    offset += q->query_state_ref.offset;
 
    if (!iris_is_query_pipelined(q)) {
-      ice->vtbl.store_data_imm64(batch, bo, offset, true);
+      batch->screen->vtbl.store_data_imm64(batch, bo, offset, true);
    } else {
       /* Order available *after* the query results. */
       flags |= PIPE_CONTROL_FLUSH_ENABLE;
@@ -203,14 +205,14 @@ write_value(struct iris_context *ice, struct iris_query *q, unsigned offset)
                            offset);
       break;
    case PIPE_QUERY_PRIMITIVES_GENERATED:
-      ice->vtbl.store_register_mem64(batch,
+      batch->screen->vtbl.store_register_mem64(batch,
                                      q->index == 0 ?
                                      GENX(CL_INVOCATION_COUNT_num) :
                                      SO_PRIM_STORAGE_NEEDED(q->index),
                                      bo, offset, false);
       break;
    case PIPE_QUERY_PRIMITIVES_EMITTED:
-      ice->vtbl.store_register_mem64(batch,
+      batch->screen->vtbl.store_register_mem64(batch,
                                      SO_NUM_PRIMS_WRITTEN(q->index),
                                      bo, offset, false);
       break;
@@ -230,7 +232,7 @@ write_value(struct iris_context *ice, struct iris_query *q, unsigned offset)
       };
       const uint32_t reg = index_to_reg[q->index];
 
-      ice->vtbl.store_register_mem64(batch, reg, bo, offset, false);
+      batch->screen->vtbl.store_register_mem64(batch, reg, bo, offset, false);
       break;
    }
    default:
@@ -256,9 +258,9 @@ write_overflow_values(struct iris_context *ice, struct iris_query *q, bool end)
                            stream[s].num_prims[end]);
       int w_idx = offset + offsetof(struct iris_query_so_overflow,
                            stream[s].prim_storage_needed[end]);
-      ice->vtbl.store_register_mem64(batch, SO_NUM_PRIMS_WRITTEN(s),
+      batch->screen->vtbl.store_register_mem64(batch, SO_NUM_PRIMS_WRITTEN(s),
                                      bo, g_idx, false);
-      ice->vtbl.store_register_mem64(batch, SO_PRIM_STORAGE_NEEDED(s),
+      batch->screen->vtbl.store_register_mem64(batch, SO_PRIM_STORAGE_NEEDED(s),
                                      bo, w_idx, false);
    }
 }
@@ -462,8 +464,10 @@ iris_create_batch_query(struct pipe_context *ctx,
    q->type = PIPE_QUERY_DRIVER_SPECIFIC;
    q->index = -1;
    q->monitor = iris_create_monitor_object(ice, num_queries, query_types);
-   if (unlikely(!q->monitor))
+   if (unlikely(!q->monitor)) {
+      free(q);
       return NULL;
+   }
 
    return (struct pipe_query *) q;
 }
@@ -477,7 +481,8 @@ iris_destroy_query(struct pipe_context *ctx, struct pipe_query *p_query)
       iris_destroy_monitor_object(ctx, query->monitor);
       query->monitor = NULL;
    } else {
-      iris_syncpt_reference(screen, &query->syncpt, NULL);
+      iris_syncobj_reference(screen, &query->syncobj, NULL);
+      screen->base.fence_reference(ctx->screen, &query->fence, NULL);
    }
    free(query);
 }
@@ -541,11 +546,16 @@ iris_end_query(struct pipe_context *ctx, struct pipe_query *query)
    if (q->monitor)
       return iris_end_monitor(ctx, q->monitor);
 
+   if (q->type == PIPE_QUERY_GPU_FINISHED) {
+      ctx->flush(ctx, &q->fence, PIPE_FLUSH_DEFERRED);
+      return true;
+   }
+
    struct iris_batch *batch = &ice->batches[q->batch_idx];
 
    if (q->type == PIPE_QUERY_TIMESTAMP) {
       iris_begin_query(ctx, query);
-      iris_batch_reference_signal_syncpt(batch, &q->syncpt);
+      iris_batch_reference_signal_syncobj(batch, &q->syncobj);
       mark_available(ice, q);
       return true;
    }
@@ -563,7 +573,7 @@ iris_end_query(struct pipe_context *ctx, struct pipe_query *query)
                   q->query_state_ref.offset +
                   offsetof(struct iris_query_snapshots, end));
 
-   iris_batch_reference_signal_syncpt(batch, &q->syncpt);
+   iris_batch_reference_signal_syncobj(batch, &q->syncobj);
    mark_available(ice, q);
 
    return true;
@@ -604,14 +614,22 @@ iris_get_query_result(struct pipe_context *ctx,
       return true;
    }
 
+   if (q->type == PIPE_QUERY_GPU_FINISHED) {
+      struct pipe_screen *screen = ctx->screen;
+
+      result->b = screen->fence_finish(screen, ctx, q->fence,
+                                       wait ? PIPE_TIMEOUT_INFINITE : 0);
+      return result->b;
+   }
+
    if (!q->ready) {
       struct iris_batch *batch = &ice->batches[q->batch_idx];
-      if (q->syncpt == iris_batch_get_signal_syncpt(batch))
+      if (q->syncobj == iris_batch_get_signal_syncobj(batch))
          iris_batch_flush(batch);
 
       while (!READ_ONCE(q->map->snapshots_landed)) {
          if (wait)
-            iris_wait_syncpt(ctx->screen, q->syncpt, INT64_MAX);
+            iris_wait_syncobj(ctx->screen, q->syncobj, INT64_MAX);
          else
             return false;
       }
@@ -654,10 +672,10 @@ iris_get_query_result_resource(struct pipe_context *ctx,
        * now so that progress happens.  Either way, copy the snapshots
        * landed field to the destination resource.
        */
-      if (q->syncpt == iris_batch_get_signal_syncpt(batch))
+      if (q->syncobj == iris_batch_get_signal_syncobj(batch))
          iris_batch_flush(batch);
 
-      ice->vtbl.copy_mem_mem(batch, dst_bo, offset,
+      batch->screen->vtbl.copy_mem_mem(batch, dst_bo, offset,
                              query_bo, snapshots_landed_offset,
                              result_type <= PIPE_QUERY_TYPE_U32 ? 4 : 8);
       return;
@@ -673,9 +691,9 @@ iris_get_query_result_resource(struct pipe_context *ctx,
    if (q->ready) {
       /* We happen to have the result on the CPU, so just copy it. */
       if (result_type <= PIPE_QUERY_TYPE_U32) {
-         ice->vtbl.store_data_imm32(batch, dst_bo, offset, q->result);
+         batch->screen->vtbl.store_data_imm32(batch, dst_bo, offset, q->result);
       } else {
-         ice->vtbl.store_data_imm64(batch, dst_bo, offset, q->result);
+         batch->screen->vtbl.store_data_imm64(batch, dst_bo, offset, q->result);
       }
 
       /* Make sure the result lands before they use bind the QBO elsewhere
@@ -693,6 +711,8 @@ iris_get_query_result_resource(struct pipe_context *ctx,
    struct gen_mi_builder b;
    gen_mi_builder_init(&b, batch);
 
+   iris_batch_sync_region_start(batch);
+
    struct gen_mi_value result = calculate_result_on_gpu(devinfo, &b, q);
    struct gen_mi_value dst =
       result_type <= PIPE_QUERY_TYPE_U32 ? gen_mi_mem32(rw_bo(dst_bo, offset))
@@ -705,6 +725,8 @@ iris_get_query_result_resource(struct pipe_context *ctx,
    } else {
       gen_mi_store(&b, dst, result);
    }
+
+   iris_batch_sync_region_end(batch);
 }
 
 static void
@@ -719,13 +741,13 @@ iris_set_active_query_state(struct pipe_context *ctx, bool enable)
    // have to be done dynamically at draw time, which is a pain
    ice->state.statistics_counters_enabled = enable;
    ice->state.dirty |= IRIS_DIRTY_CLIP |
-                       IRIS_DIRTY_GS |
                        IRIS_DIRTY_RASTER |
                        IRIS_DIRTY_STREAMOUT |
-                       IRIS_DIRTY_TCS |
-                       IRIS_DIRTY_TES |
-                       IRIS_DIRTY_VS |
                        IRIS_DIRTY_WM;
+   ice->state.stage_dirty |= IRIS_STAGE_DIRTY_GS |
+                             IRIS_STAGE_DIRTY_TCS |
+                             IRIS_STAGE_DIRTY_TES |
+                             IRIS_STAGE_DIRTY_VS;
 }
 
 static void
@@ -745,6 +767,8 @@ set_predicate_for_result(struct iris_context *ice,
    struct iris_batch *batch = &ice->batches[IRIS_BATCH_RENDER];
    struct iris_bo *bo = iris_resource_bo(q->query_state_ref.res);
 
+   iris_batch_sync_region_start(batch);
+
    /* The CPU doesn't have the query result yet; use hardware predication */
    ice->state.predicate = IRIS_PREDICATE_STATE_USE_BIT;
 
@@ -791,6 +815,8 @@ set_predicate_for_result(struct iris_context *ice,
    gen_mi_store(&b, query_mem64(q, offsetof(struct iris_query_snapshots,
                                             predicate_result)), result);
    ice->state.compute_predicate = bo;
+
+   iris_batch_sync_region_end(batch);
 }
 
 static void
@@ -847,6 +873,7 @@ void
 genX(init_query)(struct iris_context *ice)
 {
    struct pipe_context *ctx = &ice->ctx;
+   struct iris_screen *screen = (struct iris_screen *)ctx->screen;
 
    ctx->create_query = iris_create_query;
    ctx->create_batch_query = iris_create_batch_query;
@@ -858,5 +885,5 @@ genX(init_query)(struct iris_context *ice)
    ctx->set_active_query_state = iris_set_active_query_state;
    ctx->render_condition = iris_render_condition;
 
-   ice->vtbl.resolve_conditional_render = iris_resolve_conditional_render;
+   screen->vtbl.resolve_conditional_render = iris_resolve_conditional_render;
 }