static void
u_vbuf_translate_buffers(struct u_vbuf_priv *mgr, struct translate_key *key,
unsigned vb_mask, unsigned out_vb,
- int start_vertex, unsigned num_vertices)
+ int start_vertex, unsigned num_vertices,
+ int start_index, unsigned num_indices, int min_index,
+ bool unroll_indices)
{
struct translate *tr;
struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0};
PIPE_TRANSFER_READ, &vb_transfer[i]);
}
+ /* Subtract min_index so that indexing with the index buffer works. */
+ if (unroll_indices) {
+ map -= vb->stride * min_index;
+ }
+
tr->set_buffer(tr, i, map, vb->stride, ~0);
}
}
- /* Create and map the output buffer. */
- u_upload_alloc(mgr->b.uploader,
- key->output_stride * start_vertex,
- key->output_stride * num_vertices,
- &out_offset, &out_buffer,
- (void**)&out_map);
+ /* Translate. */
+ if (unroll_indices) {
+ struct pipe_index_buffer *ib = &mgr->b.index_buffer;
+ struct pipe_transfer *transfer = NULL;
+ unsigned offset = ib->offset + start_index * ib->index_size;
+ uint8_t *map;
- out_offset -= key->output_stride * start_vertex;
+ assert(ib->buffer && ib->index_size);
- /* Translate. */
- tr->run(tr, 0, num_vertices, 0, out_map);
+ if (u_vbuf_resource(ib->buffer)->user_ptr) {
+ map = u_vbuf_resource(ib->buffer)->user_ptr + offset;
+ } else {
+ map = pipe_buffer_map_range(mgr->pipe, ib->buffer, offset,
+ num_indices * ib->index_size,
+ PIPE_TRANSFER_READ, &transfer);
+ }
+
+ /* Create and map the output buffer. */
+ u_upload_alloc(mgr->b.uploader, 0,
+ key->output_stride * num_indices,
+ &out_offset, &out_buffer,
+ (void**)&out_map);
+
+ switch (ib->index_size) {
+ case 4:
+ tr->run_elts(tr, (unsigned*)map, num_indices, 0, out_map);
+ break;
+ case 2:
+ tr->run_elts16(tr, (uint16_t*)map, num_indices, 0, out_map);
+ break;
+ case 1:
+ tr->run_elts8(tr, map, num_indices, 0, out_map);
+ break;
+ }
+
+ if (transfer) {
+ pipe_buffer_unmap(mgr->pipe, transfer);
+ }
+ } else {
+ /* Create and map the output buffer. */
+ u_upload_alloc(mgr->b.uploader,
+ key->output_stride * start_vertex,
+ key->output_stride * num_vertices,
+ &out_offset, &out_buffer,
+ (void**)&out_map);
+
+ out_offset -= key->output_stride * start_vertex;
+
+ tr->run(tr, 0, num_vertices, 0, out_map);
+ }
/* Unmap all buffers. */
for (i = 0; i < mgr->b.nr_vertex_buffers; i++) {
static boolean
u_vbuf_translate_begin(struct u_vbuf_priv *mgr,
int start_vertex, unsigned num_vertices,
- int start_instance, unsigned num_instances)
+ int start_instance, unsigned num_instances,
+ int start_index, unsigned num_indices, int min_index,
+ bool unroll_indices)
{
unsigned mask[VB_NUM] = {0};
struct translate_key key[VB_NUM];
for (i = 0; i < mgr->ve->count; i++) {
unsigned vb_index = mgr->ve->ve[i].vertex_buffer_index;
- if (!mgr->ve->incompatible_layout_elem[i] &&
- !mgr->incompatible_vb[vb_index]) {
- continue;
- }
-
if (!mgr->b.vertex_buffer[vb_index].stride) {
+ if (!mgr->ve->incompatible_layout_elem[i] &&
+ !mgr->incompatible_vb[vb_index]) {
+ continue;
+ }
mask[VB_CONST] |= 1 << vb_index;
} else if (mgr->ve->ve[i].instance_divisor) {
+ if (!mgr->ve->incompatible_layout_elem[i] &&
+ !mgr->incompatible_vb[vb_index]) {
+ continue;
+ }
mask[VB_INSTANCE] |= 1 << vb_index;
} else {
+ if (!unroll_indices &&
+ !mgr->ve->incompatible_layout_elem[i] &&
+ !mgr->incompatible_vb[vb_index]) {
+ continue;
+ }
mask[VB_VERTEX] |= 1 << vb_index;
}
}
struct translate_key *k;
struct translate_element *te;
unsigned bit, vb_index = mgr->ve->ve[i].vertex_buffer_index;
+ bit = 1 << vb_index;
if (!mgr->ve->incompatible_layout_elem[i] &&
- !mgr->incompatible_vb[vb_index]) {
+ !mgr->incompatible_vb[vb_index] &&
+ (!unroll_indices || !(mask[VB_VERTEX] & bit))) {
continue;
}
/* Set type to what we will translate.
* Whether vertex, instance, or constant attribs. */
- bit = 1 << vb_index;
for (type = 0; type < VB_NUM; type++) {
if (mask[type] & bit) {
break;
if (key[type].nr_elements) {
u_vbuf_translate_buffers(mgr, &key[type], mask[type],
mgr->fallback_vbs[type],
- start[type], num[type]);
+ start[type], num[type],
+ start_index, num_indices, min_index,
+ unroll_indices && type == VB_VERTEX);
/* Fixup the stride for constant attribs. */
if (type == VB_CONST) {
enum u_vbuf_return_flags
u_vbuf_draw_begin(struct u_vbuf *mgrb,
- const struct pipe_draw_info *info)
+ struct pipe_draw_info *info)
{
struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb;
- int start_vertex;
+ int start_vertex, min_index;
unsigned num_vertices;
+ bool unroll_indices = false;
if (!mgr->incompatible_vb_layout &&
!mgr->ve->incompatible_layout &&
}
if (info->indexed) {
- int min_index, max_index;
+ int max_index;
bool index_bounds_valid = false;
if (info->max_index != ~0) {
start_vertex = min_index + info->index_bias;
num_vertices = max_index + 1 - min_index;
+
+ /* Primitive restart doesn't work when unrolling indices.
+ * We would have to break this drawing operation into several ones. */
+ /* Use some heuristic to see if unrolling indices improves
+ * performance. */
+ if (!info->primitive_restart &&
+ num_vertices > info->count*2 &&
+ num_vertices-info->count > 32) {
+ /*printf("num_vertices=%i count=%i\n", num_vertices, info->count);*/
+ unroll_indices = true;
+ }
} else {
/* Nothing to do for per-vertex attribs. */
start_vertex = 0;
} else {
start_vertex = info->start;
num_vertices = info->count;
+ min_index = 0;
}
/* Translate vertices with non-native layouts or formats. */
- if (mgr->incompatible_vb_layout || mgr->ve->incompatible_layout) {
+ if (unroll_indices ||
+ mgr->incompatible_vb_layout ||
+ mgr->ve->incompatible_layout) {
/* XXX check the return value */
u_vbuf_translate_begin(mgr, start_vertex, num_vertices,
- info->start_instance, info->instance_count);
+ info->start_instance, info->instance_count,
+ info->start, info->count, min_index,
+ unroll_indices);
}
/* Upload user buffers. */
info->start_instance, info->instance_count);
}
- /*unsigned i;
+ /*
+ if (unroll_indices) {
+ printf("unrolling indices: start_vertex = %i, num_vertices = %i\n",
+ start_vertex, num_vertices);
+ util_dump_draw_info(stdout, info);
+ printf("\n");
+ }
+
+ unsigned i;
for (i = 0; i < mgr->b.nr_vertex_buffers; i++) {
printf("input %i: ", i);
util_dump_vertex_buffer(stdout, mgr->b.vertex_buffer+i);
printf("real %i: ", i);
util_dump_vertex_buffer(stdout, mgr->b.real_vertex_buffer+i);
printf("\n");
- }*/
+ }
+ */
+
+ if (unroll_indices) {
+ info->indexed = FALSE;
+ info->index_bias = 0;
+ info->min_index = 0;
+ info->max_index = info->count - 1;
+ info->start = 0;
+ }
return U_VBUF_BUFFERS_UPDATED;
}