Skip to content

Instantly share code, notes, and snippets.

@dolang
Forked from tito/README.md
Last active March 21, 2018 14:22
Show Gist options
  • Save dolang/28663c251c90ac1be8319721a80c4293 to your computer and use it in GitHub Desktop.
Save dolang/28663c251c90ac1be8319721a80c4293 to your computer and use it in GitHub Desktop.
Find GL leaks from a apitrace dump

Find leaks from a apitrace dump trace

  1. Trace your program: apitrace trace python main.py
  2. Dump the trace: apitrace dump python.2.7.trace > log
  3. Check for leaks: python findleak.py log
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
-> No glDeleteRenderbuffers ?
https://gist.github.com/tito/1174b86ce126fd1ac11afbc77750d9ac
Find leaks from a apitrace dump trace
1. Trace your program: apitrace trace python main.py
2. Dump the trace: apitrace dump python.2.7.trace > log
3. Check for leaks: python findleak.py log
This is the fork I use on my Windows machine.
"""
from __future__ import print_function, unicode_literals
import sys
import re
from pprint import pprint
from io import open
state = {
"textures": [],
"framebuffers": [],
"renderbuffers": [],
"buffers": [],
"programs": []
}
def processline(line):
if not re.match("\d+ .*", line):
return
lineno, line = line.split(" ", 1)
if line.startswith("glGenTextures("):
gl_id = int(re.match(".*\(.*, textures = &(\d+)\)", line).group(1))
state["textures"].append(gl_id)
elif line.startswith("glGenFramebuffers("):
gl_id = int(re.match(".*\(.*, framebuffers = &(\d+)\)", line).group(1))
state["framebuffers"].append(gl_id)
elif line.startswith("glGenRenderbuffers("):
gl_id = int(re.match(".*\(.*, renderbuffers = &(\d+)\)", line).group(1))
state["renderbuffers"].append(gl_id)
elif line.startswith("glGenBuffers("):
gl_id = int(re.match(".*\(.*, buffers = &(\d+)\)", line).group(1))
state["buffers"].append(gl_id)
elif line.startswith("glCreateProgram("):
gl_id = int(re.match(".*\(\) = (\d+)", line).group(1))
state["programs"].append(gl_id)
elif line.startswith("glDeleteBuffers"):
ids = re.match(".*\(.*, buffers = \{(.*)\}", line).group(1)
ids = [int(x) for x in ids.split(", ")]
for gl_id in ids:
if gl_id not in state["buffers"]:
print("Missing 'buffer' id {}".format(gl_id))
else:
index = state["buffers"].index(gl_id)
state["buffers"].pop(index)
elif line.startswith("glDeleteTextures"):
ids = re.match(".*\(.*, textures = \{(.*)\}", line).group(1)
ids = [int(x) for x in ids.split(", ")]
for gl_id in ids:
if gl_id not in state["textures"]:
print("Missing 'texture' id {}".format(gl_id))
else:
index = state["textures"].index(gl_id)
state["textures"].pop(index)
elif line.startswith("glDeleteRenderbuffers"):
ids = re.match(".*\(.*, renderbuffers = \{(.*)\}", line).group(1)
ids = [int(x) for x in ids.split(", ")]
for gl_id in ids:
if gl_id not in state["renderbuffers"]:
print("Missing 'renderbuffer' id {}".format(gl_id))
else:
index = state["renderbuffers"].index(gl_id)
state["renderbuffers"].pop(index)
elif line.startswith("glDeleteFramebuffers"):
ids = re.match(".*\(.*, framebuffers = \{(.*)\}", line).group(1)
ids = [int(x) for x in ids.split(", ")]
for gl_id in ids:
if gl_id not in state["framebuffers"]:
print("Missing 'framebuffer' id {}".format(gl_id))
else:
index = state["framebuffers"].index(gl_id)
state["framebuffers"].pop(index)
elif line.startswith("glDeleteProgram"):
gl_id = int(re.match(".*\(program = (\d+)", line).group(1))
if gl_id not in state["programs"]:
print("Missing 'program' id {}".format(gl_id))
else:
index = state["programs"].index(gl_id)
state["programs"].pop(index)
if __name__ == "__main__":
with open(sys.argv[1], encoding='UTF-16LE') as fd:
for line in fd.readlines():
processline(line.strip())
for key, values in state.items():
print("{}: {}".format(key, values))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment