Marek Olšák <mar...@gmail.com> writes: > From: Marek Olšák <marek.ol...@amd.com> > > v2: need to do MAX{start+count} instead of MAX{count} > added piglit tests > --- > src/gallium/auxiliary/util/u_vbuf.c | 199 ++++++++++++++++++++++++---- > 1 file changed, 175 insertions(+), 24 deletions(-) > > diff --git a/src/gallium/auxiliary/util/u_vbuf.c > b/src/gallium/auxiliary/util/u_vbuf.c > index 746ff1085ce..ca53e6218fd 100644 > --- a/src/gallium/auxiliary/util/u_vbuf.c > +++ b/src/gallium/auxiliary/util/u_vbuf.c > @@ -1124,20 +1124,45 @@ static void u_vbuf_set_driver_vertex_buffers(struct > u_vbuf *mgr) > unsigned start_slot, count; > > start_slot = ffs(mgr->dirty_real_vb_mask) - 1; > count = util_last_bit(mgr->dirty_real_vb_mask >> start_slot); > > pipe->set_vertex_buffers(pipe, start_slot, count, > mgr->real_vertex_buffer + start_slot); > mgr->dirty_real_vb_mask = 0; > } > > +static void > +u_vbuf_split_indexed_multidraw(struct u_vbuf *mgr, struct pipe_draw_info > *info, > + unsigned *indirect_data, unsigned stride, > + unsigned draw_count) > +{ > + assert(info->index_size); > + info->indirect = NULL; > + > + for (unsigned i = 0; i < draw_count; i++) { > + unsigned offset = i * stride / 4; > + > + info->count = indirect_data[offset + 0]; > + info->instance_count = indirect_data[offset + 1]; > + > + if (!info->count || !info->instance_count) > + continue; > + > + info->start = indirect_data[offset + 2]; > + info->index_bias = indirect_data[offset + 3]; > + info->start_instance = indirect_data[offset + 4]; > + > + u_vbuf_draw_vbo(mgr, info); > + } > +} > + > void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info) > { > struct pipe_context *pipe = mgr->pipe; > int start_vertex; > unsigned min_index; > unsigned num_vertices; > boolean unroll_indices = FALSE; > const uint32_t used_vb_mask = mgr->ve->used_vb_mask; > uint32_t user_vb_mask = mgr->user_vb_mask & used_vb_mask; > const uint32_t incompatible_vb_mask = > @@ -1153,47 +1178,172 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const > struct pipe_draw_info *info) > if (mgr->dirty_real_vb_mask & used_vb_mask) { > u_vbuf_set_driver_vertex_buffers(mgr); > } > > pipe->draw_vbo(pipe, info); > return; > } > > new_info = *info; > > - /* Fallback. We need to know all the parameters. */ > + /* Handle indirect (multi)draws. */ > if (new_info.indirect) { > - struct pipe_transfer *transfer = NULL; > - int *data; > - > - if (new_info.index_size) { > - data = pipe_buffer_map_range(pipe, new_info.indirect->buffer, > - new_info.indirect->offset, 20, > - PIPE_TRANSFER_READ, &transfer); > - new_info.index_bias = data[3]; > - new_info.start_instance = data[4]; > - } > - else { > - data = pipe_buffer_map_range(pipe, new_info.indirect->buffer, > - new_info.indirect->offset, 16, > - PIPE_TRANSFER_READ, &transfer); > - new_info.start_instance = data[3]; > + const struct pipe_draw_indirect_info *indirect = new_info.indirect; > + unsigned draw_count = 0; > + > + /* Get the number of draws. */ > + if (indirect->indirect_draw_count) { > + pipe_buffer_read(pipe, indirect->indirect_draw_count, > + indirect->indirect_draw_count_offset, > + 4, &draw_count); > + } else { > + draw_count = indirect->draw_count; > } > > - new_info.count = data[0]; > - new_info.instance_count = data[1]; > - new_info.start = data[2]; > - pipe_buffer_unmap(pipe, transfer); > - new_info.indirect = NULL; > - > - if (!new_info.count) > + if (!draw_count) > return; > + > + unsigned data_size = (draw_count - 1) * indirect->stride + > + (new_info.index_size ? 20 : 16); > + unsigned *data = alloca(data_size);
I continue to believe that alloca isn't something we should be using on unbounded data_size like this. We should be returing GL_OUT_OF_MEMORY when we fail, not segfaulting. We're already reading back the BOs, it's not like the allocation is a performance concern at this point.
signature.asc
Description: PGP signature
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev