OpenGL object counting snippet

Hello everyone.

This is just a small snippet which calls glIs****() functions repeatedly to count how many objects are currently active. The point of it is to help find memory leaks in your code that can be fatal when a game is played for a long time. It’s a bit hacky and may not always be accurate. The number of checks for each object type is tweakable with the constants at the top of the code. If all tested objects are active, the code prints an extra “+” after the count to signal that the count is most likely higher. If a feature isn’t supported by your graphics card, it prints out a count of -1 for that object type (untested).

Note that this code is only meant to be an indicator. It may not report the count correctly.

  • Let’s say the object limit is 1000. You create 3000 objects and delete the first 1000. The count is reported as 0 since the first 1000 IDs weren’t active objects.
  • Let’s say the object limit is 1000. You create 3000 objects and delete the first 100. The count is reported as 900 (not 900+ or 1000+).

In addition, it may not even work at all if the driver doesn’t assign IDs the same way as the Nvidia driver does, but it does work well enough on Nvidia drivers.

Sample output:

[quote]OpenGL object counts
Textures: 79
Samplers: 0
FBOs: 30
RBOs: 0
Buffers: 58
VAOs: 70
Shaders: 145
Programs: 67
Pipelines: 0
Queries: 740
TransFeed: 0
[/quote]
Code:


import org.lwjgl.opengl.ARBFramebufferObject;
import org.lwjgl.opengl.ARBOcclusionQuery;
import org.lwjgl.opengl.ARBSamplerObjects;
import org.lwjgl.opengl.ARBSeparateShaderObjects;
import org.lwjgl.opengl.ARBTransformFeedback2;
import org.lwjgl.opengl.ARBVertexArrayObject;
import org.lwjgl.opengl.ARBVertexBufferObject;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GLCapabilities;

public class ActiveOpenGLObjectCounter {
	
	private ActiveOpenGLObjectCounter() {}
	
	private static final int TEXTURE_TESTS = 1000;
	private static final int SAMPLER_TESTS = 1000;
	
	private static final int FRAMEBUFFER_TESTS = 100;
	private static final int RENDERBUFFER_TESTS = 10;

	
	private static final int BUFFER_TESTS = 10000;
	private static final int VAO_TESTS = 10000;
	
	private static final int SHADER_TESTS = 1000;
	private static final int PROGRAM_TESTS = 1000;
	private static final int PIPELINE_TESTS = 100;

	private static final int QUERY_TESTS = 10000;
	
	private static final int TRANSFORM_FEEDBACK_TESTS = 100;
	
	public static void dumpCounts(){
		
		int textures = 0;
		int samplers = 0;
		
		int framebuffers = 0;
		int renderbuffers = 0;
		
		int buffers = 0;
		int vaos = 0;
		
		int shaders = 0;
		int programs = 0;
		int pipelines = 0;
		
		int queries = 0;
		
		int transformFeedbacks = 0;
		
		

		GLCapabilities caps = GL.getCapabilities();
		
		for(int i = 1; i <= TEXTURE_TESTS; i++){
			if(GL11.glIsTexture(i)){
				textures++;
			}
		}
		if(caps.GL_ARB_sampler_objects){
			for(int i = 1; i <= SAMPLER_TESTS; i++){
				if(ARBSamplerObjects.glIsSampler(i)){
					samplers++;
				}
			}
		}else{
			samplers = -1;
		}
		
		if(caps.GL_ARB_framebuffer_object){
			for(int i = 1; i <= FRAMEBUFFER_TESTS; i++){
				if(ARBFramebufferObject.glIsFramebuffer(i)){
					framebuffers++;
				}
			}
			for(int i = 1; i <= RENDERBUFFER_TESTS; i++){
				if(ARBFramebufferObject.glIsRenderbuffer(i)){
					renderbuffers++;
				}
			}
		}else{
			framebuffers = -1;
			renderbuffers = -1;
		}

		
		if(caps.GL_ARB_vertex_buffer_object){
			for(int i = 1; i <= BUFFER_TESTS; i++){
				if(ARBVertexBufferObject.glIsBufferARB(i)){
					buffers++;
				}
			}
		}else{
			buffers = -1;
		}
		if(caps.GL_ARB_vertex_array_object){
			for(int i = 1; i <= VAO_TESTS; i++){
				if(ARBVertexArrayObject.glIsVertexArray(i)){
					vaos++;
				}
			}
		}else{
			vaos = -1;
		}
		
		if(caps.OpenGL20){
			for(int i = 1; i <= SHADER_TESTS; i++){
				if(GL20.glIsShader(i)){
					shaders++;
				}
			}
			for(int i = 1; i <= PROGRAM_TESTS; i++){
				if(GL20.glIsProgram(i)){
					programs++;
				}
			}
		}else{
			shaders = -1;
			programs = -1;
		}
		if(caps.GL_ARB_separate_shader_objects){
			for(int i = 1; i <= PIPELINE_TESTS; i++){
				if(ARBSeparateShaderObjects.glIsProgramPipeline(i)){
					pipelines++;
				}
			}
		}else{
			pipelines = -1;
		}

		if(caps.GL_ARB_occlusion_query){
			for(int i = 1; i <= QUERY_TESTS; i++){
				if(ARBOcclusionQuery.glIsQueryARB(i)){
					queries++;
				}
			}
		}else{
			queries = -1;
		}
		if(caps.GL_ARB_transform_feedback2){
			for(int i = 1; i <= TRANSFORM_FEEDBACK_TESTS; i++){
				if(ARBTransformFeedback2.glIsTransformFeedback(i)){
					transformFeedbacks++;
				}
			}
		}else{
			transformFeedbacks = -1;
		}
		

		System.out.println("OpenGL object counts");

		System.out.println("    Textures:  " + textures + (textures == TEXTURE_TESTS ? "+" : ""));
		System.out.println("    Samplers:  " + samplers + (samplers == SAMPLER_TESTS ? "+" : ""));

		System.out.println("    FBOs:      " + framebuffers + (framebuffers == FRAMEBUFFER_TESTS ? "+" : ""));
		System.out.println("    RBOs:      " + renderbuffers + (renderbuffers == RENDERBUFFER_TESTS ? "+" : ""));

		System.out.println("    Buffers:   " + buffers + (buffers == BUFFER_TESTS ? "+" : ""));
		System.out.println("    VAOs:      " + vaos + (vaos == VAO_TESTS ? "+" : ""));

		System.out.println("    Shaders:   " + shaders + (shaders == SHADER_TESTS ? "+" : ""));
		System.out.println("    Programs:  " + programs + (programs == PROGRAM_TESTS ? "+" : ""));
		System.out.println("    Pipelines: " + pipelines + (pipelines == PIPELINE_TESTS ? "+" : ""));
		
		System.out.println("    Queries:   " + queries + (queries == QUERY_TESTS ? "+" : ""));
		
		System.out.println("    TransFeed: " + transformFeedbacks + (transformFeedbacks == TRANSFORM_FEEDBACK_TESTS ? "+" : ""));

		System.out.println();
		
	}
}

1 Like