ilo: hook up pipe context 3D functions
authorChia-I Wu <olvaffe@gmail.com>
Tue, 16 Apr 2013 08:36:03 +0000 (16:36 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Fri, 26 Apr 2013 08:16:43 +0000 (16:16 +0800)
src/gallium/drivers/ilo/ilo_3d.c
src/gallium/drivers/ilo/ilo_3d.h
src/gallium/drivers/ilo/ilo_context.c
src/gallium/drivers/ilo/ilo_context.h

index afe6323300ff20be9908dd13c72928fbb6c2a574..9d01c92def7df46169ad92359053aaee6c12cb15 100644 (file)
  *    Chia-I Wu <olv@lunarg.com>
  */
 
+#include "intel_winsys.h"
+
+#include "ilo_3d_pipeline.h"
 #include "ilo_context.h"
+#include "ilo_cp.h"
+#include "ilo_query.h"
+#include "ilo_shader.h"
+#include "ilo_state.h"
 #include "ilo_3d.h"
 
+/**
+ * Hook for CP new-batch.
+ */
+void
+ilo_3d_new_cp_batch(struct ilo_3d *hw3d)
+{
+   hw3d->new_batch = true;
+
+   /* invalidate the pipeline */
+   ilo_3d_pipeline_invalidate(hw3d->pipeline,
+         ILO_3D_PIPELINE_INVALIDATE_BATCH_BO |
+         ILO_3D_PIPELINE_INVALIDATE_STATE_BO);
+   if (!hw3d->cp->hw_ctx) {
+      ilo_3d_pipeline_invalidate(hw3d->pipeline,
+            ILO_3D_PIPELINE_INVALIDATE_HW);
+   }
+}
+
+/**
+ * Hook for CP pre-flush.
+ */
+void
+ilo_3d_pre_cp_flush(struct ilo_3d *hw3d)
+{
+}
+
+/**
+ * Hook for CP post-flush
+ */
+void
+ilo_3d_post_cp_flush(struct ilo_3d *hw3d)
+{
+   if (ilo_debug & ILO_DEBUG_3D)
+      ilo_3d_pipeline_dump(hw3d->pipeline);
+}
+
+/**
+ * Create a 3D context.
+ */
+struct ilo_3d *
+ilo_3d_create(struct ilo_cp *cp, int gen, int gt)
+{
+   struct ilo_3d *hw3d;
+
+   hw3d = CALLOC_STRUCT(ilo_3d);
+   if (!hw3d)
+      return NULL;
+
+   hw3d->cp = cp;
+   hw3d->new_batch = true;
+
+   hw3d->pipeline = ilo_3d_pipeline_create(cp, gen, gt);
+   if (!hw3d->pipeline) {
+      FREE(hw3d);
+      return NULL;
+   }
+
+   return hw3d;
+}
+
+/**
+ * Destroy a 3D context.
+ */
+void
+ilo_3d_destroy(struct ilo_3d *hw3d)
+{
+   ilo_3d_pipeline_destroy(hw3d->pipeline);
+   FREE(hw3d);
+}
+
+static bool
+draw_vbo(struct ilo_3d *hw3d, const struct ilo_context *ilo,
+         const struct pipe_draw_info *info,
+         int *prim_generated, int *prim_emitted)
+{
+   bool need_flush;
+   int max_len;
+
+   ilo_cp_set_ring(hw3d->cp, ILO_CP_RING_RENDER);
+
+   /*
+    * Without a better tracking mechanism, when the framebuffer changes, we
+    * have to assume that the old framebuffer may be sampled from.  If that
+    * happens in the middle of a batch buffer, we need to insert manual
+    * flushes.
+    */
+   need_flush = (!hw3d->new_batch && (ilo->dirty & ILO_DIRTY_FRAMEBUFFER));
+
+   /* make sure there is enough room first */
+   max_len = ilo_3d_pipeline_estimate_size(hw3d->pipeline,
+         ILO_3D_PIPELINE_DRAW, ilo);
+   if (need_flush) {
+      max_len += ilo_3d_pipeline_estimate_size(hw3d->pipeline,
+            ILO_3D_PIPELINE_FLUSH, NULL);
+   }
+
+   if (max_len > ilo_cp_space(hw3d->cp)) {
+      ilo_cp_flush(hw3d->cp);
+      need_flush = false;
+      assert(max_len <= ilo_cp_space(hw3d->cp));
+   }
+
+   if (need_flush)
+      ilo_3d_pipeline_emit_flush(hw3d->pipeline);
+
+   return ilo_3d_pipeline_emit_draw(hw3d->pipeline, ilo, info,
+         prim_generated, prim_emitted);
+}
+
+static bool
+pass_render_condition(struct ilo_3d *hw3d, struct pipe_context *pipe)
+{
+   uint64_t result;
+   bool wait;
+
+   if (!hw3d->render_condition.query)
+      return true;
+
+   switch (hw3d->render_condition.mode) {
+   case PIPE_RENDER_COND_WAIT:
+   case PIPE_RENDER_COND_BY_REGION_WAIT:
+      wait = true;
+      break;
+   case PIPE_RENDER_COND_NO_WAIT:
+   case PIPE_RENDER_COND_BY_REGION_NO_WAIT:
+   default:
+      wait = false;
+      break;
+   }
+
+   if (pipe->get_query_result(pipe, hw3d->render_condition.query,
+            wait, (union pipe_query_result *) &result)) {
+      return (result > 0);
+   }
+   else {
+      return true;
+   }
+}
+
+static void
+ilo_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
+{
+   struct ilo_context *ilo = ilo_context(pipe);
+   struct ilo_3d *hw3d = ilo->hw3d;
+   int prim_generated, prim_emitted;
+
+   if (!pass_render_condition(hw3d, pipe))
+      return;
+
+   /* assume the cache is still in use by the previous batch */
+   if (hw3d->new_batch)
+      ilo_shader_cache_mark_busy(ilo->shader_cache);
+
+   ilo_finalize_states(ilo);
+
+   /* the shaders may be uploaded to a new shader cache */
+   if (hw3d->shader_cache_seqno != ilo->shader_cache->seqno) {
+      ilo_3d_pipeline_invalidate(hw3d->pipeline,
+            ILO_3D_PIPELINE_INVALIDATE_KERNEL_BO);
+   }
+
+   /*
+    * The VBs and/or IB may have different BOs due to being mapped with
+    * PIPE_TRANSFER_DISCARD_x.  We should track that instead of setting the
+    * dirty flags for the performance reason.
+    */
+   ilo->dirty |= ILO_DIRTY_VERTEX_BUFFERS | ILO_DIRTY_INDEX_BUFFER;
+
+   if (!draw_vbo(hw3d, ilo, info, &prim_generated, &prim_emitted))
+      return;
+
+   /* clear dirty status */
+   ilo->dirty = 0x0;
+   hw3d->new_batch = false;
+   hw3d->shader_cache_seqno = ilo->shader_cache->seqno;
+
+   if (ilo_debug & ILO_DEBUG_NOCACHE)
+      ilo_3d_pipeline_emit_flush(hw3d->pipeline);
+}
+
+static void
+ilo_render_condition(struct pipe_context *pipe,
+                     struct pipe_query *query,
+                     uint mode)
+{
+   struct ilo_context *ilo = ilo_context(pipe);
+   struct ilo_3d *hw3d = ilo->hw3d;
+
+   /* reference count? */
+   hw3d->render_condition.query = query;
+   hw3d->render_condition.mode = mode;
+}
+
+static void
+ilo_texture_barrier(struct pipe_context *pipe)
+{
+   struct ilo_context *ilo = ilo_context(pipe);
+   struct ilo_3d *hw3d = ilo->hw3d;
+
+   if (ilo->cp->ring != ILO_CP_RING_RENDER)
+      return;
+
+   ilo_3d_pipeline_emit_flush(hw3d->pipeline);
+
+   /* don't know why */
+   if (ilo->gen >= ILO_GEN(7))
+      ilo_cp_flush(hw3d->cp);
+}
+
+static void
+ilo_get_sample_position(struct pipe_context *pipe,
+                        unsigned sample_count,
+                        unsigned sample_index,
+                        float *out_value)
+{
+   struct ilo_context *ilo = ilo_context(pipe);
+   struct ilo_3d *hw3d = ilo->hw3d;
+
+   ilo_3d_pipeline_get_sample_position(hw3d->pipeline,
+         sample_count, sample_index,
+         &out_value[0], &out_value[1]);
+}
+
 /**
  * Initialize 3D-related functions.
  */
 void
 ilo_init_3d_functions(struct ilo_context *ilo)
 {
-   ilo->base.draw_vbo = NULL;
-   ilo->base.render_condition = NULL;
-   ilo->base.texture_barrier = NULL;
-   ilo->base.get_sample_position = NULL;
+   ilo->base.draw_vbo = ilo_draw_vbo;
+   ilo->base.render_condition = ilo_render_condition;
+   ilo->base.texture_barrier = ilo_texture_barrier;
+   ilo->base.get_sample_position = ilo_get_sample_position;
 }
index ba098cb451cc1e774bbbf7c09e7d9b11733d0ca8..c9b7bc9ea858b052763e8dff27f8e27397385b74 100644 (file)
 
 #include "ilo_common.h"
 
+struct ilo_3d_pipeline;
 struct ilo_context;
+struct ilo_cp;
+struct ilo_query;
+
+/**
+ * 3D context.
+ */
+struct ilo_3d {
+   struct ilo_cp *cp;
+
+   bool new_batch;
+   uint32_t shader_cache_seqno;
+
+   struct {
+      struct pipe_query *query;
+      unsigned mode;
+   } render_condition;
+
+   struct ilo_3d_pipeline *pipeline;
+};
+
+struct ilo_3d *
+ilo_3d_create(struct ilo_cp *cp, int gen, int gt);
+
+void
+ilo_3d_destroy(struct ilo_3d *hw3d);
+
+void
+ilo_3d_new_cp_batch(struct ilo_3d *hw3d);
+
+void
+ilo_3d_pre_cp_flush(struct ilo_3d *hw3d);
+
+void
+ilo_3d_post_cp_flush(struct ilo_3d *hw3d);
 
 void
 ilo_init_3d_functions(struct ilo_context *ilo);
index 82da56e71968b9302ab3ac7c75e16469fa996a8d..880c9c1a7ba6657e4f523efb1f051c9519fd5e67 100644 (file)
 static void
 ilo_context_new_cp_batch(struct ilo_cp *cp, void *data)
 {
+   struct ilo_context *ilo = ilo_context(data);
+
+   if (cp->ring == ILO_CP_RING_RENDER)
+      ilo_3d_new_cp_batch(ilo->hw3d);
 }
 
 static void
 ilo_context_pre_cp_flush(struct ilo_cp *cp, void *data)
 {
+   struct ilo_context *ilo = ilo_context(data);
+
+   if (cp->ring == ILO_CP_RING_RENDER)
+      ilo_3d_pre_cp_flush(ilo->hw3d);
 }
 
 static void
@@ -61,6 +69,9 @@ ilo_context_post_cp_flush(struct ilo_cp *cp, void *data)
    /* remember the just flushed bo, on which fences could wait */
    ilo->last_cp_bo = cp->bo;
    ilo->last_cp_bo->reference(ilo->last_cp_bo);
+
+   if (cp->ring == ILO_CP_RING_RENDER)
+      ilo_3d_post_cp_flush(ilo->hw3d);
 }
 
 static void
@@ -103,6 +114,8 @@ ilo_context_destroy(struct pipe_context *pipe)
 
    if (ilo->blitter)
       util_blitter_destroy(ilo->blitter);
+   if (ilo->hw3d)
+      ilo_3d_destroy(ilo->hw3d);
    if (ilo->shader_cache)
       ilo_shader_cache_destroy(ilo->shader_cache);
    if (ilo->cp)
@@ -177,8 +190,10 @@ ilo_context_create(struct pipe_screen *screen, void *priv)
 
    ilo->cp = ilo_cp_create(ilo->winsys, is->has_llc);
    ilo->shader_cache = ilo_shader_cache_create(ilo->winsys);
+   if (ilo->cp)
+      ilo->hw3d = ilo_3d_create(ilo->cp, ilo->gen, ilo->gt);
 
-   if (!ilo->cp || !ilo->shader_cache) {
+   if (!ilo->cp || !ilo->shader_cache || !ilo->hw3d) {
       ilo_context_destroy(&ilo->base);
       return NULL;
    }
index 58fee1f1821ffa1a9d4e2cddf36ca1c1e2650994..695f6f4d29a84a1a69636c0239972c42ad886950 100644 (file)
@@ -57,6 +57,7 @@
 struct blitter_context;
 struct intel_winsys;
 struct intel_bo;
+struct ilo_3d;
 struct ilo_cp;
 struct ilo_screen;
 struct ilo_shader_state;
@@ -87,6 +88,7 @@ struct ilo_context {
    struct intel_bo *last_cp_bo;
 
    struct ilo_shader_cache *shader_cache;
+   struct ilo_3d *hw3d;
    struct blitter_context *blitter;
 
    uint32_t dirty;