Make it easier to debug custom shader compile errors
Right now, the way I debug compilation errors for a custom shader is putting a breakpoint in ShaderProgram.createAndLinkProgram() on one of the lines that throw DeveloperError, and then inspect the variables vsSource and fsSource which contain the complete shader text (custom shader + ModelExperimental shader code + CesiumJS builtin-stuff). But this is cumbersome and might be confusing to explain.
The tricky thing is the shader code is built in stages:
-
CustomShaderonly has the code the user added -
ModelExperimentalhas aShaderBuilderobject when creating draw commands. This contains the complete shader, of which the custom shader is a small portion. This is usually the code I want to look at when debugging since it has more context about attributes and structs in the shader. - the draw command has the
ShaderProgramwhich has the full shader (ModelExperimental code + built in renderer code)
It would be great to make some of these more accessible for debugging. Some ideas:
- Perhaps the easiest, instead of ShaderProgram throwing a
DeveloperError, maybe it could throw a newShaderCompilationErrorthat includes the vertex and fragment text. - Or just
console.errorwith the shader text - the
ShaderBuildercould certainly have a method likegetFullFragmentShaderText()that combines the text like it does when building theShaderProgram, but returns the string. The only tricky part is how would the user access the shader builder, as this is pretty deep in the private API. - a similar method could be used for the
ShaderProgram, but again it would be cumbersome to access and would be exposing more private API.
I'm starting to like the sound of 1) then the user could catch the error and handle it as desired.
- Perhaps the easiest, instead of ShaderProgram throwing a DeveloperError, maybe it could throw a new ShaderCompilationError that includes the vertex and fragment text.
I like this. And if the event has no listeners, it could throw a DeveloperError, like the pseudocode:
try {
compileShader();
compilationEvent.raiseEvent(true);
} catch (error) {
destroyResources();
if (compilationEvent.numberOfListeners === 0) {
throw new DeveloperError("Error generating shader");
} else {
compilationEvent.raiseEvent(false);
}
}
- Or just
console.errorwith the shader text
This is what https://github.com/CesiumGS/cesium/pull/10629 does.
I think this behavior was originally intended in createAndLinkProgram, but it wasn't working because the shader was deleted before calling debugShaders.getTranslatedShaderSource.
Note: the console.error output is the translated shader source. From my tests, it is still close enough to the raw shader code to be useful.