From aa1a752979b430aeeb1b2fcdc9bc738ce9de8cc3 Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer Date: Fri, 16 Dec 2022 16:16:45 +0100 Subject: [PATCH] vbo/save: avoid dangling_attr_ref situation MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Ian Romanick Part-of: --- src/mesa/vbo/vbo_save_api.c | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index 5ed8adb..880933e 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -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]; \ -- 2.7.4