ilo: add ILO_3D_PIPELINE_WRITE_STATISTICS
[mesa.git] / src / gallium / drivers / ilo / ilo_3d_pipeline_gen7.c
index b395f9beffb69e48bed10d6ab77490a65ba2a7b4..5ed8b7e1e6abf7c7e67547814577ebd595f56ae6 100644 (file)
@@ -28,7 +28,7 @@
 #include "util/u_dual_blend.h"
 #include "intel_reg.h"
 
-#include "ilo_common.h"
+#include "ilo_blitter.h"
 #include "ilo_context.h"
 #include "ilo_cp.h"
 #include "ilo_gpe_gen7.h"
@@ -46,7 +46,7 @@ gen7_wa_pipe_control_cs_stall(struct ilo_3d_pipeline *p,
    struct intel_bo *bo = NULL;
    uint32_t dw1 = PIPE_CONTROL_CS_STALL;
 
-   assert(p->dev->gen == ILO_GEN(7));
+   assert(p->dev->gen == ILO_GEN(7) || p->dev->gen == ILO_GEN(7.5));
 
    /* emit once */
    if (p->state.has_gen6_wa_pipe_control)
@@ -94,7 +94,7 @@ gen7_wa_pipe_control_cs_stall(struct ilo_3d_pipeline *p,
 static void
 gen7_wa_pipe_control_vs_depth_stall(struct ilo_3d_pipeline *p)
 {
-   assert(p->dev->gen == ILO_GEN(7));
+   assert(p->dev->gen == ILO_GEN(7) || p->dev->gen == ILO_GEN(7.5));
 
    /*
     * From the Ivy Bridge PRM, volume 2 part 1, page 106:
@@ -115,7 +115,7 @@ static void
 gen7_wa_pipe_control_wm_depth_stall(struct ilo_3d_pipeline *p,
                                     bool change_depth_buffer)
 {
-   assert(p->dev->gen == ILO_GEN(7));
+   assert(p->dev->gen == ILO_GEN(7) || p->dev->gen == ILO_GEN(7.5));
 
    /*
     * From the Ivy Bridge PRM, volume 2 part 1, page 276:
@@ -161,14 +161,14 @@ gen7_wa_pipe_control_wm_depth_stall(struct ilo_3d_pipeline *p,
 }
 
 static void
-gen7_wa_pipe_control_wm_max_threads_stall(struct ilo_3d_pipeline *p)
+gen7_wa_pipe_control_ps_max_threads_stall(struct ilo_3d_pipeline *p)
 {
-   assert(p->dev->gen == ILO_GEN(7));
+   assert(p->dev->gen == ILO_GEN(7) || p->dev->gen == ILO_GEN(7.5));
 
    /*
     * From the Ivy Bridge PRM, volume 2 part 1, page 286:
     *
-    *     "If this field (Maximum Number of Threads in 3DSTATE_WM) is changed
+    *     "If this field (Maximum Number of Threads in 3DSTATE_PS) is changed
     *      between 3DPRIMITIVE commands, a PIPE_CONTROL command with Stall at
     *      Pixel Scoreboard set is required to be issued."
     */
@@ -188,7 +188,8 @@ gen7_pipeline_common_urb(struct ilo_3d_pipeline *p,
    /* 3DSTATE_URB_{VS,GS,HS,DS} */
    if (DIRTY(VE) || DIRTY(VS)) {
       /* the first 16KB are reserved for VS and PS PCBs */
-      const int offset = 16 * 1024;
+      const int offset =
+         (p->dev->gen == ILO_GEN(7.5) && p->dev->gt == 3) ? 32768 : 16384;
       int vs_entry_size, vs_total_size;
 
       vs_entry_size = (ilo->vs) ?
@@ -227,16 +228,21 @@ gen7_pipeline_common_pcb_alloc(struct ilo_3d_pipeline *p,
    /* 3DSTATE_PUSH_CONSTANT_ALLOC_{VS,PS} */
    if (session->hw_ctx_changed) {
       /*
-       * push constant buffers are only allowed to take up at most the first
-       * 16KB of the URB
+       * Push constant buffers are only allowed to take up at most the first
+       * 16KB of the URB.  Split the space evenly for VS and FS.
        */
-      gen7_emit_3DSTATE_PUSH_CONSTANT_ALLOC_VS(p->dev,
-            0, 8192, p->cp);
+      const int max_size =
+         (p->dev->gen == ILO_GEN(7.5) && p->dev->gt == 3) ? 32768 : 16384;
+      const int size = max_size / 2;
+      int offset = 0;
 
-      gen7_emit_3DSTATE_PUSH_CONSTANT_ALLOC_PS(p->dev,
-            8192, 8192, p->cp);
+      gen7_emit_3DSTATE_PUSH_CONSTANT_ALLOC_VS(p->dev, offset, size, p->cp);
+      offset += size;
 
-      gen7_wa_pipe_control_cs_stall(p, true, true);
+      gen7_emit_3DSTATE_PUSH_CONSTANT_ALLOC_PS(p->dev, offset, size, p->cp);
+
+      if (p->dev->gen == ILO_GEN(7))
+         gen7_wa_pipe_control_cs_stall(p, true, true);
    }
 }
 
@@ -416,12 +422,6 @@ gen7_pipeline_sol(struct ilo_3d_pipeline *p,
          const int stride = so_info->stride[i] * 4; /* in bytes */
          int base = 0;
 
-         /* reset HW write offsets and offset buffer base */
-         if (!p->cp->render_ctx) {
-            ilo_cp_set_one_off_flags(p->cp, INTEL_EXEC_GEN7_SOL_RESET);
-            base += p->state.so_num_vertices * stride;
-         }
-
          gen7_emit_3DSTATE_SO_BUFFER(p->dev, i, base, stride,
                ilo->so.states[i], p->cp);
       }
@@ -451,15 +451,16 @@ gen7_pipeline_sf(struct ilo_3d_pipeline *p,
                  struct gen6_pipeline_session *session)
 {
    /* 3DSTATE_SBE */
-   if (DIRTY(RASTERIZER) || DIRTY(VS) || DIRTY(GS) || DIRTY(FS)) {
-      gen7_emit_3DSTATE_SBE(p->dev, ilo->rasterizer, ilo->fs,
-            (ilo->gs) ? ilo->gs : ilo->vs, ilo->cp);
-   }
+   if (DIRTY(RASTERIZER) || DIRTY(FS))
+      gen7_emit_3DSTATE_SBE(p->dev, ilo->rasterizer, ilo->fs, ilo->cp);
 
    /* 3DSTATE_SF */
    if (DIRTY(RASTERIZER) || DIRTY(FB)) {
+      struct pipe_surface *zs = ilo->fb.state.zsbuf;
+
       gen7_wa_pipe_control_cs_stall(p, true, true);
-      gen7_emit_3DSTATE_SF(p->dev, ilo->rasterizer, ilo->fb.state.zsbuf, p->cp);
+      gen7_emit_3DSTATE_SF(p->dev, ilo->rasterizer,
+            (zs) ? zs->format : PIPE_FORMAT_NONE, p->cp);
    }
 }
 
@@ -473,11 +474,8 @@ gen7_pipeline_wm(struct ilo_3d_pipeline *p,
       const bool cc_may_kill = (ilo->dsa->dw_alpha ||
                                 ilo->blend->alpha_to_coverage);
 
-      if (p->dev->gen == ILO_GEN(7) && session->hw_ctx_changed)
-         gen7_wa_pipe_control_wm_max_threads_stall(p);
-
       gen7_emit_3DSTATE_WM(p->dev, ilo->fs,
-            ilo->rasterizer, cc_may_kill, p->cp);
+            ilo->rasterizer, cc_may_kill, 0, p->cp);
    }
 
    /* 3DSTATE_BINDING_TABLE_POINTERS_PS */
@@ -493,8 +491,12 @@ gen7_pipeline_wm(struct ilo_3d_pipeline *p,
    }
 
    /* 3DSTATE_CONSTANT_PS */
-   if (session->pcb_state_fs_changed)
-      gen7_emit_3DSTATE_CONSTANT_PS(p->dev, NULL, NULL, 0, p->cp);
+   if (session->pcb_state_fs_changed) {
+      gen7_emit_3DSTATE_CONSTANT_PS(p->dev,
+            &p->state.wm.PUSH_CONSTANT_BUFFER,
+            &p->state.wm.PUSH_CONSTANT_BUFFER_size,
+            1, p->cp);
+   }
 
    /* 3DSTATE_PS */
    if (DIRTY(FS) || DIRTY(SAMPLER_FS) || DIRTY(BLEND) ||
@@ -502,6 +504,10 @@ gen7_pipeline_wm(struct ilo_3d_pipeline *p,
       const int num_samplers = ilo->sampler[PIPE_SHADER_FRAGMENT].count;
       const bool dual_blend = ilo->blend->dual_blend;
 
+      if ((p->dev->gen == ILO_GEN(7) || p->dev->gen == ILO_GEN(7.5)) &&
+          session->hw_ctx_changed)
+         gen7_wa_pipe_control_ps_max_threads_stall(p);
+
       gen7_emit_3DSTATE_PS(p->dev, ilo->fs, num_samplers, dual_blend, p->cp);
    }
 
@@ -533,24 +539,28 @@ gen7_pipeline_wm(struct ilo_3d_pipeline *p,
    /* 3DSTATE_DEPTH_BUFFER and 3DSTATE_CLEAR_PARAMS */
    if (DIRTY(FB) || session->batch_bo_changed) {
       const struct ilo_zs_surface *zs;
+      uint32_t clear_params;
 
       if (ilo->fb.state.zsbuf) {
          const struct ilo_surface_cso *surface =
             (const struct ilo_surface_cso *) ilo->fb.state.zsbuf;
+         const struct ilo_texture_slice *slice =
+            ilo_texture_get_slice(ilo_texture(surface->base.texture),
+                  surface->base.u.tex.level, surface->base.u.tex.first_layer);
 
          assert(!surface->is_rt);
          zs = &surface->u.zs;
+         clear_params = slice->clear_value;
       }
       else {
          zs = &ilo->fb.null_zs;
+         clear_params = 0;
       }
 
       gen6_emit_3DSTATE_DEPTH_BUFFER(p->dev, zs, p->cp);
       gen6_emit_3DSTATE_HIER_DEPTH_BUFFER(p->dev, zs, p->cp);
       gen6_emit_3DSTATE_STENCIL_BUFFER(p->dev, zs, p->cp);
-
-      /* TODO */
-      gen7_emit_3DSTATE_CLEAR_PARAMS(p->dev, 0, p->cp);
+      gen7_emit_3DSTATE_CLEAR_PARAMS(p->dev, clear_params, p->cp);
    }
 }
 
@@ -639,6 +649,237 @@ ilo_3d_pipeline_emit_draw_gen7(struct ilo_3d_pipeline *p,
    gen6_pipeline_end(p, ilo, &session);
 }
 
+static void
+gen7_rectlist_pcb_alloc(struct ilo_3d_pipeline *p,
+                        const struct ilo_blitter *blitter,
+                        struct gen6_rectlist_session *session)
+{
+   /*
+    * Push constant buffers are only allowed to take up at most the first
+    * 16KB of the URB.  Split the space evenly for VS and FS.
+    */
+   const int max_size =
+      (p->dev->gen == ILO_GEN(7.5) && p->dev->gt == 3) ? 32768 : 16384;
+   const int size = max_size / 2;
+   int offset = 0;
+
+   gen7_emit_3DSTATE_PUSH_CONSTANT_ALLOC_VS(p->dev, offset, size, p->cp);
+   offset += size;
+
+   gen7_emit_3DSTATE_PUSH_CONSTANT_ALLOC_PS(p->dev, offset, size, p->cp);
+
+   gen7_wa_pipe_control_cs_stall(p, true, true);
+}
+
+static void
+gen7_rectlist_urb(struct ilo_3d_pipeline *p,
+                  const struct ilo_blitter *blitter,
+                  struct gen6_rectlist_session *session)
+{
+   /* the first 16KB are reserved for VS and PS PCBs */
+   const int offset =
+      (p->dev->gen == ILO_GEN(7.5) && p->dev->gt == 3) ? 32768 : 16384;
+
+   gen7_emit_3DSTATE_URB_VS(p->dev, offset, p->dev->urb_size - offset,
+         blitter->ve.count * 4 * sizeof(float), p->cp);
+
+   gen7_emit_3DSTATE_URB_GS(p->dev, offset, 0, 0, p->cp);
+   gen7_emit_3DSTATE_URB_HS(p->dev, offset, 0, 0, p->cp);
+   gen7_emit_3DSTATE_URB_DS(p->dev, offset, 0, 0, p->cp);
+}
+
+static void
+gen7_rectlist_vs_to_sf(struct ilo_3d_pipeline *p,
+                       const struct ilo_blitter *blitter,
+                       struct gen6_rectlist_session *session)
+{
+   gen7_emit_3DSTATE_CONSTANT_VS(p->dev, NULL, NULL, 0, p->cp);
+   gen6_emit_3DSTATE_VS(p->dev, NULL, 0, p->cp);
+
+   gen7_emit_3DSTATE_CONSTANT_HS(p->dev, NULL, NULL, 0, p->cp);
+   gen7_emit_3DSTATE_HS(p->dev, NULL, 0, p->cp);
+
+   gen7_emit_3DSTATE_TE(p->dev, p->cp);
+
+   gen7_emit_3DSTATE_CONSTANT_DS(p->dev, NULL, NULL, 0, p->cp);
+   gen7_emit_3DSTATE_DS(p->dev, NULL, 0, p->cp);
+
+   gen7_emit_3DSTATE_CONSTANT_GS(p->dev, NULL, NULL, 0, p->cp);
+   gen7_emit_3DSTATE_GS(p->dev, NULL, 0, p->cp);
+
+   gen7_emit_3DSTATE_STREAMOUT(p->dev, 0x0, 0, false, p->cp);
+
+   gen6_emit_3DSTATE_CLIP(p->dev, NULL, NULL, false, 0, p->cp);
+
+   gen7_wa_pipe_control_cs_stall(p, true, true);
+
+   gen7_emit_3DSTATE_SF(p->dev, NULL, blitter->fb.dst.base.format, p->cp);
+   gen7_emit_3DSTATE_SBE(p->dev, NULL, NULL, p->cp);
+}
+
+static void
+gen7_rectlist_wm(struct ilo_3d_pipeline *p,
+                 const struct ilo_blitter *blitter,
+                 struct gen6_rectlist_session *session)
+{
+   uint32_t hiz_op;
+
+   switch (blitter->op) {
+   case ILO_BLITTER_RECTLIST_CLEAR_ZS:
+      hiz_op = GEN7_WM_DEPTH_CLEAR;
+      break;
+   case ILO_BLITTER_RECTLIST_RESOLVE_Z:
+      hiz_op = GEN7_WM_DEPTH_RESOLVE;
+      break;
+   case ILO_BLITTER_RECTLIST_RESOLVE_HIZ:
+      hiz_op = GEN7_WM_HIERARCHICAL_DEPTH_RESOLVE;
+      break;
+   default:
+      hiz_op = 0;
+      break;
+   }
+
+   gen7_emit_3DSTATE_WM(p->dev, NULL, NULL, false, hiz_op, p->cp);
+
+   gen7_emit_3DSTATE_CONSTANT_PS(p->dev, NULL, NULL, 0, p->cp);
+
+   gen7_wa_pipe_control_ps_max_threads_stall(p);
+   gen7_emit_3DSTATE_PS(p->dev, NULL, 0, false, p->cp);
+}
+
+static void
+gen7_rectlist_wm_depth(struct ilo_3d_pipeline *p,
+                       const struct ilo_blitter *blitter,
+                       struct gen6_rectlist_session *session)
+{
+   gen7_wa_pipe_control_wm_depth_stall(p, true);
+
+   if (blitter->uses & (ILO_BLITTER_USE_FB_DEPTH |
+                        ILO_BLITTER_USE_FB_STENCIL)) {
+      gen6_emit_3DSTATE_DEPTH_BUFFER(p->dev,
+            &blitter->fb.dst.u.zs, p->cp);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_FB_DEPTH) {
+      gen6_emit_3DSTATE_HIER_DEPTH_BUFFER(p->dev,
+            &blitter->fb.dst.u.zs, p->cp);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_FB_STENCIL) {
+      gen6_emit_3DSTATE_STENCIL_BUFFER(p->dev,
+            &blitter->fb.dst.u.zs, p->cp);
+   }
+
+   gen7_emit_3DSTATE_CLEAR_PARAMS(p->dev,
+         blitter->depth_clear_value, p->cp);
+}
+
+static void
+gen7_rectlist_wm_multisample(struct ilo_3d_pipeline *p,
+                             const struct ilo_blitter *blitter,
+                             struct gen6_rectlist_session *session)
+{
+   const uint32_t *packed_sample_pos =
+      (blitter->fb.num_samples > 4) ? p->packed_sample_position_8x :
+      (blitter->fb.num_samples > 1) ? &p->packed_sample_position_4x :
+      &p->packed_sample_position_1x;
+
+   gen7_wa_pipe_control_cs_stall(p, true, true);
+
+   gen6_emit_3DSTATE_MULTISAMPLE(p->dev, blitter->fb.num_samples,
+         packed_sample_pos, true, p->cp);
+
+   gen7_emit_3DSTATE_SAMPLE_MASK(p->dev,
+         (1 << blitter->fb.num_samples) - 1, blitter->fb.num_samples, p->cp);
+}
+
+static void
+gen7_rectlist_commands(struct ilo_3d_pipeline *p,
+                       const struct ilo_blitter *blitter,
+                       struct gen6_rectlist_session *session)
+{
+   gen7_rectlist_wm_multisample(p, blitter, session);
+
+   gen6_emit_STATE_BASE_ADDRESS(p->dev,
+         NULL,                /* General State Base */
+         p->cp->bo,           /* Surface State Base */
+         p->cp->bo,           /* Dynamic State Base */
+         NULL,                /* Indirect Object Base */
+         NULL,                /* Instruction Base */
+         0, 0, 0, 0, p->cp);
+
+   gen6_emit_3DSTATE_VERTEX_BUFFERS(p->dev,
+         &blitter->ve, &blitter->vb, p->cp);
+
+   gen6_emit_3DSTATE_VERTEX_ELEMENTS(p->dev,
+         &blitter->ve, false, false, p->cp);
+
+   gen7_rectlist_pcb_alloc(p, blitter, session);
+
+   /* needed for any VS-related commands */
+   gen7_wa_pipe_control_vs_depth_stall(p);
+
+   gen7_rectlist_urb(p, blitter, session);
+
+   if (blitter->uses & ILO_BLITTER_USE_DSA) {
+      gen7_emit_3DSTATE_DEPTH_STENCIL_STATE_POINTERS(p->dev,
+            session->DEPTH_STENCIL_STATE, p->cp);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_CC) {
+      gen7_emit_3DSTATE_CC_STATE_POINTERS(p->dev,
+            session->COLOR_CALC_STATE, p->cp);
+   }
+
+   gen7_rectlist_vs_to_sf(p, blitter, session);
+   gen7_rectlist_wm(p, blitter, session);
+
+   if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) {
+      gen7_emit_3DSTATE_VIEWPORT_STATE_POINTERS_CC(p->dev,
+            session->CC_VIEWPORT, p->cp);
+   }
+
+   gen7_rectlist_wm_depth(p, blitter, session);
+
+   gen6_emit_3DSTATE_DRAWING_RECTANGLE(p->dev, 0, 0,
+         blitter->fb.width, blitter->fb.height, p->cp);
+
+   gen7_emit_3DPRIMITIVE(p->dev, &blitter->draw, NULL, true, p->cp);
+}
+
+static void
+gen7_rectlist_states(struct ilo_3d_pipeline *p,
+                     const struct ilo_blitter *blitter,
+                     struct gen6_rectlist_session *session)
+{
+   if (blitter->uses & ILO_BLITTER_USE_DSA) {
+      session->DEPTH_STENCIL_STATE =
+         gen6_emit_DEPTH_STENCIL_STATE(p->dev, &blitter->dsa, p->cp);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_CC) {
+      session->COLOR_CALC_STATE =
+         gen6_emit_COLOR_CALC_STATE(p->dev, &blitter->cc.stencil_ref,
+               blitter->cc.alpha_ref, &blitter->cc.blend_color, p->cp);
+   }
+
+   if (blitter->uses & ILO_BLITTER_USE_VIEWPORT) {
+      session->CC_VIEWPORT =
+         gen6_emit_CC_VIEWPORT(p->dev, &blitter->viewport, 1, p->cp);
+   }
+}
+
+static void
+ilo_3d_pipeline_emit_rectlist_gen7(struct ilo_3d_pipeline *p,
+                                   const struct ilo_blitter *blitter)
+{
+   struct gen6_rectlist_session session;
+
+   memset(&session, 0, sizeof(session));
+   gen7_rectlist_states(p, blitter, &session);
+   gen7_rectlist_commands(p, blitter, &session);
+}
+
 static int
 gen7_pipeline_estimate_commands(const struct ilo_3d_pipeline *p,
                                 const struct ilo_context *ilo)
@@ -798,6 +1039,22 @@ ilo_3d_pipeline_estimate_size_gen7(struct ilo_3d_pipeline *p,
       size = ilo_gpe_gen7_estimate_command_size(p->dev,
             ILO_GPE_GEN7_PIPE_CONTROL, 1);
       break;
+   case ILO_3D_PIPELINE_WRITE_STATISTICS:
+      {
+         const int num_regs = 10;
+         const int num_pads = 1;
+
+         size = ilo_gpe_gen7_estimate_command_size(p->dev,
+               ILO_GPE_GEN7_PIPE_CONTROL, 1);
+         size += ilo_gpe_gen7_estimate_command_size(p->dev,
+               ILO_GPE_GEN7_MI_STORE_REGISTER_MEM, 1) * 2 * num_regs;
+         size += ilo_gpe_gen7_estimate_command_size(p->dev,
+               ILO_GPE_GEN7_MI_STORE_DATA_IMM, 1) * num_pads;
+      }
+      break;
+   case ILO_3D_PIPELINE_RECTLIST:
+      size = 64 + 256; /* states + commands */
+      break;
    default:
       assert(!"unknown 3D pipeline action");
       size = 0;
@@ -815,4 +1072,6 @@ ilo_3d_pipeline_init_gen7(struct ilo_3d_pipeline *p)
    p->emit_flush = ilo_3d_pipeline_emit_flush_gen6;
    p->emit_write_timestamp = ilo_3d_pipeline_emit_write_timestamp_gen6;
    p->emit_write_depth_count = ilo_3d_pipeline_emit_write_depth_count_gen6;
+   p->emit_write_statistics = ilo_3d_pipeline_emit_write_statistics_gen6;
+   p->emit_rectlist = ilo_3d_pipeline_emit_rectlist_gen7;
 }