Workaround OpenColorIO GLSL issues in MacOS
ClosedPublic

Authored by lsegovia on Jun 11 2018, 6:54 PM.

Details

Summary

Enabling OCIO and OpenGL at the same time in MacOS throws up the following error log:

2018-06-11 18:51:49.326035+0000 krita[34171:155019] QOpenGLShader::compile(Fragment): ERROR: 0:13: Invalid call of undeclared identifier 'texture3D'
2018-06-11 18:51:49.326101+0000 krita[34171:155019] *** Problematic Fragment shader source code ***
#version 150 core
#define lowp
#define mediump
#define highp
#line 1
#define DIRECT_LOD_FETCH
#define HIGHQ_SCALING
#define USE_OCIO

// Generated by OpenColorIO

vec4 OCIODisplay(in vec4 inPixel, 
    const sampler3D lut3d) 
{
vec4 out_pixel = inPixel; 
// OSX segfault work-around: Force a no-op sampling of the 3d lut.
texture3D(lut3d, 0.984375 * out_pixel.rgb + 0.0078125).rgb;
return out_pixel;
}


/*
 * shader for handling scaling
 */
uniform sampler2D texture0;

#ifdef USE_OCIO
uniform sampler3D texture1;
#endif

in vec4 v_textureCoordinate;
out vec4 fragColor;

const float eps = 1e-6;

#if defined HIGHQ_SCALING || defined DIRECT_LOD_FETCH
uniform float viewportScale;
#endif /* defined HIGHQ_SCALING || defined DIRECT_LOD_FETCH */

#ifdef DIRECT_LOD_FETCH
uniform float fixedLodLevel;
#endif

#ifdef HIGHQ_SCALING

uniform float texelSize;

vec4 filterPureLinear8(sampler2D texture, vec2 texcoord)
{
    float newTexelSize = texelSize / viewportScale;
    float support = 0.5 * newTexelSize;
    float step = texelSize * 1.0;

    float offset = support - 0.5*texelSize;

    float level = 0.0;


    if (viewportScale < 0.03125) {
        level = 4.0;
    } else if (viewportScale < 0.0625) {
        level = 3.0;
    } else if (viewportScale < 0.125) {
        level = 2.0;
    } else if (viewportScale < 0.25) {
        level = 1.0;
    }

/*
    vec4 p1 = textureLod(texture, vec2(texcoord.x - offset, texcoord.y - offset), level);
    vec4 p2 = 2.0*textureLod(texture, vec2(texcoord.x         , texcoord.y - offset), level);
    vec4 p3 = textureLod(texture, vec2(texcoord.x + offset, texcoord.y - offset), level);

    vec4 p4 = 2.0*textureLod(texture, vec2(texcoord.x - offset, texcoord.y), level);
    vec4 p5 = 5.0*textureLod(texture, vec2(texcoord.x         , texcoord.y), level);
    vec4 p6 = 2.0*textureLod(texture, vec2(texcoord.x + offset, texcoord.y), level);

    vec4 p7 = textureLod(texture, vec2(texcoord.x - offset, texcoord.y + offset), level);
    vec4 p8 = 2.0*textureLod(texture, vec2(texcoord.x         , texcoord.y + offset), level);
    vec4 p9 = textureLod(texture, vec2(texcoord.x + offset, texcoord.y + offset), level);

    return (p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) / 17.0;
*/

    vec4 p1 = textureLod(texture, vec2(texcoord.x - offset, texcoord.y - offset), level);
    vec4 p2 = textureLod(texture, vec2(texcoord.x + offset, texcoord.y - offset), level);

    vec4 p3 = vec4(4.0) * textureLod(texture, vec2(texcoord.x, texcoord.y), level);

    vec4 p4 = textureLod(texture, vec2(texcoord.x - offset, texcoord.y + offset), level);
    vec4 p5 = textureLod(texture, vec2(texcoord.x + offset, texcoord.y + offset), level);

    vec4 p6 = vec4(3.0) * textureLod(texture, vec2(texcoord.x, texcoord.y), level + 1.0);

    return (p1 + p2 + p3 + p4 + p5 + p6) / vec4(11.0);

}

#endif /* HIGHQ_SCALING */

void main() {
    vec4 col;

#if defined HIGHQ_SCALING || defined DIRECT_LOD_FETCH

    if (viewportScale < 0.5 - eps) {

#ifdef DIRECT_LOD_FETCH

        if (fixedLodLevel > eps) {
            col = textureLod(texture0, v_textureCoordinate.st, fixedLodLevel);
        } else

#endif /* DIRECT_LOD_FETCH */

        {

#ifdef HIGHQ_SCALING
            col = filterPureLinear8(texture0, v_textureCoordinate.st);
#else /* HIGHQ_SCALING */
            col = texture(texture0, v_textureCoordinate.st);
#endif /* HIGHQ_SCALING */

        }
    } else

#endif /* defined HIGHQ_SCALING || defined DIRECT_LOD_FETCH */

    {
#ifdef DIRECT_LOD_FETCH

        if (fixedLodLevel > eps) {
            col = textureLod(texture0, v_textureCoordinate.st, fixedLodLevel);
        } else

#endif /* DIRECT_LOD_FETCH */
        {
            col = texture(texture0, v_textureCoordinate.st);
        }
    }

#ifdef USE_OCIO
    fragColor = OCIODisplay(col, texture1);
#else /* USE_OCIO */
    fragColor = col;
#endif /* USE_OCIO */

}

***
2018-06-11 18:51:49.326984+0000 krita[34171:155019] Shader Compilation Failure:  "Failed to add fragment shader source from file: highq_downscale.frag - Cause: ERROR: 0:13: Invalid call of undeclared identifier 'texture3D'\n"

Usually, after this, Krita either crashes with EXC_BAD_ACCESS or empties the canvas and becomes unusable.

I looked up how Blender supports OCIO in MacOS, and Brecht Van Lommel pushed a workaround that uses texture instead of texture2D and texture3D (https://lists.blender.org/pipermail/bf-blender-cvs/2017-August/100014.html).

Test Plan
  1. Enable OpenGL rendering in Krita.
  1. Open the docker "LUT Management", then enable OCIO.
  1. Check that Krita doesn't crash, and that the image has the correct gamma.

Diff Detail

Repository
R37 Krita
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.
lsegovia created this revision.Jun 11 2018, 6:54 PM
lsegovia created this object with edit policy "Krita (Project)".
Restricted Application added a reviewer: Krita. · View Herald TranscriptJun 11 2018, 6:54 PM
Restricted Application edited projects, added Krita; removed Krita: Stable bug fixes. · View Herald Transcript
lsegovia requested review of this revision.Jun 11 2018, 6:54 PM
rempt accepted this revision.Jun 12 2018, 7:47 AM
This revision is now accepted and ready to land.Jun 12 2018, 7:47 AM
This revision was automatically updated to reflect the committed changes.