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 <airlied@redhat.com>
Acked-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5886>
This commit is contained in:
Mike Blumenkrantz
2020-07-11 11:19:43 -04:00
committed by Marge Bot
parent a58081f97c
commit c77a414ec2

View File

@@ -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;