Debugging: Difference between revisions

From WebGL Public Wiki
Jump to navigation Jump to search
Added a section on the WebGL Inspector
added more debugging tips
Line 30: Line 30:
};
};


ctx = WebGLDebugUtils.makeDebugContext(canvas.getContext("webgl"), throwOnGLError);
gl = canvas.getContext(...);
gl = WebGLDebugUtils.makeDebugContext(gl, throwOnGLError);
</source>
</source>


===Showing every WebGL function call===
Download the webgl-debug library mentioned above. Then make a function to print the calls like this
<source lang="javascript">
function logGLCall(functionName, args) { 
  console.log("gl." + functionName + "(" +
      WebGLDebugUtils.glFunctionArgsToString(functionName, args) + ")"); 
}
gl = canvas.getContext(...);
gl = WebGLDebugUtils.makeDebugContext(gl, undefined, logGLCall);
</source>
===Checking that none of your arguments are undefined===
One of the interesting choices of JavaScript is that it will try to coerce values of 1 type into another. This can make it hard to find bugs. For example if you do something like this
<source lang="javascript">
  var textureInfo = {
    tex: gl.createTexture()
  }
  gl.bindTexture(gl.TEXTURE_2D, textureInfo.tx);
</source>
Notice the typo? It's 'tex' at the top but 'tx' at the bottom. 'tx' is undefined but the rules of JavaScript require that to be silently coerced into NULL which is a valid argument.
You can check for errors like this by adding a function that checks for undefined on all arguments passed to WebGL.
<source lang="javascript">
function validateNoneOfTheArgsAreUndefined(functionName, args) {
  for (var ii = 0; ii < args.length; ++ii) {
    if (args[ii] === undefined) {
      console.error("undefined passed to gl." + functionName + "(" +
                    WebGLDebugUtils.glFunctionArgsToString(functionName, args) + ")");
    }
  }
}
gl = canvas.getContext(...);
gl = WebGLDebugUtils.makeDebugContext(
    gl, undefined, validateNoneOfTheArgsAreUndefined);
</source>
===Combine all 3 techniques above ===
<source lang="javascript">
function logAndValidate(functionName, args) {
  logGLCalls(functionName, args);
  validateNoneOfTheArgsAreUndefined (functionName, args);
}
 
gl = canvas.getContext(...);
gl = WebGLDebugUtils.makeDebugContext(gl, throwOnGLError, logAndValidate);
</source>
==Printing Errors and other constants ==
==Printing Errors and other constants ==
WebGL uses many constants and returns errors as numbers. It's often easier to display those numbers as strings. With that in mind you can call WebGLDebugUtils.glEnumToString to convert a WebGL constant to a string.
WebGL uses many constants and returns errors as numbers. It's often easier to display those numbers as strings. With that in mind you can call WebGLDebugUtils.glEnumToString to convert a WebGL constant to a string.

Revision as of 04:17, 9 May 2012

Interactive Debugging of WebGL applications

The WebGL Inspector provides an interactive set of tools for debugging and diagnosing advanced WebGL applications. It provides the ability to capture entire frames' rendering calls and interactively step through them, an annotated call log with stepping/resource navigation and redundant call warnings, resource browsers for textures, buffers, and programs, and much more.

Programmatically Debugging WebGL applications

WebGL's error reporting mechanism involves calling getError and checking for errors. As it can be burdensome to put a getError call after every WebGL function call here is small library to help with make this easier.

https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/sdk/debug/webgl-debug.js

To use the library, download it, put it on your server and include it with

<script src="webgl-debug.js"></script>

Then you can wrap your WebGLRenderingContext in an object that checks all calls like this

ctx = WebGLDebugUtils.makeDebugContext(canvas.getContext("webgl"));

This will make any GL errors show up in your browser JavaScript console.

If you want to do something else, like throw an exception you can pass in your own error handling function.

function throwOnGLError(err, funcName, args) {
  throw WebGLDebugUtils.glEnumToString(err) + " was caused by call to" + funcName;
};

gl = canvas.getContext(...); 
gl = WebGLDebugUtils.makeDebugContext(gl, throwOnGLError);

Showing every WebGL function call

Download the webgl-debug library mentioned above. Then make a function to print the calls like this

function logGLCall(functionName, args) {   
   console.log("gl." + functionName + "(" + 
      WebGLDebugUtils.glFunctionArgsToString(functionName, args) + ")");   
} 

gl = canvas.getContext(...);
gl = WebGLDebugUtils.makeDebugContext(gl, undefined, logGLCall);

Checking that none of your arguments are undefined

One of the interesting choices of JavaScript is that it will try to coerce values of 1 type into another. This can make it hard to find bugs. For example if you do something like this


   var textureInfo = {
     tex: gl.createTexture()
   }
   gl.bindTexture(gl.TEXTURE_2D, textureInfo.tx);

Notice the typo? It's 'tex' at the top but 'tx' at the bottom. 'tx' is undefined but the rules of JavaScript require that to be silently coerced into NULL which is a valid argument.

You can check for errors like this by adding a function that checks for undefined on all arguments passed to WebGL.


function validateNoneOfTheArgsAreUndefined(functionName, args) {
  for (var ii = 0; ii < args.length; ++ii) {
    if (args[ii] === undefined) {
      console.error("undefined passed to gl." + functionName + "(" +
                     WebGLDebugUtils.glFunctionArgsToString(functionName, args) + ")");
    }
  }
} 

 
gl = canvas.getContext(...);
gl = WebGLDebugUtils.makeDebugContext(
    gl, undefined, validateNoneOfTheArgsAreUndefined);

Combine all 3 techniques above

function logAndValidate(functionName, args) {
   logGLCalls(functionName, args);
   validateNoneOfTheArgsAreUndefined (functionName, args);
}
  
gl = canvas.getContext(...);
gl = WebGLDebugUtils.makeDebugContext(gl, throwOnGLError, logAndValidate);

Printing Errors and other constants

WebGL uses many constants and returns errors as numbers. It's often easier to display those numbers as strings. With that in mind you can call WebGLDebugUtils.glEnumToString to convert a WebGL constant to a string.

Example:

WebGLDebugUtils.init(ctx);
alert(WebGLDebugUtils.glEnumToString(ctx.getError()));