enum u_vbuf_return_flags u_vbuf_draw_begin(struct u_vbuf *mgrb, const struct pipe_draw_info *info) { struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb; int min_index, max_index; if (!mgr->incompatible_vb_layout && !mgr->ve->incompatible_layout && !mgr->any_user_vbs) { return 0; } if (info->indexed) { if (info->max_index != ~0) { min_index = info->min_index + info->index_bias; max_index = info->max_index + info->index_bias; } else if (u_vbuf_need_minmax_index(mgr)) { u_vbuf_get_minmax_index(mgr->pipe, &mgr->b.index_buffer, info, &min_index, &max_index); min_index += info->index_bias; max_index += info->index_bias; } else { min_index = 0; max_index = 0; } } else { min_index = info->start; max_index = info->start + info->count - 1; } /* Translate vertices with non-native layouts or formats. */ if (mgr->incompatible_vb_layout || mgr->ve->incompatible_layout) { u_vbuf_translate_begin(mgr, min_index, max_index); } /* Upload user buffers. */ if (mgr->any_user_vbs) { u_vbuf_upload_buffers(mgr, min_index, max_index, info->instance_count); } return U_VBUF_BUFFERS_UPDATED; }
void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info) { struct pipe_context *pipe = mgr->pipe; int start_vertex, min_index; unsigned num_vertices; boolean unroll_indices = FALSE; uint32_t used_vb_mask = mgr->ve->used_vb_mask; uint32_t user_vb_mask = mgr->user_vb_mask & used_vb_mask; uint32_t incompatible_vb_mask = mgr->incompatible_vb_mask & used_vb_mask; struct pipe_draw_info new_info; /* Normal draw. No fallback and no user buffers. */ if (!incompatible_vb_mask && !mgr->ve->incompatible_elem_mask && !user_vb_mask) { /* Set vertex buffers if needed. */ 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. */ if (new_info.indirect) { struct pipe_transfer *transfer = NULL; int *data; if (new_info.indexed) { data = pipe_buffer_map_range(pipe, new_info.indirect, 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, new_info.indirect_offset, 16, PIPE_TRANSFER_READ, &transfer); new_info.start_instance = data[3]; } 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.indexed) { /* See if anything needs to be done for per-vertex attribs. */ if (u_vbuf_need_minmax_index(mgr)) { int max_index; if (new_info.max_index != ~0u) { min_index = new_info.min_index; max_index = new_info.max_index; } else { u_vbuf_get_minmax_index(mgr->pipe, &mgr->index_buffer, new_info.primitive_restart, new_info.restart_index, new_info.start, new_info.count, &min_index, &max_index); } assert(min_index <= max_index); start_vertex = min_index + new_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 (!new_info.primitive_restart && num_vertices > new_info.count*2 && num_vertices - new_info.count > 32 && !u_vbuf_mapping_vertex_buffer_blocks(mgr)) { unroll_indices = TRUE; user_vb_mask &= ~(mgr->nonzero_stride_vb_mask & mgr->ve->noninstance_vb_mask_any); } } else { /* Nothing to do for per-vertex attribs. */ start_vertex = 0; num_vertices = 0; min_index = 0; } } else { start_vertex = new_info.start; num_vertices = new_info.count; min_index = 0; } /* Translate vertices with non-native layouts or formats. */ if (unroll_indices || incompatible_vb_mask || mgr->ve->incompatible_elem_mask) { if (!u_vbuf_translate_begin(mgr, start_vertex, num_vertices, new_info.start_instance, new_info.instance_count, new_info.start, new_info.count, min_index, unroll_indices)) { debug_warn_once("u_vbuf_translate_begin() failed"); return; } if (unroll_indices) { new_info.indexed = FALSE; new_info.index_bias = 0; new_info.min_index = 0; new_info.max_index = new_info.count - 1; new_info.start = 0; } user_vb_mask &= ~(incompatible_vb_mask | mgr->ve->incompatible_vb_mask_all); } /* Upload user buffers. */ if (user_vb_mask) { if (u_vbuf_upload_buffers(mgr, start_vertex, num_vertices, new_info.start_instance, new_info.instance_count) != PIPE_OK) { debug_warn_once("u_vbuf_upload_buffers() failed"); return; } mgr->dirty_real_vb_mask |= user_vb_mask; } /* 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->nr_vertex_buffers; i++) { printf("input %i: ", i); util_dump_vertex_buffer(stdout, mgr->vertex_buffer+i); printf("\n"); } for (i = 0; i < mgr->nr_real_vertex_buffers; i++) { printf("real %i: ", i); util_dump_vertex_buffer(stdout, mgr->real_vertex_buffer+i); printf("\n"); } */ u_upload_unmap(pipe->stream_uploader); u_vbuf_set_driver_vertex_buffers(mgr); pipe->draw_vbo(pipe, &new_info); if (mgr->using_translate) { u_vbuf_translate_end(mgr); } }
void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info) { struct pipe_context *pipe = mgr->pipe; int start_vertex, min_index; unsigned num_vertices; boolean unroll_indices = FALSE; uint32_t user_vb_mask = mgr->user_vb_mask; /* Normal draw. No fallback and no user buffers. */ if (!mgr->incompatible_vb_mask && !mgr->ve->incompatible_elem_mask && !user_vb_mask) { /* Set vertex buffers if needed. */ if (mgr->vertex_buffers_dirty) { pipe->set_vertex_buffers(pipe, mgr->nr_real_vertex_buffers, mgr->real_vertex_buffer); mgr->vertex_buffers_dirty = FALSE; } pipe->draw_vbo(pipe, info); return; } if (info->indexed) { /* See if anything needs to be done for per-vertex attribs. */ if (u_vbuf_need_minmax_index(mgr)) { int max_index; if (info->max_index != ~0) { min_index = info->min_index; max_index = info->max_index; } else { u_vbuf_get_minmax_index(mgr->pipe, &mgr->index_buffer, info, &min_index, &max_index); } assert(min_index <= max_index); 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 && !u_vbuf_mapping_vertex_buffer_blocks(mgr)) { /*printf("num_vertices=%i count=%i\n", num_vertices, info->count);*/ unroll_indices = TRUE; user_vb_mask &= ~(mgr->nonzero_stride_vb_mask & mgr->ve->noninstance_vb_mask_any); } } else { /* Nothing to do for per-vertex attribs. */ start_vertex = 0; num_vertices = 0; min_index = 0; } } else { start_vertex = info->start; num_vertices = info->count; min_index = 0; } /* Translate vertices with non-native layouts or formats. */ if (unroll_indices || mgr->incompatible_vb_mask || mgr->ve->incompatible_elem_mask) { /* XXX check the return value */ u_vbuf_translate_begin(mgr, start_vertex, num_vertices, info->start_instance, info->instance_count, info->start, info->count, min_index, unroll_indices); user_vb_mask &= ~(mgr->incompatible_vb_mask | mgr->ve->incompatible_vb_mask_all); } /* Upload user buffers. */ if (user_vb_mask) { u_vbuf_upload_buffers(mgr, start_vertex, num_vertices, info->start_instance, info->instance_count); } /* 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->nr_vertex_buffers; i++) { printf("input %i: ", i); util_dump_vertex_buffer(stdout, mgr->vertex_buffer+i); printf("\n"); } for (i = 0; i < mgr->nr_real_vertex_buffers; i++) { printf("real %i: ", i); util_dump_vertex_buffer(stdout, mgr->real_vertex_buffer+i); printf("\n"); } */ u_upload_unmap(mgr->uploader); pipe->set_vertex_buffers(pipe, mgr->nr_real_vertex_buffers, mgr->real_vertex_buffer); if (unlikely(unroll_indices)) { struct pipe_draw_info new_info = *info; new_info.indexed = FALSE; new_info.index_bias = 0; new_info.min_index = 0; new_info.max_index = info->count - 1; new_info.start = 0; pipe->draw_vbo(pipe, &new_info); } else { pipe->draw_vbo(pipe, info); } if (mgr->using_translate) { u_vbuf_translate_end(mgr); } mgr->vertex_buffers_dirty = TRUE; }