cinder / Cinder

Cinder is a community-developed, free and open source library for professional-quality creative coding in C++.
http://libcinder.org
Other
5.34k stars 943 forks source link

Identifying the shader on compilation or linking exception #1983

Open IntellectualKitty opened 6 years ago

IntellectualKitty commented 6 years ago

It would be helpful to include additional information when compilation or linking failures occur when constructing shaders so that the problematic shader can be found more easily.

richardeakin commented 6 years ago

What are you seeing that is ambiguous? I've had good experiences debugging even quite complex shaders since https://github.com/cinder/Cinder/pull/1721. How are you logging the exception? I always recommend using CI_LOG_EXCEPTION, which will give you much verbosity, like for example when I add a typo it is showing me that it is a GlslCompileExc (as opposed to GlslLinkExc):

|error  | mason::AssetManager::getShader::<lambda_8683a21412f09ec654f8918845dc1d0e>::operator ()[183] Failed to reload glsl: [trails.vert,trails.frag], exception type: class cinder::gl::GlslProgCompileExc, what: VERTEX: trailsCommon.glsl(32) : error C0159: invalid char 'a' in integer constant suffix
trailsCommon.glsl(32) : error C0000: syntax error, unexpected integer constant, expecting ',' or ';' at token "<int-const>"

|error  | mason::AssetManager::getShader::<lambda_564f81ddaa6778c507c95ae5d18a8570>::operator ()[138] Failed to reload glsl: [trails.comp], exception type: class cinder::gl::GlslProgCompileExc, what: COMPUTE: trailsCommon.glsl(32) : error C0159: invalid char 'a' in integer constant suffix
trailsCommon.glsl(32) : error C0000: syntax error, unexpected integer constant, expecting ',' or ';' at token "<int-const>"

|error  | mason::AssetManager::getShader::<lambda_8683a21412f09ec654f8918845dc1d0e>::operator ()[183] Failed to reload glsl: [trailsOffsetVis.vert,trailsOffsetVis.frag], exception type: class cinder::gl::GlslProgCompileExc, what: VERTEX: trailsCommon.glsl(32) : error C0159: invalid char 'a' in integer constant suffix
trailsCommon.glsl(32) : error C0000: syntax error, unexpected integer constant, expecting ',' or ';' at token "<int-const>"

There is also to error code starting with C, but this might be graphics card dependent (I'm using an nvidia gtx, I think when I tested on Mac OS X a while back it was much less verbose).

IntellectualKitty commented 6 years ago

@richardeakin the shader exception and logging system is great. It makes debugging easy.

The problem I'm having is identifying which program is causing the problem. For example, I'm working on a complex lens flare system right now, and I've got about 50 shader programs all with many similar internal computations. Also, I tend not to be particularly careful to work on just one at a time since I use global search and replace while developing them. So, when I look at the log, it's hard to identify which program is causing the problem.

So, it would be helpful to include information about where the shader came from. For example, including file and line number in the CI_GLSL macro and reporting that with GlslCompileExc with the default logging on compilation failure.

richardeakin commented 6 years ago

You actually get filenames (even if the error is in an #include) and line numbers if this guy is enabled, which it is by default. It is non-standard, but works on NVidia windows cards (probably linux too but I haven't checked).

To do this by directly manipulating the GlslProgExc seems tricky to me because:

That said if you can figure it out I'd be stoked. :) Because like I said, the current support for this is NVidia + Windows only (the main cards we use in production at least).

Btw I enable it in my own AssetManager with the following:

#if defined( CINDER_MSW )
    auto vendor = gl::getVendorString();
    std::transform( vendor.begin(), vendor.end(), vendor.begin(), tolower );
    if( vendor.find( "nvidia" ) != string::npos ) {
        mShaderPreprocessor->setUseFilenameInLineDirectiveEnabled( true );
    }
#endif
IntellectualKitty commented 6 years ago

@richardeakin what about leaving the exception the way it is and logging the shader text during compilation, both for verbose logging and debug logging on error? Then when the compilation exception is thrown, there's already context available if the logging level is set high enough, before the exception itself is logged.

I don't have any experience with GLSL linker errors, but perhaps it would also be helpful to log all of the GLSL program's shader code for debug logging when a linking exception occurs.

richardeakin commented 6 years ago

I don't think we can do all that logging from cinder itself, but what I do (and recommend to most people) is to use some sort of asset manager to load your shaders, and other assets, wherein you can keep your logging consistent and to your application's needs.

If you'd like to see how I load assets, you can try out the AssetManager I use, which isn't fancy but it'll give you live coding with shaders and really nice exception handling. Here's an example of it in use.