From e1948c9a71cc7bc9da62fe771276ef1681e3d2fb Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 5 Nov 2021 11:56:22 -0400 Subject: [PATCH] aux/primconvert: break out primconvert internals into util function this should (ideally) be no functional changes Reviewed-by: Rob Clark Part-of: --- src/gallium/auxiliary/indices/u_primconvert.c | 306 +++++++++--------- 1 file changed, 160 insertions(+), 146 deletions(-) diff --git a/src/gallium/auxiliary/indices/u_primconvert.c b/src/gallium/auxiliary/indices/u_primconvert.c index 5ce8dddfa1f..30da20ddb63 100644 --- a/src/gallium/auxiliary/indices/u_primconvert.c +++ b/src/gallium/auxiliary/indices/u_primconvert.c @@ -102,16 +102,14 @@ util_primconvert_save_flatshade_first(struct primconvert_context *pc, bool flats pc->api_pv = flatshade_first ? PV_FIRST : PV_LAST; } -void -util_primconvert_draw_vbo(struct primconvert_context *pc, - const struct pipe_draw_info *info, - unsigned drawid_offset, - const struct pipe_draw_indirect_info *indirect, - const struct pipe_draw_start_count_bias *draws, - unsigned num_draws) +static bool +primconvert_init_draw(struct primconvert_context *pc, + const struct pipe_draw_info *info, + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count_bias *draws, + struct pipe_draw_info *new_info, + struct pipe_draw_start_count_bias *new_draw) { - struct pipe_draw_info new_info; - struct pipe_draw_start_count_bias new_draw; struct pipe_draw_start_count_bias *direct_draws = NULL; unsigned num_direct_draws = 0; struct pipe_transfer *src_transfer = NULL; @@ -123,6 +121,158 @@ util_primconvert_draw_vbo(struct primconvert_context *pc, unsigned total_index_count = draws->count; void *rewrite_buffer = NULL; + const struct pipe_draw_start_count_bias *draw = &draws[0]; + + /* Filter out degenerate primitives, u_upload_alloc() will assert + * on size==0 so just bail: + */ + if (!info->primitive_restart && + !u_trim_pipe_prim(info->mode, (unsigned*)&draw->count)) + return false; + + util_draw_init_info(new_info); + new_info->index_bounds_valid = info->index_bounds_valid; + new_info->min_index = info->min_index; + new_info->max_index = info->max_index; + new_info->start_instance = info->start_instance; + new_info->instance_count = info->instance_count; + new_info->primitive_restart = info->primitive_restart; + new_info->restart_index = info->restart_index; + if (info->index_size) { + enum pipe_prim_type mode = new_info->mode = u_index_prim_type_convert(pc->cfg.primtypes_mask, info->mode, true); + unsigned index_size = info->index_size; + new_info->index_size = u_index_size_convert(info->index_size); + + src = info->has_user_indices ? info->index.user : NULL; + if (!src) { + src = pipe_buffer_map(pc->pipe, info->index.resource, + PIPE_MAP_READ, &src_transfer); + } + src = (const uint8_t *)src; + + /* if the resulting primitive type is not supported by the driver for primitive restart, + * or if the original primitive type was not supported by the driver, + * the draw needs to be rewritten to not use primitive restart + */ + if (info->primitive_restart && + (!(pc->cfg.restart_primtypes_mask & BITFIELD_BIT(mode)) || + !(pc->cfg.primtypes_mask & BITFIELD_BIT(info->mode)))) { + /* step 1: rewrite draw to not use primitive primitive restart; + * this pre-filters degenerate primitives + */ + direct_draws = util_prim_restart_convert_to_direct(src, info, draw, &num_direct_draws, + &new_info->min_index, &new_info->max_index, &total_index_count); + new_info->primitive_restart = false; + /* step 2: get a translator function which does nothing but handle any index size conversions + * which may or may not occur (8bit -> 16bit) + */ + u_index_translator(0xffff, + info->mode, index_size, total_index_count, + pc->api_pv, pc->api_pv, + PR_DISABLE, + &mode, &index_size, &new_draw->count, + &direct_draw_func); + /* this should always be a direct translation */ + assert(new_draw->count == total_index_count); + /* step 3: allocate a temp buffer for an intermediate rewrite step + * if no indices were found, this was a single incomplete restart and can be discarded + */ + if (total_index_count) + rewrite_buffer = malloc(index_size * total_index_count); + if (!rewrite_buffer) { + if (src_transfer) + pipe_buffer_unmap(pc->pipe, src_transfer); + return false; + } + } + /* (step 4: get the actual primitive conversion translator function) */ + u_index_translator(pc->cfg.primtypes_mask, + info->mode, index_size, total_index_count, + pc->api_pv, pc->api_pv, + new_info->primitive_restart ? PR_ENABLE : PR_DISABLE, + &mode, &index_size, &new_draw->count, + &trans_func); + assert(new_info->mode == mode); + assert(new_info->index_size == index_size); + } + else { + enum pipe_prim_type mode = 0; + unsigned index_size; + + u_index_generator(pc->cfg.primtypes_mask, + info->mode, draw->start, draw->count, + pc->api_pv, pc->api_pv, + &mode, &index_size, &new_draw->count, + &gen_func); + new_info->mode = mode; + new_info->index_size = index_size; + } + + /* (step 5: allocate gpu memory sized for the FINAL index count) */ + u_upload_alloc(pc->pipe->stream_uploader, 0, new_info->index_size * new_draw->count, 4, + &ib_offset, &new_info->index.resource, &dst); + new_draw->start = ib_offset / new_info->index_size; + new_draw->index_bias = info->index_size ? draw->index_bias : 0; + + if (info->index_size) { + if (num_direct_draws) { + uint8_t *ptr = rewrite_buffer; + uint8_t *dst_ptr = dst; + /* step 6: if rewriting a prim-restart draw to direct draws, + * loop over all the direct draws in order to rewrite them into a single index buffer + * and draw in order to match the original call + */ + for (unsigned i = 0; i < num_direct_draws; i++) { + /* step 6a: get the index count for this draw, once converted */ + unsigned tmp_count = u_index_count_converted_indices(pc->cfg.primtypes_mask, true, info->mode, direct_draws[i].count); + /* step 6b: handle index size conversion using the temp buffer; no change in index count + * TODO: this step can be optimized out if the index size is known to not change + */ + direct_draw_func(src, direct_draws[i].start, direct_draws[i].count, direct_draws[i].count, info->restart_index, ptr); + /* step 6c: handle the primitive type conversion rewriting to the converted index count */ + trans_func(ptr, 0, direct_draws[i].count, tmp_count, info->restart_index, dst_ptr); + /* step 6d: increment the temp buffer and mapped final index buffer pointers */ + ptr += new_info->index_size * direct_draws[i].count; + dst_ptr += new_info->index_size * tmp_count; + } + /* step 7: set the final index count, which is the converted total index count from the original draw rewrite */ + new_draw->count = u_index_count_converted_indices(pc->cfg.primtypes_mask, true, info->mode, total_index_count); + } else + trans_func(src, draw->start, draw->count, new_draw->count, info->restart_index, dst); + + if (pc->cfg.fixed_prim_restart && new_info->primitive_restart) { + new_info->restart_index = (1ull << (new_info->index_size * 8)) - 1; + if (info->restart_index != new_info->restart_index) + util_translate_prim_restart_data(new_info->index_size, dst, dst, + new_draw->count, + info->restart_index); + } + } + else { + gen_func(draw->start, new_draw->count, dst); + } + + if (src_transfer) + pipe_buffer_unmap(pc->pipe, src_transfer); + + u_upload_unmap(pc->pipe->stream_uploader); + + free(direct_draws); + free(rewrite_buffer); + return true; +} + +void +util_primconvert_draw_vbo(struct primconvert_context *pc, + const struct pipe_draw_info *info, + unsigned drawid_offset, + const struct pipe_draw_indirect_info *indirect, + const struct pipe_draw_start_count_bias *draws, + unsigned num_draws) +{ + struct pipe_draw_info new_info; + struct pipe_draw_start_count_bias new_draw; + if (indirect && indirect->buffer) { /* this is stupid, but we're already doing a readback, * so this thing may as well get the rest of the job done @@ -149,146 +299,10 @@ util_primconvert_draw_vbo(struct primconvert_context *pc, return; } - const struct pipe_draw_start_count_bias *draw = &draws[0]; - - /* Filter out degenerate primitives, u_upload_alloc() will assert - * on size==0 so just bail: - */ - if (!info->primitive_restart && - !u_trim_pipe_prim(info->mode, (unsigned*)&draw->count)) + if (!primconvert_init_draw(pc, info, indirect, draws, &new_info, &new_draw)) return; - - util_draw_init_info(&new_info); - new_info.index_bounds_valid = info->index_bounds_valid; - new_info.min_index = info->min_index; - new_info.max_index = info->max_index; - new_info.start_instance = info->start_instance; - new_info.instance_count = info->instance_count; - new_info.primitive_restart = info->primitive_restart; - new_info.restart_index = info->restart_index; - if (info->index_size) { - enum pipe_prim_type mode = new_info.mode = u_index_prim_type_convert(pc->cfg.primtypes_mask, info->mode, true); - unsigned index_size = info->index_size; - new_info.index_size = u_index_size_convert(info->index_size); - - src = info->has_user_indices ? info->index.user : NULL; - if (!src) { - src = pipe_buffer_map(pc->pipe, info->index.resource, - PIPE_MAP_READ, &src_transfer); - } - src = (const uint8_t *)src; - - /* if the resulting primitive type is not supported by the driver for primitive restart, - * or if the original primitive type was not supported by the driver, - * the draw needs to be rewritten to not use primitive restart - */ - if (info->primitive_restart && - (!(pc->cfg.restart_primtypes_mask & BITFIELD_BIT(mode)) || - !(pc->cfg.primtypes_mask & BITFIELD_BIT(info->mode)))) { - /* step 1: rewrite draw to not use primitive primitive restart; - * this pre-filters degenerate primitives - */ - direct_draws = util_prim_restart_convert_to_direct(src, info, draw, &num_direct_draws, - &new_info.min_index, &new_info.max_index, &total_index_count); - new_info.primitive_restart = false; - /* step 2: get a translator function which does nothing but handle any index size conversions - * which may or may not occur (8bit -> 16bit) - */ - u_index_translator(0xffff, - info->mode, index_size, total_index_count, - pc->api_pv, pc->api_pv, - PR_DISABLE, - &mode, &index_size, &new_draw.count, - &direct_draw_func); - /* this should always be a direct translation */ - assert(new_draw.count == total_index_count); - /* step 3: allocate a temp buffer for an intermediate rewrite step - * if no indices were found, this was a single incomplete restart and can be discarded - */ - if (total_index_count) - rewrite_buffer = malloc(index_size * total_index_count); - if (!rewrite_buffer) { - if (src_transfer) - pipe_buffer_unmap(pc->pipe, src_transfer); - return; - } - } - /* (step 4: get the actual primitive conversion translator function) */ - u_index_translator(pc->cfg.primtypes_mask, - info->mode, index_size, total_index_count, - pc->api_pv, pc->api_pv, - new_info.primitive_restart ? PR_ENABLE : PR_DISABLE, - &mode, &index_size, &new_draw.count, - &trans_func); - assert(new_info.mode == mode); - assert(new_info.index_size == index_size); - } - else { - enum pipe_prim_type mode = 0; - unsigned index_size; - - u_index_generator(pc->cfg.primtypes_mask, - info->mode, draw->start, draw->count, - pc->api_pv, pc->api_pv, - &mode, &index_size, &new_draw.count, - &gen_func); - new_info.mode = mode; - new_info.index_size = index_size; - } - - /* (step 5: allocate gpu memory sized for the FINAL index count) */ - u_upload_alloc(pc->pipe->stream_uploader, 0, new_info.index_size * new_draw.count, 4, - &ib_offset, &new_info.index.resource, &dst); - new_draw.start = ib_offset / new_info.index_size; - new_draw.index_bias = info->index_size ? draw->index_bias : 0; - - if (info->index_size) { - if (num_direct_draws) { - uint8_t *ptr = rewrite_buffer; - uint8_t *dst_ptr = dst; - /* step 6: if rewriting a prim-restart draw to direct draws, - * loop over all the direct draws in order to rewrite them into a single index buffer - * and draw in order to match the original call - */ - for (unsigned i = 0; i < num_direct_draws; i++) { - /* step 6a: get the index count for this draw, once converted */ - unsigned tmp_count = u_index_count_converted_indices(pc->cfg.primtypes_mask, true, info->mode, direct_draws[i].count); - /* step 6b: handle index size conversion using the temp buffer; no change in index count - * TODO: this step can be optimized out if the index size is known to not change - */ - direct_draw_func(src, direct_draws[i].start, direct_draws[i].count, direct_draws[i].count, info->restart_index, ptr); - /* step 6c: handle the primitive type conversion rewriting to the converted index count */ - trans_func(ptr, 0, direct_draws[i].count, tmp_count, info->restart_index, dst_ptr); - /* step 6d: increment the temp buffer and mapped final index buffer pointers */ - ptr += new_info.index_size * direct_draws[i].count; - dst_ptr += new_info.index_size * tmp_count; - } - /* step 7: set the final index count, which is the converted total index count from the original draw rewrite */ - new_draw.count = u_index_count_converted_indices(pc->cfg.primtypes_mask, true, info->mode, total_index_count); - } else - trans_func(src, draw->start, draw->count, new_draw.count, info->restart_index, dst); - - if (pc->cfg.fixed_prim_restart && new_info.primitive_restart) { - new_info.restart_index = (1ull << (new_info.index_size * 8)) - 1; - if (info->restart_index != new_info.restart_index) - util_translate_prim_restart_data(new_info.index_size, dst, dst, - new_draw.count, - info->restart_index); - } - } - else { - gen_func(draw->start, new_draw.count, dst); - } - - if (src_transfer) - pipe_buffer_unmap(pc->pipe, src_transfer); - - u_upload_unmap(pc->pipe->stream_uploader); - /* to the translated draw: */ pc->pipe->draw_vbo(pc->pipe, &new_info, drawid_offset, NULL, &new_draw, 1); - free(direct_draws); - free(rewrite_buffer); pipe_resource_reference(&new_info.index.resource, NULL); }