Question about performance and setShader/updateShader

Hi there!

I’m using Stencyl with openfl 9.1.0 and I’m looking into improving performance, testing on Windows with native export.

Using telemetry read through hxScout, by far the most expensive process tree ends with shader updates and texture creation (about half the active time throughout the running process):

Curious about the inner workings, I discovered that OpenGLRenderer.setShader() is being called constantly, every frame (or multiple times per frame, not sure). This bypasses the if (__currentShader == shader) return; check because (apparently) the shader flips back and forth between these two:

openfl/display/OpenGLRenderer.hx:355: varying vec2 openfl_TextureCoordv;
           uniform sampler2D openfl_Texture;
           void main(void) {
                   vec4 color = texture2D (openfl_Texture, openfl_TextureCoordv);
                   if (color.a == 0.0) {
                           discard;
                   } else {
                           gl_FragColor = color;
                   }
           }
openfl/display/OpenGLRenderer.hx:355: varying float openfl_Alphav;
           varying vec4 openfl_ColorMultiplierv;
           varying vec4 openfl_ColorOffsetv;
           varying vec2 openfl_TextureCoordv;
           uniform bool openfl_HasColorTransform;
           uniform sampler2D openfl_Texture;
           uniform vec2 openfl_TextureSize;
           void main(void) {
                   vec4 color = texture2D (openfl_Texture, openfl_TextureCoordv);
           if (color.a == 0.0) {
                   gl_FragColor = vec4 (0.0, 0.0, 0.0, 0.0);
           } else if (openfl_HasColorTransform) {
                   color = vec4 (color.rgb / color.a, color.a);
                   mat4 colorMultiplier = mat4 (0);
                   colorMultiplier[0][0] = openfl_ColorMultiplierv.x;
                   colorMultiplier[1][1] = openfl_ColorMultiplierv.y;
                   colorMultiplier[2][2] = openfl_ColorMultiplierv.z;
                   colorMultiplier[3][3] = 1.0; // openfl_ColorMultiplierv.w;
                   color = clamp (openfl_ColorOffsetv + (color * colorMultiplier), 0.0, 1.0);
                   if (color.a > 0.0) {
                           gl_FragColor = vec4 (color.rgb * color.a * openfl_Alphav, color.a * openfl_Alphav);
                   } else {
                           gl_FragColor = vec4 (0.0, 0.0, 0.0, 0.0);
                   }
           } else {
                   gl_FragColor = color * openfl_Alphav;
           }
           }

(just printing the fragmentSource)

  1. Is this intended behavior? Should OpenGLRenderer.setShader() be called every frame, and should it be flipping like this?
    (I’m assuming because there’s only one Stage, that there’s only one OpenGLRenderer instance for this to run on. If that’s not the case then my readings may be wrong)

This may not necessarily be connected to the section I was looking at for optimization; Shaders updating often seems reasonable to me. Creating textures constantly might not be intentional, but I’m not sure.

  1. Does this frame cost from updateShader to createTexture look normal? Is there a way to optimize this at all?

Thanks!

1 Like