vbo/save: avoid dangling_attr_ref situation

dangling_attr_ref=true can be set when the following happens:

  glBegin(GL_TRIANGLES)
  glVertex(...)
  glVertex(...)
  glColor4(...)
  glVertex(...)

When glColor4 is hit, the first 2 vertices are copied to the vertex_store
by upgrade_vertex, but since this is done before glColor4 new values are
copied, we make a note to fixup these attribute laters using dangling_attr_ref.

This causes very slow rendering. What this commit does instead, is in this
situation, the new attribute value are backported to the vertex store for the
copied vertices after upgrade_vertex is done updating the layout.

This avoids the slow corner case.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/7912

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20495>
This commit is contained in:
Pierre-Eric Pelloux-Prayer
2022-12-16 16:16:45 +01:00
committed by Marge Bot
parent a9ab06668f
commit aa1a752979
+33 -5
View File
@@ -1175,7 +1175,9 @@ upgrade_vertex(struct gl_context *ctx, GLuint attr, GLuint newsz)
grow_vertex_storage(ctx, save->copied.nr);
fi_type *dest = save->vertex_store->buffer_in_ram;
/* Need to note this and fix up at runtime (or loopback):
/* Need to note this and fix up later. This can be done in
* ATTR_UNION (by copying the new attribute values to the
* vertices we're copying here) or at runtime (or loopback).
*/
if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) {
assert(oldsz == 0);
@@ -1234,13 +1236,14 @@ upgrade_vertex(struct gl_context *ctx, GLuint attr, GLuint newsz)
* For example, after seeing one or more glTexCoord2f() calls we
* get a glTexCoord4f() or glTexCoord1f() call.
*/
static void
static bool
fixup_vertex(struct gl_context *ctx, GLuint attr,
GLuint sz, GLenum newType)
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
bool new_attr_is_bigger = sz > save->attrsz[attr];
if (sz > save->attrsz[attr] ||
if (new_attr_is_bigger ||
newType != save->attrtype[attr]) {
/* New size is larger. Need to flush existing vertices and get
* an enlarged vertex format.
@@ -1261,6 +1264,8 @@ fixup_vertex(struct gl_context *ctx, GLuint attr,
save->active_sz[attr] = sz;
grow_vertex_storage(ctx, 1);
return new_attr_is_bigger;
}
@@ -1314,8 +1319,31 @@ do { \
struct vbo_save_context *save = &vbo_context(ctx)->save; \
int sz = (sizeof(C) / sizeof(GLfloat)); \
\
if (save->active_sz[A] != N) \
fixup_vertex(ctx, A, N * sz, T); \
if (save->active_sz[A] != N) { \
bool had_dangling_ref = save->dangling_attr_ref; \
fi_type *dest = save->vertex_store->buffer_in_ram; \
if (fixup_vertex(ctx, A, N * sz, T) && \
!had_dangling_ref && save->dangling_attr_ref && \
A != VBO_ATTRIB_POS) { \
/* Copy the new attr values to the already copied \
* vertices. \
*/ \
for (int i = 0; i < save->copied.nr; i++) { \
GLbitfield64 enabled = save->enabled; \
while (enabled) { \
const int j = u_bit_scan64(&enabled); \
if (j == A) { \
if (N>0) ((C*) dest)[0] = V0; \
if (N>1) ((C*) dest)[1] = V1; \
if (N>2) ((C*) dest)[2] = V2; \
if (N>3) ((C*) dest)[3] = V3; \
} \
dest += save->attrsz[j]; \
} \
} \
save->dangling_attr_ref = false; \
} \
} \
\
{ \
C *dest = (C *)save->attrptr[A]; \