Attached example program shows a memory leak from brwNewProgram for shader type GL_COMPUTE_SHADER ltraces shows glDeleteProgram is called however doesn't call brwDeleteProgram for the compute_shader program. //gcc compute_shader_test.c -lGL -lX11 -o compute_shader_test #include <stdio.h> #include <stdlib.h> #define GL_GLEXT_PROTOTYPES #include <GL/glx.h> #include <GL/gl.h> #include <GL/glext.h> typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); int main (int argc, char ** argv) { Display *display = XOpenDisplay(0); glXCreateContextAttribsARBProc glXCreateContextAttribsARB = NULL; const char *extensions = glXQueryExtensionsString(display, DefaultScreen(display)); static int visual_attribs[] = { GLX_RENDER_TYPE, GLX_RGBA_BIT, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, GLX_DOUBLEBUFFER, 1, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, None }; int fbcount; GLXFBConfig *fbc = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount); if (!fbc) return 1; XVisualInfo *vi = glXGetVisualFromFBConfig(display, fbc[0]); XSetWindowAttributes swa; swa.colormap = XCreateColormap(display, RootWindow(display, vi->screen), vi->visual, AllocNone); swa.border_pixel = 0; swa.event_mask = StructureNotifyMask; Window win = XCreateWindow(display, RootWindow(display, vi->screen), 0, 0, 100, 100, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel|CWColormap|CWEventMask, &swa); if (!win) return 1; GLXContext ctx_old = glXCreateContext(display, vi, 0, GL_TRUE); glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); glXMakeCurrent(display, 0, 0); glXDestroyContext(display, ctx_old); if (glXCreateContextAttribsARB == NULL) return 1; static int context_attribs[] = { GLX_CONTEXT_MAJOR_VERSION_ARB, 4, GLX_CONTEXT_MINOR_VERSION_ARB, 5, None }; GLXContext ctx = glXCreateContextAttribsARB(display, fbc[0], NULL, GL_TRUE, context_attribs); if (!ctx) return 1; glXMakeCurrent(display, win, ctx); GLuint csp = glCreateProgram(); GLuint cs = glCreateShader(GL_COMPUTE_SHADER); const char *src[] = { "#version 450\n", "writeonly uniform image2D destTex;\ layout (local_size_x = 16, local_size_y = 16) in;\ void main() {\ ivec2 storePos = ivec2(gl_GlobalInvocationID.xy);\ imageStore(destTex, storePos, vec4(0.0, 0.0, 0.0, 0.0));\ }" }; glShaderSource(cs, 2, src, NULL); glCompileShader(cs); int rvalue; glGetShaderiv(cs, GL_COMPILE_STATUS, &rvalue); if (!rvalue) { fprintf(stderr, "Error in compiling the compute shader\n"); GLchar log[10240]; GLsizei length; glGetShaderInfoLog(cs, 10239, &length, log); fprintf(stderr, "Compiler log:\n%s\n", log); exit(40); } glAttachShader(csp, cs); glDeleteShader(cs); glLinkProgram(csp); glGetProgramiv(csp, GL_LINK_STATUS, &rvalue); if (!rvalue) { fprintf(stderr, "Error in linking compute shader program\n"); GLchar log[10240]; GLsizei length; glGetProgramInfoLog(csp, 10239, &length, log); fprintf(stderr, "Linker log:\n%s\n", log); exit(41); } glUseProgram(csp); glUniform1i(glGetUniformLocation(csp, "destTex"), 0); glDispatchCompute(512/16, 512/16, 1); glDeleteProgram(csp); glXMakeCurrent(display, 0, 0); glXDestroyContext(display, ctx); XFree(fbc); XFreeColormap(display, swa.colormap); XFree(vi); XCloseDisplay(display); return 0; } ltrace ./compute_shader_test XOpenDisplay(nil) = 0x55d1fb3c7010 glXQueryExtensionsString(0x55d1fb3c7010, 0, 0, 0) = 0x55d1fb3df650 glXChooseFBConfig(0x55d1fb3c7010, 0, 0x55d1fa992140, 0x7ffd7f0cb754) = 0x55d1fb3df940 glXGetVisualFromFBConfig(0x55d1fb3c7010, 0x55d1fb513d30, 0x55d1fb513d30, 0x55d1fb3dfa28) = 0x55d1fb3dfb50 XCreateColormap(0x55d1fb3c7010, 246, 0x55d1fb3c8be8, 0) = 0x1e00001 XCreateWindow(0x55d1fb3c7010, 246, 0, 0) = 0x1e00002 glXCreateContext(0x55d1fb3c7010, 0x55d1fb3dfb50, 0, 1) = 0x55d1fb3dfde0 glXGetProcAddress(0x55d1fa791738, 0, 0x8014, 0) = 0x7f403adc19b0 glXMakeCurrent(0x55d1fb3c7010, 0, 0, 0xfffd) = 1 glXDestroyContext(0x55d1fb3c7010, 0x55d1fb3dfde0, 0x55d1fb3dfde0, 0x7f4037eaf760) = 0 glXMakeCurrent(0x55d1fb3c7010, 0x1e00002, 0x55d1fb3dfde0, 0x1e00002) = 1 glCreateProgram(0, 0, 0x7f403b014a60, 3075) = 1 glCreateShader(0x91b9, 0, 0x55d1fb3e15e0, 1) = 2 glShaderSource(2, 2, 0x7ffd7f0cb6d0, 0) = 0 glCompileShader(2, 0, 0xffffffff, 0) = 1 glGetShaderiv(2, 0x8b81, 0x7ffd7f0cb6cc, 0x55d1fb53e7b0) = 1 glAttachShader(1, 2, 2, 1) = 0x55d1fb53dfe0 glDeleteShader(2, 0x55d1fb53dfe0, 0x55d1fb53df20, 0x7f403aa62b00) = 2 glLinkProgram(1, 0x7ffd7f0c8e98, 0, 1) = 0x55d1fb53dac0 glGetProgramiv(1, 0x8b82, 0x7ffd7f0cb6cc, 1) = 1 glUseProgram(1, 1, 3, 1) = 0x55d1fb53d980 glGetUniformLocation(1, 0x55d1fa7918c1, 0x55d1fb53d980, 1) = 0 glUniform1i(0, 0, 0, 0x7f4037413340) = 0x8000000000 glDispatchCompute(32, 32, 1, 0x7ffd7f0c8ea0) = -1 glGetError(0x55d1fb544850, 0xe000, 135, 0x7f403b22321c) = 0 glDeleteProgram(1, 0xe000, 135, 0x7f403b22321c) = 3 glXMakeCurrent(0x55d1fb3c7010, 0, 0, 1) = 1 glXDestroyContext(0x55d1fb3c7010, 0x55d1fb3dfde0, 0x55d1fb3dfde0, 0) = 0 XFree(0x55d1fb3df940, 0, 0x7f403b014a60, 0) = 1 XFreeColormap(0x55d1fb3c7010, 0x1e00001, 0x1e00001, 0) = 1 XFree(0x55d1fb3dfb50, 0, 0xffffffff, 0x55d1fb50e5a0) = 1 XCloseDisplay(0x55d1fb3c7010) = <void> +++ exited (status 0) +++ ==2414== Command: ./cst ==2414== ==2414== ==2414== HEAP SUMMARY: ==2414== in use at exit: 106,885 bytes in 206 blocks ==2414== total heap usage: 86,334 allocs, 86,128 frees, 35,353,433 bytes allocated ==2414== ==2414== 17,813 (1,560 direct, 16,253 indirect) bytes in 1 blocks are definitely lost in loss record 79 of 80 ==2414== at 0x4C2BBAF: malloc (vg_replace_malloc.c:299) ==2414== by 0x90F888C: ralloc_size (ralloc.c:121) ==2414== by 0x90F897D: rzalloc_size (ralloc.c:153) ==2414== by 0x920D774: brwNewProgram (brw_program.c:141) ==2414== by 0x910C913: link_intrastage_shaders(void*, gl_context*, gl_shader_program*, gl_shader**, unsigned int, bool) (linker.cpp:2266) ==2414== by 0x910E599: link_shaders(gl_context*, gl_shader_program*) (linker.cpp:4844) ==2414== by 0x904167A: _mesa_glsl_link_shader (ir_to_mesa.cpp:3108) ==2414== by 0x8F45C78: link_program (shaderapi.c:1171) ==2414== by 0x8F45C78: link_program_error (shaderapi.c:1249) ==2414== by 0x10951D: main () ==2414== ==2414== LEAK SUMMARY: ==2414== definitely lost: 1,560 bytes in 1 blocks ==2414== indirectly lost: 16,253 bytes in 94 blocks ==2414== possibly lost: 0 bytes in 0 blocks ==2414== still reachable: 89,072 bytes in 111 blocks ==2414== suppressed: 0 bytes in 0 blocks ==2414== Reachable blocks (those to which a pointer was found) are not shown. ==2414== To see them, rerun with: --leak-check=full --show-leak-kinds=all
Leak happens because of reference count increment during _mesa_update_state in glDispatchCompute (if glDispatchCompute is commented out, there is no leak). Will try to understand why this is never decremented.
Thanks for the heads up. Stepping through the code it seems _mesa_update_state_locked updates the fixed function vertex and fragment shaders for the compute shader program is this necessary?
(In reply to adam from comment #2) > Thanks for the heads up. Stepping through the code it seems > _mesa_update_state_locked updates the fixed function vertex and fragment > shaders for the compute shader program is this necessary? Only the active/existing programs get updated, in your case ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE] should be the only one.
will send a fix soon ..
Created attachment 134352 [details] [review] fix https://lists.freedesktop.org/archives/mesa-dev/2017-September/170206.html
Nice, a one liner, thanks for the fix!
commit 589457d97fa8e95f227e7179e9c89a01dff495a0 Author: Tapani Pälli <tapani.palli@intel.com> Date: Wed Sep 20 09:29:16 2017 +0300 mesa: free current ComputeProgram state in _mesa_free_context_data This is already done for other programs stages, fixes a leak when using compute programs. Signed-off-by: Tapani Pälli <tapani.palli@intel.com> Cc: mesa-stable@lists.freedesktop.org Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=102844 Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com> Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
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.