From a68f421d7370fa4b82bd2d6f94aba9cbfde39b33 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Mon, 22 Sep 2014 13:46:13 +0800 Subject: [PATCH] ilo: clean up fallback path for primitive restart We should be able to draw with the index buffer mapped. That simplifies things a lot. Signed-off-by: Chia-I Wu --- src/gallium/drivers/ilo/ilo_3d.c | 234 +++++++++++++-------------------------- 1 file changed, 74 insertions(+), 160 deletions(-) diff --git a/src/gallium/drivers/ilo/ilo_3d.c b/src/gallium/drivers/ilo/ilo_3d.c index 75b2afa..e708cbc 100644 --- a/src/gallium/drivers/ilo/ilo_3d.c +++ b/src/gallium/drivers/ilo/ilo_3d.c @@ -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); -- 2.7.4