Bug 60518

Summary: glDrawElements segfault when compiled into display list
Product: Mesa Reporter: Sergej Forat <core13>
Component: Mesa coreAssignee: mesa-dev
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: medium    
Version: 9.0   
Hardware: x86-64 (AMD64)   
OS: Linux (All)   
Whiteboard:
i915 platform: i915 features:

Description Sergej Forat 2013-02-08 21:55:06 UTC
VDrift git on a Fedora 18 box (Linux 3.7.6-201.fc18.x86_64, 2.1 Mesa 9.0.1) will segfault in the GL2/1 fallback path:

Program received signal SIGSEGV, Segmentation fault.
0x00007fffed92461b in _save_VertexAttrib4fvARB (index=<optimized out>, v=0x0) at ../../../src/mesa/vbo/vbo_attrib_tmp.h:547
547	      ATTR4FV(VBO_ATTRIB_GENERIC0 + index, v);
(gdb) bt
#0  0x00007fffed92461b in _save_VertexAttrib4fvARB (index=<optimized out>, v=0x0)
    at ../../../src/mesa/vbo/vbo_attrib_tmp.h:547
#1  0x00007fffed828a1a in _ae_ArrayElement (elt=0) at ../../../src/mesa/main/api_arrayelt.c:1670
#2  0x00007fffed9197bd in _save_OBE_DrawElements (mode=4, count=<optimized out>, type=<optimized out>, 
    indices=<optimized out>) at ../../../src/mesa/vbo/vbo_save_api.c:1252
#3  0x000000000058bfb9 in MODEL::GenerateListID (this=0x9e7080, error_output=...) at src/graphics/model.cpp:185
#4  0x000000000058b8b3 in MODEL::Load (this=0x9e7080, varray=..., error_output=..., genlist=true)
    at src/graphics/model.cpp:85


The code looks like this (with vertex, texcoord, normal pointers set):

glNewList(listid, GL_COMPILE);
glDrawElements(GL_TRIANGLES, facecount, GL_UNSIGNED_INT, faces);
glEndList();


Apitrace attached.
Comment 1 Sergej Forat 2013-02-08 22:33:09 UTC
Apitrace download link (attaching failed due to size):

http://www.gamefront.com/files/22931297/vdrift.trace.gz
Comment 2 Sergej Forat 2013-05-22 15:55:38 UTC
A workaround for the segfault is to explicitly disable vertex attribute arrays:
GLint n = 0;
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &n);
for (GLint i = 0; i < n; ++i)
    glDisableVertexAttribArray(i);

Which is weird, as they are not used at all. But hey, whatever...
Comment 3 Sergej Forat 2013-05-28 19:48:36 UTC
I've had another look at the trace created with apitrace. And it looks like the issue is caused by glGenerateMipmap(GL_TEXTURE_2D). It seems to use the first and second vertex attribute array, but doesn't disable them afterwards.

So the revised workaround is disable them explicitly after each glGenerateMipmap call:

glGenerateMipmap(GL_TEXTURE_2D);
// mesa bugfix
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
Comment 4 Brian Paul 2013-05-29 17:55:54 UTC
The link to the trace doesn't work.  Can you attach the trace to this bug report?

Which Mesa driver are you using?
Comment 5 Sergej Forat 2013-05-30 11:24:25 UTC
(In reply to comment #4)
> The link to the trace doesn't work.  Can you attach the trace to this bug
> report?
> 
> Which Mesa driver are you using?

(II) intel(0): [DRI2] DRI driver: i965

OpenGL info (two machines tested on)
GL Vendor: Intel Open Source Technology Center
GL Renderer: Mesa DRI Mobile Intel® GM45 Express Chipset 
GL Version: 2.1 Mesa 9.1

GL Vendor: Intel Open Source Technology Center
GL Renderer: Mesa DRI Intel® Ivybridge Mobile
GL Version: 3.0 Mesa 9.1.2

Apitrace link (too large to be attached):
http://sourceforge.net/projects/vdrift/files/vdrift/nightly%20builds/vdrift.trace.bz2/download

The two calls to glVertexAttribPointer are not done by the application btw. It doesn't touch vertex attribs at all on Linux/Mesa.
Comment 6 Jose Fonseca 2013-05-30 21:41:49 UTC
Sounds like the glGenerateMipmap implementation (likely Meta module) is clobbering the GL_VERTEX_ATTRIB_ARRAY_ENABLED* state.

> The two calls to glVertexAttribPointer are not done by the application btw. It doesn't touch vertex attribs at all on Linux/Mesa.

Apitrace asks the OpenGL driver whether vertex attribs are enabled or not, and will emit fake glVertexAttribPointer calls on every draw call (as only then it knows how big is the user pointer memory).
Comment 7 Jose Fonseca 2013-05-30 21:52:36 UTC
I suspect the problem are these lines in setup_glsl_generate_mipmap():

   _mesa_BindAttribLocation(mipmap->ShaderProg, 0, "position");
   _mesa_BindAttribLocation(mipmap->ShaderProg, 1, "texcoords");
   _mesa_EnableVertexAttribArray(0);
   _mesa_EnableVertexAttribArray(1);

Which can be executed without this line being called:

   _mesa_BindVertexArray(mipmap->ArrayObj);

This patch might fix this.

diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
index ca5f5a1..7da08e8 100644
--- a/src/mesa/drivers/common/meta.c
+++ b/src/mesa/drivers/common/meta.c
@@ -3397,6 +3397,8 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
                                    sizeof(struct vertex), OFFSET(x));
       _mesa_VertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
                                    sizeof(struct vertex), OFFSET(tex));
+   } else {
+      _mesa_BindVertexArray(mipmap->ArrayObj);
    }
 
    /* Generate a fragment shader program appropriate for the texture target */
Comment 8 Sergej Forat 2013-05-31 10:18:31 UTC
(In reply to comment #7)
> I suspect the problem are these lines in setup_glsl_generate_mipmap():
> 
>    _mesa_BindAttribLocation(mipmap->ShaderProg, 0, "position");
>    _mesa_BindAttribLocation(mipmap->ShaderProg, 1, "texcoords");
>    _mesa_EnableVertexAttribArray(0);
>    _mesa_EnableVertexAttribArray(1);
> 
> Which can be executed without this line being called:
> 
>    _mesa_BindVertexArray(mipmap->ArrayObj);
> 
> This patch might fix this.
> 
> diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
> index ca5f5a1..7da08e8 100644
> --- a/src/mesa/drivers/common/meta.c
> +++ b/src/mesa/drivers/common/meta.c
> @@ -3397,6 +3397,8 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
>                                     sizeof(struct vertex), OFFSET(x));
>        _mesa_VertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
>                                     sizeof(struct vertex), OFFSET(tex));
> +   } else {
> +      _mesa_BindVertexArray(mipmap->ArrayObj);
>     }
>  
>     /* Generate a fragment shader program appropriate for the texture target
> */

Yep, no segfaults with this patch. Tested with mesa git, i965. Thanks, for looking into this, José.
Comment 9 Brian Paul 2013-05-31 14:01:59 UTC
Jose, I think it would be more symmetric with the peer setup_ff_generate_mipmap() function if we just enabled the vertex arrays when we create the vertex array object.  So, how about this patch:

diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
index ca5f5a1..1ab603a 100644
--- a/src/mesa/drivers/common/meta.c
+++ b/src/mesa/drivers/common/meta.c
@@ -3397,6 +3397,8 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
                                    sizeof(struct vertex), OFFSET(x));
       _mesa_VertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
                                    sizeof(struct vertex), OFFSET(tex));
+      _mesa_EnableVertexAttribArray(0);
+      _mesa_EnableVertexAttribArray(1);
    }
 
    /* Generate a fragment shader program appropriate for the texture target */
@@ -3468,8 +3470,6 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
    _mesa_DeleteObjectARB(vs);
    _mesa_BindAttribLocation(mipmap->ShaderProg, 0, "position");
    _mesa_BindAttribLocation(mipmap->ShaderProg, 1, "texcoords");
-   _mesa_EnableVertexAttribArray(0);
-   _mesa_EnableVertexAttribArray(1);
    link_program_with_debug(ctx, mipmap->ShaderProg);
    sampler->shader_prog = mipmap->ShaderProg;
    ralloc_free(mem_ctx);


Can you test that approach, core13?
Comment 10 Sergej Forat 2013-05-31 15:10:15 UTC
(In reply to comment #9)
> Jose, I think it would be more symmetric with the peer
> setup_ff_generate_mipmap() function if we just enabled the vertex arrays
> when we create the vertex array object.  So, how about this patch:
> 
> diff --git a/src/mesa/drivers/common/meta.c b/src/mesa/drivers/common/meta.c
> index ca5f5a1..1ab603a 100644
> --- a/src/mesa/drivers/common/meta.c
> +++ b/src/mesa/drivers/common/meta.c
> @@ -3397,6 +3397,8 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
>                                     sizeof(struct vertex), OFFSET(x));
>        _mesa_VertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,
>                                     sizeof(struct vertex), OFFSET(tex));
> +      _mesa_EnableVertexAttribArray(0);
> +      _mesa_EnableVertexAttribArray(1);
>     }
>  
>     /* Generate a fragment shader program appropriate for the texture target
> */
> @@ -3468,8 +3470,6 @@ setup_glsl_generate_mipmap(struct gl_context *ctx,
>     _mesa_DeleteObjectARB(vs);
>     _mesa_BindAttribLocation(mipmap->ShaderProg, 0, "position");
>     _mesa_BindAttribLocation(mipmap->ShaderProg, 1, "texcoords");
> -   _mesa_EnableVertexAttribArray(0);
> -   _mesa_EnableVertexAttribArray(1);
>     link_program_with_debug(ctx, mipmap->ShaderProg);
>     sampler->shader_prog = mipmap->ShaderProg;
>     ralloc_free(mem_ctx);
> 
> 
> Can you test that approach, core13?

This one works too, no segfaults.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.