Module: Mesa Branch: main Commit: 583070748cb103560b173b5789998302d517b587 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=583070748cb103560b173b5789998302d517b587
Author: Mike Blumenkrantz <[email protected]> Date: Fri May 21 06:47:32 2021 -0400 util/primconvert: handle rewriting of prim-restart draws with unsupported primtype this is a bit more work, as the primitive restart needs to be rewritten into a multidraw, then the multidraw converted to the new primitive type and serialized back into a single draw detection is handled using a new primconvert config member, which is set to the full primtype mask by default for compatibility with existing drivers Reviewed-by: Rob Clark <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10973> --- src/gallium/auxiliary/indices/u_primconvert.c | 71 +++++++++++++++++++++++++-- src/gallium/auxiliary/indices/u_primconvert.h | 1 + 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/src/gallium/auxiliary/indices/u_primconvert.c b/src/gallium/auxiliary/indices/u_primconvert.c index 8c92bcb1ebc..d376841e72e 100644 --- a/src/gallium/auxiliary/indices/u_primconvert.c +++ b/src/gallium/auxiliary/indices/u_primconvert.c @@ -74,7 +74,7 @@ util_primconvert_create_config(struct pipe_context *pipe, struct primconvert_context * util_primconvert_create(struct pipe_context *pipe, uint32_t primtypes_mask) { - struct primconvert_config cfg = { .primtypes_mask = primtypes_mask }; + struct primconvert_config cfg = { .primtypes_mask = primtypes_mask, .restart_primtypes_mask = primtypes_mask }; return util_primconvert_create_config(pipe, &cfg); } @@ -112,12 +112,16 @@ util_primconvert_draw_vbo(struct primconvert_context *pc, { 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; - u_translate_func trans_func; + u_translate_func trans_func, direct_draw_func; u_generate_func gen_func; const void *src = NULL; void *dst; unsigned ib_offset; + unsigned total_index_count = draws->count; + void *rewrite_buffer = NULL; if (indirect && indirect->buffer) { /* this is stupid, but we're already doing a readback, @@ -168,8 +172,39 @@ util_primconvert_draw_vbo(struct primconvert_context *pc, } src = (const uint8_t *)src; + /* if the resulting primitive type is not supported by the driver for primitive restart, + * the draw needs to be rewritten to not use primitive restart + */ + if (info->primitive_restart && + !(pc->cfg.restart_primtypes_mask & BITFIELD_BIT(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 */ + 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, draws->count, + 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, @@ -190,15 +225,39 @@ util_primconvert_draw_vbo(struct primconvert_context *pc, 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) { - trans_func(src, draw->start, draw->count, new_draw.count, info->restart_index, dst); + 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 && info->primitive_restart) { + 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, @@ -217,6 +276,8 @@ util_primconvert_draw_vbo(struct primconvert_context *pc, /* 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); } diff --git a/src/gallium/auxiliary/indices/u_primconvert.h b/src/gallium/auxiliary/indices/u_primconvert.h index a4e8892b845..0dfd5f83c67 100644 --- a/src/gallium/auxiliary/indices/u_primconvert.h +++ b/src/gallium/auxiliary/indices/u_primconvert.h @@ -37,6 +37,7 @@ struct primconvert_context; struct primconvert_config { uint32_t primtypes_mask; + uint32_t restart_primtypes_mask; bool fixed_prim_restart; }; _______________________________________________ mesa-commit mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/mesa-commit
