ilo: clean up fallback path for primitive restart
authorChia-I Wu <olvaffe@gmail.com>
Mon, 22 Sep 2014 05:46:13 +0000 (13:46 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Mon, 22 Sep 2014 06:22:37 +0000 (14:22 +0800)
We should be able to draw with the index buffer mapped.  That simplifies
things a lot.

Signed-off-by: Chia-I Wu <olvaffe@gmail.com>
src/gallium/drivers/ilo/ilo_3d.c

index 75b2afacc3eb20468616a2487c3997514e287827..e708cbc7743ba9e64e9ef725aa1367490a9476c4 100644 (file)
@@ -507,185 +507,105 @@ ilo_3d_draw_rectlist(struct ilo_3d *hw3d, const struct ilo_blitter *blitter)
    hw3d->new_batch = false;
 }
 
-#define UPDATE_MIN2(a, b) (a) = MIN2((a), (b))
-#define UPDATE_MAX2(a, b) (a) = MAX2((a), (b))
-
-/**
- * \see find_sub_primitives() from core mesa
- */
-static int
-ilo_find_sub_primitives(const void *elements, unsigned element_size,
-                    const struct pipe_draw_info *orig_info,
-                    struct pipe_draw_info *info)
+static void
+draw_vbo_with_sw_restart(struct ilo_context *ilo,
+                         const struct pipe_draw_info *info)
 {
-   const unsigned max_prims = orig_info->count - orig_info->start;
-   unsigned i, cur_start, cur_count;
-   int scan_index;
-   unsigned scan_num;
-
-   cur_start = orig_info->start;
-   cur_count = 0;
-   scan_num = 0;
-
-#define IB_INDEX_READ(TYPE, INDEX) (((const TYPE *) elements)[INDEX])
-
-#define SCAN_ELEMENTS(TYPE) \
-   info[scan_num] = *orig_info; \
-   info[scan_num].primitive_restart = false; \
-   for (i = orig_info->start; i < orig_info->count; i++) { \
-      scan_index = IB_INDEX_READ(TYPE, i); \
-      if (scan_index == orig_info->restart_index) { \
-         if (cur_count > 0) { \
-            assert(scan_num < max_prims); \
-            info[scan_num].start = cur_start; \
-            info[scan_num].count = cur_count; \
-            scan_num++; \
-            info[scan_num] = *orig_info; \
-            info[scan_num].primitive_restart = false; \
-         } \
-         cur_start = i + 1; \
-         cur_count = 0; \
-      } \
-      else { \
-         UPDATE_MIN2(info[scan_num].min_index, scan_index); \
-         UPDATE_MAX2(info[scan_num].max_index, scan_index); \
-         cur_count++; \
-      } \
-   } \
-   if (cur_count > 0) { \
-      assert(scan_num < max_prims); \
-      info[scan_num].start = cur_start; \
-      info[scan_num].count = cur_count; \
-      scan_num++; \
+   const struct ilo_ib_state *ib = &ilo->state_vector.ib;
+   union {
+      const void *ptr;
+      const uint8_t *u8;
+      const uint16_t *u16;
+      const uint32_t *u32;
+   } u;
+
+   /* we will draw with IB mapped */
+   if (ib->buffer) {
+      u.ptr = intel_bo_map(ilo_buffer(ib->buffer)->bo, false);
+      if (u.ptr)
+         u.u8 += ib->offset;
+   } else {
+      u.ptr = ib->user_buffer;
    }
 
-   switch (element_size) {
+   if (!u.ptr)
+      return;
+
+#define DRAW_VBO_WITH_SW_RESTART(pipe, info, ptr) do {   \
+   const unsigned end = (info)->start + (info)->count;   \
+   struct pipe_draw_info subinfo;                        \
+   unsigned i;                                           \
+                                                         \
+   subinfo = *(info);                                    \
+   subinfo.primitive_restart = false;                    \
+   for (i = (info)->start; i < end; i++) {               \
+      if ((ptr)[i] == (info)->restart_index) {           \
+         subinfo.count = i - subinfo.start;              \
+         if (subinfo.count)                              \
+            (pipe)->draw_vbo(pipe, &subinfo);            \
+         subinfo.start = i + 1;                          \
+      }                                                  \
+   }                                                     \
+   subinfo.count = i - subinfo.start;                    \
+   if (subinfo.count)                                    \
+      (pipe)->draw_vbo(pipe, &subinfo);                  \
+} while (0)
+
+   switch (ib->index_size) {
    case 1:
-      SCAN_ELEMENTS(uint8_t);
+      DRAW_VBO_WITH_SW_RESTART(&ilo->base, info, u.u8);
       break;
    case 2:
-      SCAN_ELEMENTS(uint16_t);
+      DRAW_VBO_WITH_SW_RESTART(&ilo->base, info, u.u16);
       break;
    case 4:
-      SCAN_ELEMENTS(uint32_t);
+      DRAW_VBO_WITH_SW_RESTART(&ilo->base, info, u.u32);
       break;
    default:
-      assert(0 && "bad index_size in find_sub_primitives()");
+      assert(!"unsupported index size");
+      break;
    }
 
-#undef SCAN_ELEMENTS
+#undef DRAW_VBO_WITH_SW_RESTART
 
-   return scan_num;
+   if (ib->buffer)
+      intel_bo_unmap(ilo_buffer(ib->buffer)->bo);
 }
 
-static inline bool
-ilo_check_restart_index(const struct ilo_context *ilo, unsigned restart_index)
+static bool
+draw_vbo_need_sw_restart(const struct ilo_context *ilo,
+                         const struct pipe_draw_info *info)
 {
-   /*
-    * Haswell (GEN(7.5)) supports an arbitrary cut index, check everything
-    * older.
-    */
-   if (ilo_dev_gen(ilo->dev) >= ILO_GEN(7.5))
-      return true;
-
-   /* Note: indices must be unsigned byte, unsigned short or unsigned int */
-   switch (ilo->state_vector.ib.index_size) {
-   case 1:
-      return ((restart_index & 0xff) == 0xff);
-      break;
-   case 2:
-      return ((restart_index & 0xffff) == 0xffff);
-      break;
-   case 4:
-      return (restart_index == 0xffffffff);
-      break;
+   /* the restart index is fixed prior to GEN7.5 */
+   if (ilo_dev_gen(ilo->dev) < ILO_GEN(7.5)) {
+      const unsigned cut_index =
+         (ilo->state_vector.ib.index_size == 1) ? 0xff :
+         (ilo->state_vector.ib.index_size == 2) ? 0xffff :
+         (ilo->state_vector.ib.index_size == 4) ? 0xffffffff : 0;
+
+      if (info->restart_index < cut_index)
+         return true;
    }
-   return false;
-}
 
-static inline bool
-ilo_check_restart_prim_type(const struct ilo_context *ilo, unsigned prim)
-{
-   switch (prim) {
+   switch (info->mode) {
    case PIPE_PRIM_POINTS:
    case PIPE_PRIM_LINES:
    case PIPE_PRIM_LINE_STRIP:
    case PIPE_PRIM_TRIANGLES:
    case PIPE_PRIM_TRIANGLE_STRIP:
-      /* All 965 GEN graphics support a cut index for these primitive types */
-      return true;
-      break;
-
+      /* these never need software fallback */
+      return false;
    case PIPE_PRIM_LINE_LOOP:
    case PIPE_PRIM_POLYGON:
    case PIPE_PRIM_QUAD_STRIP:
    case PIPE_PRIM_QUADS:
    case PIPE_PRIM_TRIANGLE_FAN:
-      if (ilo_dev_gen(ilo->dev) >= ILO_GEN(7.5)) {
-         /* Haswell and newer parts can handle these prim types. */
-         return true;
-      }
-      break;
-   }
-
-   return false;
-}
-
-/*
- * Handle VBOs using primitive restart.
- * Verify that restart index and primitive type can be handled by the HW.
- * Return true if this routine did the rendering
- * Return false if this routine did NOT render because restart can be handled
- * in HW.
- */
-static void
-ilo_draw_vbo_with_sw_restart(struct pipe_context *pipe,
-                             const struct pipe_draw_info *info)
-{
-   struct ilo_state_vector *vec = &ilo_context(pipe)->state_vector;
-   struct pipe_draw_info *restart_info = NULL;
-   int sub_prim_count = 1;
-
-   /*
-    * We have to break up the primitive into chunks manually
-    * Worst case, every other index could be a restart index so
-    * need to have space for that many primitives
-    */
-   restart_info = MALLOC(((info->count + 1) / 2) * sizeof(*info));
-   if (NULL == restart_info) {
-      /* If we can't get memory for this, bail out */
-      ilo_err("%s:%d - Out of memory", __FILE__, __LINE__);
-      return;
-   }
-
-   if (vec->ib.buffer) {
-      struct pipe_transfer *transfer;
-      const void *map;
-
-      map = pipe_buffer_map(pipe, vec->ib.buffer,
-            PIPE_TRANSFER_READ, &transfer);
-
-      sub_prim_count = ilo_find_sub_primitives(map + vec->ib.offset,
-            vec->ib.index_size, info, restart_info);
-
-      pipe_buffer_unmap(pipe, transfer);
-   }
-   else {
-      sub_prim_count =
-         ilo_find_sub_primitives(vec->ib.user_buffer,
-               vec->ib.index_size, info, restart_info);
-   }
-
-   info = restart_info;
-
-   while (sub_prim_count > 0) {
-      pipe->draw_vbo(pipe, info);
-
-      sub_prim_count--;
-      info++;
+      /* these need software fallback prior to GEN7.5 */
+      return (ilo_dev_gen(ilo->dev) < ILO_GEN(7.5));
+   default:
+      /* the rest always needs software fallback */
+      return true;
    }
-
-   FREE(restart_info);
 }
 
 static void
@@ -712,16 +632,10 @@ ilo_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
    if (ilo_skip_rendering(ilo))
       return;
 
-   if (info->primitive_restart && info->indexed) {
-      /*
-       * Want to draw an indexed primitive using primitive restart
-       * Check that HW can handle the request and fall to SW if not.
-       */
-      if (!ilo_check_restart_index(ilo, info->restart_index) ||
-          !ilo_check_restart_prim_type(ilo, info->mode)) {
-         ilo_draw_vbo_with_sw_restart(pipe, info);
-         return;
-      }
+   if (info->primitive_restart && info->indexed &&
+       draw_vbo_need_sw_restart(ilo, info)) {
+      draw_vbo_with_sw_restart(ilo, info);
+      return;
    }
 
    ilo_finalize_3d_states(ilo, info);