示例#1
0
static void
gen6_wa_pre_depth(struct ilo_render *r)
{
   ILO_DEV_ASSERT(r->dev, 6, 6);

   /*
    * From the Ivy Bridge PRM, volume 2 part 1, page 315:
    *
    *     "Restriction: Prior to changing Depth/Stencil Buffer state (i.e.,
    *      any combination of 3DSTATE_DEPTH_BUFFER, 3DSTATE_CLEAR_PARAMS,
    *      3DSTATE_STENCIL_BUFFER, 3DSTATE_HIER_DEPTH_BUFFER) SW must first
    *      issue a pipelined depth stall (PIPE_CONTROL with Depth Stall bit
    *      set), followed by a pipelined depth cache flush (PIPE_CONTROL with
    *      Depth Flush Bit set, followed by another pipelined depth stall
    *      (PIPE_CONTROL with Depth Stall Bit set), unless SW can otherwise
    *      guarantee that the pipeline from WM onwards is already flushed
    *      (e.g., via a preceding MI_FLUSH)."
    *
    * According to the classic driver, it also applies for GEN6.
    */
   gen6_wa_pre_pipe_control(r, GEN6_PIPE_CONTROL_DEPTH_STALL |
                               GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH);

   gen6_pipe_control(r, GEN6_PIPE_CONTROL_DEPTH_STALL);
   gen6_pipe_control(r, GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH);
   gen6_pipe_control(r, GEN6_PIPE_CONTROL_DEPTH_STALL);
}
示例#2
0
/**
 * This should be called before any non-pipelined state command.
 */
static void
gen6_wa_pre_non_pipelined(struct ilo_render *r)
{
   ILO_DEV_ASSERT(r->dev, 6, 6);

   /* non-pipelined state commands produce depth stall */
   gen6_wa_pre_pipe_control(r, GEN6_PIPE_CONTROL_DEPTH_STALL);
}
示例#3
0
static void
gen6_wa_post_3dstate_constant_vs(struct ilo_render *r)
{
   /*
    * According to upload_vs_state() of the classic driver, we need to emit a
    * PIPE_CONTROL after 3DSTATE_CONSTANT_VS, otherwise the command is kept
    * being buffered by VS FF, to the point that the FF dies.
    */
   const uint32_t dw1 = GEN6_PIPE_CONTROL_DEPTH_STALL |
                        GEN6_PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE |
                        GEN6_PIPE_CONTROL_STATE_CACHE_INVALIDATE;

   gen6_wa_pre_pipe_control(r, dw1);

   if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
      gen6_pipe_control(r, dw1);
}
示例#4
0
static void
gen6_wa_pre_3dstate_wm_max_threads(struct ilo_render *r)
{
   /*
    * From the Sandy Bridge PRM, volume 2 part 1, page 274:
    *
    *     "A PIPE_CONTROL command, with only the Stall At Pixel Scoreboard
    *      field set (DW1 Bit 1), must be issued prior to any change to the
    *      value in this field (Maximum Number of Threads in 3DSTATE_WM)"
    */
   const uint32_t dw1 = GEN6_PIPE_CONTROL_PIXEL_SCOREBOARD_STALL;

   ILO_DEV_ASSERT(r->dev, 6, 6);

   gen6_wa_pre_pipe_control(r, dw1);

   if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
      gen6_pipe_control(r, dw1);
}
示例#5
0
static void
gen6_wa_post_3dstate_urb_no_gs(struct ilo_render *r)
{
   /*
    * From the Sandy Bridge PRM, volume 2 part 1, page 27:
    *
    *     "Because of a urb corruption caused by allocating a previous
    *      gsunit's urb entry to vsunit software is required to send a
    *      "GS NULL Fence" (Send URB fence with VS URB size == 1 and GS URB
    *      size == 0) plus a dummy DRAW call before any case where VS will
    *      be taking over GS URB space."
    */
   const uint32_t dw1 = GEN6_PIPE_CONTROL_CS_STALL;

   if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
      gen6_wa_pre_pipe_control(r, dw1);
   if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
      ilo_render_pipe_control(r, dw1);
}
示例#6
0
static void
gen6_wa_pre_3dstate_multisample(struct ilo_render *r)
{
   /*
    * From the Sandy Bridge PRM, volume 2 part 1, page 305:
    *
    *     "Driver must guarentee that all the caches in the depth pipe are
    *      flushed before this command (3DSTATE_MULTISAMPLE) is parsed. This
    *      requires driver to send a PIPE_CONTROL with a CS stall along with a
    *      Depth Flush prior to this command."
    */
   const uint32_t dw1 = GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH |
                        GEN6_PIPE_CONTROL_CS_STALL;

   ILO_DEV_ASSERT(r->dev, 6, 6);

   gen6_wa_pre_pipe_control(r, dw1);

   if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
      gen6_pipe_control(r, dw1);
}
示例#7
0
/**
 * Emit PIPE_CONTROLs to flush all caches.
 */
void
ilo_render_emit_flush(struct ilo_render *render)
{
   const uint32_t dw1 = GEN6_PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE |
                        GEN6_PIPE_CONTROL_RENDER_CACHE_FLUSH |
                        GEN6_PIPE_CONTROL_DEPTH_CACHE_FLUSH |
                        GEN6_PIPE_CONTROL_VF_CACHE_INVALIDATE |
                        GEN6_PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE |
                        GEN6_PIPE_CONTROL_CS_STALL;
   const unsigned batch_used = ilo_builder_batch_used(render->builder);

   ILO_DEV_ASSERT(render->dev, 6, 8);

   if (ilo_dev_gen(render->dev) == ILO_GEN(6))
      gen6_wa_pre_pipe_control(render, dw1);

   ilo_render_pipe_control(render, dw1);

   assert(ilo_builder_batch_used(render->builder) <= batch_used +
         ilo_render_get_flush_len(render));
}
示例#8
0
static void
gen6_wa_pre_3dstate_vs_toggle(struct ilo_render *r)
{
   /*
    * The classic driver has this undocumented WA:
    *
    * From the BSpec, 3D Pipeline > Geometry > Vertex Shader > State,
    * 3DSTATE_VS, Dword 5.0 "VS Function Enable":
    *
    *   [DevSNB] A pipeline flush must be programmed prior to a 3DSTATE_VS
    *   command that causes the VS Function Enable to toggle. Pipeline
    *   flush can be executed by sending a PIPE_CONTROL command with CS
    *   stall bit set and a post sync operation.
    */
   const uint32_t dw1 = GEN6_PIPE_CONTROL_WRITE_IMM |
                        GEN6_PIPE_CONTROL_CS_STALL;

   if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
      gen6_wa_pre_pipe_control(r, dw1);
   if ((r->state.current_pipe_control_dw1 & dw1) != dw1)
      ilo_render_pipe_control(r, dw1);
}
示例#9
0
/**
 * Emit PIPE_CONTROLs or MI_STORE_REGISTER_MEMs to store register values.
 */
void
ilo_render_emit_query(struct ilo_render *render,
                      struct ilo_query *q, uint32_t offset)
{
   const uint32_t pipeline_statistics_regs[11] = {
      GEN6_REG_IA_VERTICES_COUNT,
      GEN6_REG_IA_PRIMITIVES_COUNT,
      GEN6_REG_VS_INVOCATION_COUNT,
      GEN6_REG_GS_INVOCATION_COUNT,
      GEN6_REG_GS_PRIMITIVES_COUNT,
      GEN6_REG_CL_INVOCATION_COUNT,
      GEN6_REG_CL_PRIMITIVES_COUNT,
      GEN6_REG_PS_INVOCATION_COUNT,
      (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ?
         GEN7_REG_HS_INVOCATION_COUNT : 0,
      (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ?
         GEN7_REG_DS_INVOCATION_COUNT : 0,
      0,
   };
   const uint32_t primitives_generated_reg =
      (ilo_dev_gen(render->dev) >= ILO_GEN(7) && q->index > 0) ?
      GEN7_REG_SO_PRIM_STORAGE_NEEDED(q->index) :
      GEN6_REG_CL_INVOCATION_COUNT;
   const uint32_t primitives_emitted_reg =
      (ilo_dev_gen(render->dev) >= ILO_GEN(7)) ?
      GEN7_REG_SO_NUM_PRIMS_WRITTEN(q->index) :
      GEN6_REG_SO_NUM_PRIMS_WRITTEN;
   const unsigned batch_used = ilo_builder_batch_used(render->builder);
   const uint32_t *regs;
   int reg_count = 0, i;
   uint32_t pipe_control_dw1 = 0;

   ILO_DEV_ASSERT(render->dev, 6, 8);

   switch (q->type) {
   case PIPE_QUERY_OCCLUSION_COUNTER:
   case PIPE_QUERY_OCCLUSION_PREDICATE:
      pipe_control_dw1 = GEN6_PIPE_CONTROL_DEPTH_STALL |
                         GEN6_PIPE_CONTROL_WRITE_PS_DEPTH_COUNT;
      break;
   case PIPE_QUERY_TIMESTAMP:
   case PIPE_QUERY_TIME_ELAPSED:
      pipe_control_dw1 = GEN6_PIPE_CONTROL_WRITE_TIMESTAMP;
      break;
   case PIPE_QUERY_PRIMITIVES_GENERATED:
      regs = &primitives_generated_reg;
      reg_count = 1;
      break;
   case PIPE_QUERY_PRIMITIVES_EMITTED:
      regs = &primitives_emitted_reg;
      reg_count = 1;
      break;
   case PIPE_QUERY_PIPELINE_STATISTICS:
      regs = pipeline_statistics_regs;
      reg_count = ARRAY_SIZE(pipeline_statistics_regs);
      break;
   default:
      break;
   }

   if (pipe_control_dw1) {
      assert(!reg_count);

      if (ilo_dev_gen(render->dev) == ILO_GEN(6))
         gen6_wa_pre_pipe_control(render, pipe_control_dw1);

      gen6_PIPE_CONTROL(render->builder, pipe_control_dw1, q->bo, offset, 0);

      render->state.current_pipe_control_dw1 |= pipe_control_dw1;
      render->state.deferred_pipe_control_dw1 &= ~pipe_control_dw1;
   } else if (reg_count) {
      ilo_render_emit_flush(render);
   }

   for (i = 0; i < reg_count; i++) {
      if (regs[i]) {
         /* store lower 32 bits */
         gen6_MI_STORE_REGISTER_MEM(render->builder, regs[i], q->bo, offset);
         /* store higher 32 bits */
         gen6_MI_STORE_REGISTER_MEM(render->builder, regs[i] + 4,
               q->bo, offset + 4);
      } else {
         gen6_MI_STORE_DATA_IMM(render->builder, q->bo, offset, 0);
      }

      offset += 8;
   }

   assert(ilo_builder_batch_used(render->builder) <= batch_used +
         ilo_render_get_query_len(render, q->type));
}