From c77a414ec2d3cfde3783300afcf59e4f87826b82 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Sat, 11 Jul 2020 11:19:43 -0400 Subject: [PATCH] u_prim_restart: handle indirect draws this is pretty gross, but we need to map the indirect buffer to get the index info and then use that for mapping the index buffer and translating the restart index Reviewed-by: Dave Airlie Acked-by: Alyssa Rosenzweig Part-of: --- src/gallium/auxiliary/util/u_prim_restart.c | 76 +++++++++++++++++---- 1 file changed, 63 insertions(+), 13 deletions(-) diff --git a/src/gallium/auxiliary/util/u_prim_restart.c b/src/gallium/auxiliary/util/u_prim_restart.c index 188f49e34c4..a6bfa16dc57 100644 --- a/src/gallium/auxiliary/util/u_prim_restart.c +++ b/src/gallium/auxiliary/util/u_prim_restart.c @@ -29,6 +29,33 @@ #include "util/u_memory.h" #include "u_prim_restart.h" +typedef struct { + uint32_t count; + uint32_t primCount; + uint32_t firstIndex; + int32_t baseVertex; + uint32_t reservedMustBeZero; +} DrawElementsIndirectCommand; + +static DrawElementsIndirectCommand +read_indirect_elements(struct pipe_context *context, struct pipe_draw_indirect_info *indirect) +{ + DrawElementsIndirectCommand ret; + struct pipe_transfer *transfer = NULL; + void *map = NULL; + /* we only need the first 3 members */ + unsigned read_size = 3 * sizeof(uint32_t); + assert(indirect->buffer->width0 > 3 * sizeof(uint32_t)); + map = pipe_buffer_map_range(context, indirect->buffer, + indirect->offset, + read_size, + PIPE_TRANSFER_READ, + &transfer); + assert(map); + memcpy(&ret, map, read_size); + pipe_buffer_unmap(context, transfer); + return ret; +} /** * Translate an index buffer for primitive restart. @@ -47,15 +74,24 @@ util_translate_prim_restart_ib(struct pipe_context *context, void *src_map = NULL, *dst_map = NULL; const unsigned src_index_size = info->index_size; unsigned dst_index_size; + DrawElementsIndirectCommand indirect; + unsigned count = info->count; + unsigned start = info->start; /* 1-byte indexes are converted to 2-byte indexes, 4-byte stays 4-byte */ dst_index_size = MAX2(2, info->index_size); assert(dst_index_size == 2 || dst_index_size == 4); + if (info->indirect) { + indirect = read_indirect_elements(context, info->indirect); + count = indirect.count; + start = indirect.firstIndex; + } + /* Create new index buffer */ *dst_buffer = pipe_buffer_create(screen, PIPE_BIND_INDEX_BUFFER, PIPE_USAGE_STREAM, - info->count * dst_index_size); + count * dst_index_size); if (!*dst_buffer) goto error; @@ -66,12 +102,12 @@ util_translate_prim_restart_ib(struct pipe_context *context, goto error; if (info->has_user_indices) - src_map = (unsigned char*)info->index.user + info->start * src_index_size; + src_map = (unsigned char*)info->index.user + start * src_index_size; else /* Map original / src index buffer */ src_map = pipe_buffer_map_range(context, info->index.resource, - info->start * src_index_size, - info->count * src_index_size, + start * src_index_size, + count * src_index_size, PIPE_TRANSFER_READ, &src_transfer); if (!src_map) @@ -81,7 +117,7 @@ util_translate_prim_restart_ib(struct pipe_context *context, uint8_t *src = (uint8_t *) src_map; uint16_t *dst = (uint16_t *) dst_map; unsigned i; - for (i = 0; i < info->count; i++) { + for (i = 0; i < count; i++) { dst[i] = (src[i] == info->restart_index) ? 0xffff : src[i]; } } @@ -89,7 +125,7 @@ util_translate_prim_restart_ib(struct pipe_context *context, uint16_t *src = (uint16_t *) src_map; uint16_t *dst = (uint16_t *) dst_map; unsigned i; - for (i = 0; i < info->count; i++) { + for (i = 0; i < count; i++) { dst[i] = (src[i] == info->restart_index) ? 0xffff : src[i]; } } @@ -99,7 +135,7 @@ util_translate_prim_restart_ib(struct pipe_context *context, unsigned i; assert(src_index_size == 4); assert(dst_index_size == 4); - for (i = 0; i < info->count; i++) { + for (i = 0; i < count; i++) { dst[i] = (src[i] == info->restart_index) ? 0xffffffff : src[i]; } } @@ -183,16 +219,27 @@ util_draw_vbo_without_prim_restart(struct pipe_context *context, struct pipe_draw_info new_info; struct pipe_transfer *src_transfer = NULL; unsigned i, start, count; + DrawElementsIndirectCommand indirect; + unsigned info_start = info->start; + unsigned info_count = info->count; + unsigned info_instance_count = info->instance_count; assert(info->index_size); assert(info->primitive_restart); + if (info->indirect) { + indirect = read_indirect_elements(context, info->indirect); + info_count = indirect.count; + info_start = indirect.firstIndex; + info_instance_count = indirect.primCount; + } + /* Get pointer to the index data */ if (!info->has_user_indices) { /* map the index buffer (only the range we need to scan) */ src_map = pipe_buffer_map_range(context, info->index.resource, - info->start * info->index_size, - info->count * info->index_size, + info_start * info->index_size, + info_count * info->index_size, PIPE_TRANSFER_READ, &src_transfer); if (!src_map) { @@ -205,16 +252,16 @@ util_draw_vbo_without_prim_restart(struct pipe_context *context, return PIPE_ERROR_BAD_INPUT; } src_map = (const uint8_t *) info->index.user - + info->start * info->index_size; + + info_start * info->index_size; } #define SCAN_INDEXES(TYPE) \ - for (i = 0; i <= info->count; i++) { \ - if (i == info->count || \ + for (i = 0; i <= info_count; i++) { \ + if (i == info_count || \ ((const TYPE *) src_map)[i] == info->restart_index) { \ /* cut / restart */ \ if (count > 0) { \ - if (!add_range(&ranges, info->start + start, count)) { \ + if (!add_range(&ranges, info_start + start, count)) { \ if (src_transfer) \ pipe_buffer_unmap(context, src_transfer); \ return PIPE_ERROR_OUT_OF_MEMORY; \ @@ -251,6 +298,9 @@ util_draw_vbo_without_prim_restart(struct pipe_context *context, /* draw ranges between the restart indexes */ new_info = *info; + /* we've effectively remapped this to a direct draw */ + new_info.indirect = NULL; + new_info.instance_count = info_instance_count; new_info.primitive_restart = FALSE; for (i = 0; i < ranges.count; i++) { new_info.start = ranges.ranges[i].start; -- 2.30.2