to skip atomics in u_threaded_context. This will decrease CPU overhead.
Reviewed-by: Zoltán Böszörményi <zboszor@gmail.com>
Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8298>
struct u_vbuf *vbuf = cso->vbuf_current;
if (vbuf) {
+ /* Increase refcount to be able to use take_index_buffer_ownership with
+ * all draws.
+ */
+ if (num_draws > 1 && info->take_index_buffer_ownership)
+ p_atomic_add(&info->index.resource->reference.count, num_draws - 1);
+
for (unsigned i = 0; i < num_draws; i++) {
- if (draws[i].count)
- u_vbuf_draw_vbo(vbuf, info, NULL, draws[i]);
+ u_vbuf_draw_vbo(vbuf, info, NULL, draws[i]);
if (info->increment_draw_id)
info->drawid++;
*/
info->has_user_indices = false;
info->index_bounds_valid = false;
+ info->take_index_buffer_ownership = false;
info->_pad = 0;
/* This shouldn't be set when merging single draws. */
info->info.index_bounds_valid = false;
info->info.has_user_indices = false;
+ info->info.take_index_buffer_ownership = false;
pipe->draw_vbo(pipe, &info->info, NULL, draw, 1);
if (info->info.index_size)
struct tc_draw_indirect *info = (struct tc_draw_indirect*)payload;
info->info.index_bounds_valid = false;
+ info->info.take_index_buffer_ownership = false;
pipe->draw_vbo(pipe, &info->info, &info->indirect, &info->draw, 1);
if (info->info.index_size)
info->info.has_user_indices = false;
info->info.index_bounds_valid = false;
+ info->info.take_index_buffer_ownership = false;
pipe->draw_vbo(pipe, &info->info, NULL, info->slot, info->num_draws);
if (info->info.index_size)
struct tc_draw_indirect *p =
tc_add_struct_typed_call(tc, TC_CALL_draw_indirect, tc_draw_indirect);
- if (index_size) {
+ if (index_size && !info->take_index_buffer_ownership) {
tc_set_resource_reference(&p->info.index.resource,
info->index.resource);
}
/* Non-indexed call or indexed with a real index buffer. */
struct tc_draw_single *p =
tc_add_struct_typed_call(tc, TC_CALL_draw_single, tc_draw_single);
- if (index_size) {
+ if (index_size && !info->take_index_buffer_ownership) {
tc_set_resource_reference(&p->info.index.resource,
info->index.resource);
}
struct tc_draw_multi *p =
tc_add_slot_based_call(tc, TC_CALL_draw_multi, tc_draw_multi,
num_draws);
- if (index_size) {
+ if (index_size && !info->take_index_buffer_ownership) {
tc_set_resource_reference(&p->info.index.resource,
info->index.resource);
}
unsigned *indirect_data, unsigned stride,
unsigned draw_count)
{
+ /* Increase refcount to be able to use take_index_buffer_ownership with
+ * all draws.
+ */
+ if (draw_count > 1 && info->take_index_buffer_ownership)
+ p_atomic_add(&info->index.resource->reference.count, draw_count - 1);
+
assert(info->index_size);
for (unsigned i = 0; i < draw_count; i++) {
draw.count = indirect_data[offset + 0];
info->instance_count = indirect_data[offset + 1];
-
- if (!draw.count || !info->instance_count)
- continue;
-
draw.start = indirect_data[offset + 2];
info->index_bias = indirect_data[offset + 3];
info->start_instance = indirect_data[offset + 4];
}
if (!draw_count)
- return;
+ goto cleanup;
unsigned data_size = (draw_count - 1) * indirect->stride +
(new_info.index_size ? 20 : 16);
unsigned *data = malloc(data_size);
if (!data)
- return; /* report an error? */
+ goto cleanup; /* report an error? */
/* Read the used buffer range only once, because the read can be
* uncached.
new_info.instance_count = end_instance - new_info.start_instance;
if (new_info.start_instance == ~0u || !new_info.instance_count)
- return;
+ goto cleanup;
} else {
/* Non-indexed multidraw.
*
new_info.instance_count = end_instance - new_info.start_instance;
if (new_draw.start == ~0u || !new_draw.count || !new_info.instance_count)
- return;
+ goto cleanup;
}
}
start_vertex, num_vertices,
min_index, unroll_indices)) {
debug_warn_once("u_vbuf_translate_begin() failed");
- return;
+ goto cleanup;
}
if (unroll_indices) {
new_info.start_instance,
new_info.instance_count) != PIPE_OK) {
debug_warn_once("u_vbuf_upload_buffers() failed");
- return;
+ goto cleanup;
}
mgr->dirty_real_vb_mask |= user_vb_mask;
if (mgr->using_translate) {
u_vbuf_translate_end(mgr);
}
+ return;
+
+cleanup:
+ if (info->take_index_buffer_ownership) {
+ struct pipe_resource *indexbuf = info->index.resource;
+ pipe_resource_reference(&indexbuf, NULL);
+ }
}
void u_vbuf_save_vertex_elements(struct u_vbuf *mgr)
bool index_bounds_valid:1; /**< whether min_index and max_index are valid;
they're always invalid if index_size == 0 */
bool increment_draw_id:1; /**< whether drawid increments for direct draws */
- char _pad:4; /**< padding for memcmp */
+ bool take_index_buffer_ownership:1; /**< callee inherits caller's refcount
+ (no need to reference indexbuf, but still needs to unreference it) */
+ char _pad:3; /**< padding for memcmp */
unsigned start_instance; /**< first instance id */
unsigned instance_count; /**< number of instances */
info.has_user_indices = false;
info.index_bounds_valid = true;
info.increment_draw_id = false;
+ info.take_index_buffer_ownership = false;
info._pad = 0;
/* Packed section end. */
info.start_instance = baseInstance;
info.has_user_indices = false;
info.index_bounds_valid = false;
info.increment_draw_id = primcount > 1;
+ info.take_index_buffer_ownership = false;
info._pad = 0;
/* Packed section end. */
info.start_instance = 0;
info.has_user_indices = index_bo == NULL;
info.index_bounds_valid = index_bounds_valid;
info.increment_draw_id = false;
+ info.take_index_buffer_ownership = false;
info._pad = 0;
/* Packed section end. */
info.start_instance = baseInstance;
info.has_user_indices = index_bo == NULL;
info.index_bounds_valid = false;
info.increment_draw_id = primcount > 1;
+ info.take_index_buffer_ownership = false;
info._pad = 0;
/* Packed section end. */
info.start_instance = 0;
info.restart_index = 0;
info.start_instance = base_instance;
info.instance_count = num_instances;
+ info.take_index_buffer_ownership = false;
info._pad = 0;
if (ib) {
info->mode = mode[first];
cso_multi_draw(cso, info, &draws[first], i - first);
first = i;
+
+ /* We can pass the reference only once. st_buffer_object keeps
+ * the reference alive for later draws.
+ */
+ info->take_index_buffer_ownership = false;
}
}
break;
info->index_bias = base_vertex[first];
cso_multi_draw(cso, info, &draws[first], i - first);
first = i;
+
+ /* We can pass the reference only once. st_buffer_object keeps
+ * the reference alive for later draws.
+ */
+ info->take_index_buffer_ownership = false;
}
}
break;
info->index_bias = base_vertex[first];
cso_multi_draw(cso, info, &draws[first], i - first);
first = i;
+
+ /* We can pass the reference only once. st_buffer_object keeps
+ * the reference alive for later draws.
+ */
+ info->take_index_buffer_ownership = false;
}
}
break;
/* Initialize pipe_draw_info. */
info.primitive_restart = false;
+ info.take_index_buffer_ownership = false;
info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
info.restart_index = 0;