vbo: optimize resizing vertex attributes during immediate mode

Just move data manually instead of copying all attributes back and forth.

This increases performance by 5% for Viewperf11/Catia - first scene.

Reviewed-by: Mathias Fröhlich <mathias.froehlich@web.de>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3766>
This commit is contained in:
Marek Olšák 2020-01-29 22:09:20 -05:00 committed by Marge Bot
parent 1f6e53e243
commit 077a843c27

View file

@ -230,35 +230,6 @@ vbo_exec_copy_to_current(struct vbo_exec_context *exec)
}
/**
* Copy current vertex attribute values into the current vertex.
*/
static void
vbo_exec_copy_from_current(struct vbo_exec_context *exec)
{
struct gl_context *ctx = exec->ctx;
struct vbo_context *vbo = vbo_context(ctx);
GLint i;
for (i = VBO_ATTRIB_POS + 1; i < VBO_ATTRIB_MAX; i++) {
if (exec->vtx.attr[i].type == GL_DOUBLE ||
exec->vtx.attr[i].type == GL_UNSIGNED_INT64_ARB) {
memcpy(exec->vtx.attrptr[i], vbo->current[i].Ptr,
exec->vtx.attr[i].size * sizeof(GLfloat));
} else {
const fi_type *current = (fi_type *) vbo->current[i].Ptr;
switch (exec->vtx.attr[i].size) {
case 4: exec->vtx.attrptr[i][3] = current[3];
case 3: exec->vtx.attrptr[i][2] = current[2];
case 2: exec->vtx.attrptr[i][1] = current[1];
case 1: exec->vtx.attrptr[i][0] = current[0];
break;
}
}
}
}
/**
* Flush existing data, set new attrib size, replay copied vertices.
* This is called when we transition from a small vertex attribute size
@ -275,6 +246,7 @@ vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
struct vbo_context *vbo = vbo_context(ctx);
const GLint lastcount = exec->vtx.vert_count;
fi_type *old_attrptr[VBO_ATTRIB_MAX];
const GLuint old_vtx_size_no_pos = exec->vtx.vertex_size_no_pos;
const GLuint old_vtx_size = exec->vtx.vertex_size; /* floats per vertex */
const GLuint oldSize = exec->vtx.attr[attr].size;
GLuint i;
@ -294,16 +266,6 @@ vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr));
}
bool repopulate = unlikely(oldSize) || (attr != 0 && exec->vtx.attr[0].size);
if (repopulate) {
/* Do a COPY_TO_CURRENT to ensure back-copying works for the
* case when the attribute already exists in the vertex and is
* having its size increased.
*/
vbo_exec_copy_to_current(exec);
}
/* Heuristic: Attempt to isolate attributes received outside
* begin/end so that they don't bloat the vertices.
*/
@ -323,33 +285,62 @@ vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
exec->vtx.buffer_ptr = exec->vtx.buffer_map;
exec->vtx.enabled |= BITFIELD64_BIT(attr);
if (repopulate) {
/* Size changed, recalculate all the attrptr[] values
*/
fi_type *tmp = exec->vtx.vertex;
if (attr != 0) {
if (unlikely(oldSize)) {
unsigned offset = exec->vtx.attrptr[attr] - exec->vtx.vertex;
/* Iterate backwards to make the position last, because glVertex
* expects that.
*/
for (int i = VBO_ATTRIB_MAX - 1; i >= 0; i--) {
if (exec->vtx.attr[i].size) {
exec->vtx.attrptr[i] = tmp;
tmp += exec->vtx.attr[i].size;
/* If there are attribs after the resized attrib... */
if (offset + oldSize < old_vtx_size_no_pos) {
int size_diff = newSize - oldSize;
fi_type *old_first = exec->vtx.attrptr[attr] + oldSize;
fi_type *new_first = exec->vtx.attrptr[attr] + newSize;
fi_type *old_last = exec->vtx.vertex + old_vtx_size_no_pos - 1;
fi_type *new_last = exec->vtx.vertex + exec->vtx.vertex_size_no_pos - 1;
if (size_diff < 0) {
/* Decreasing the size: Copy from first to last to move
* elements to the left.
*/
fi_type *old_end = old_last + 1;
fi_type *old = old_first;
fi_type *new = new_first;
do {
*new++ = *old++;
} while (old != old_end);
} else {
/* Increasing the size: Copy from last to first to move
* elements to the right.
*/
fi_type *old_end = old_first - 1;
fi_type *old = old_last;
fi_type *new = new_last;
do {
*new-- = *old--;
} while (old != old_end);
}
/* Update pointers to attribs, because we moved them. */
GLbitfield64 enabled = exec->vtx.enabled &
~BITFIELD64_BIT(VBO_ATTRIB_POS) &
~BITFIELD64_BIT(attr);
while (enabled) {
unsigned i = u_bit_scan64(&enabled);
if (exec->vtx.attrptr[i] > exec->vtx.attrptr[attr])
exec->vtx.attrptr[i] += size_diff;
}
}
else
exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */
} else {
/* Just have to append the new attribute at the end */
exec->vtx.attrptr[attr] = exec->vtx.vertex +
exec->vtx.vertex_size_no_pos - newSize;
}
}
/* Copy from current to repopulate the vertex with correct
* values.
*/
vbo_exec_copy_from_current(exec);
}
else {
/* Just have to append the new attribute at the end */
exec->vtx.attrptr[attr] = exec->vtx.vertex +
exec->vtx.vertex_size - newSize;
}
/* The position is always last. */
exec->vtx.attrptr[0] = exec->vtx.vertex + exec->vtx.vertex_size_no_pos;
/* Replay stored vertices to translate them
* to new format here.