Hi,

we currently have a zoo of shaders to render layers:

  RGBALayerProgramType,
  BGRALayerProgramType,
  RGBXLayerProgramType,
  BGRXLayerProgramType,
  RGBARectLayerProgramType,
  RGBXRectLayerProgramType,
  BGRARectLayerProgramType,
  RGBAExternalLayerProgramType,
  ColorLayerProgramType,
  YCbCrLayerProgramType,
  ComponentAlphaPass1ProgramType,
  ComponentAlphaPass1RGBProgramType,
  ComponentAlphaPass2ProgramType,
  ComponentAlphaPass2RGBProgramType,

(I have just eliminated the Copy2D variants, so omitted here.)

Next, I would like to replace everything but the YCbCr and ComponentAlpha 
shaders with one unified shader (attached below).

Rationale:

Most of our shader programs only differ minimally in cycle count, and we are 
generally memory bound, not GPU cycle bound (even on mobile). In addition, GPUs 
are actually are very efficient at branching, as long the branch is uniform and 
doesn't change direction per pixel or vertex (the driver compiles essentially 
variants and runs that). Last but not least, switching shaders tends to be 
expensive.

Proposed approach:

We use a single shader to replace the current 8 layer shaders. I verified with 
the mali shader compiler that the shortest path (color layer) is pretty close 
to the old color shader (is now 3, due to the opacity multiplication, was 1). 
For a lot of scenes we will be able to render without ever switching shaders, 
so that should more than make up for the extra cycles, especially since we are 
memory bound anyway.

More uniforms have to be set per shader invocation, but that should be pretty 
cheap.

I completely dropped the distinction of 2D and 3D masks. 3D masks should be 
able to handle the 2D case and the cycle savings are minimal, and as mentioned 
before, irrelevant.

An important advantage is that with this approach we can now easily add 
additional layer effects to the pipeline without exponentially exploding the 
number of programs 
(RGBXRectLayerProgramWithGrayscaleAndWithoutOpacityButMaskAndNotMask3D…).

Also, last but not least, this reduces code complexity quite a bit.

Feedback welcome.

Thanks,

Andreas

---

// Base color (will be rendered if layer texture is not read).
uniform vec4 uColor;

// Layer texture (disabled for color layers).
uniform bool uTextureEnabled;
uniform vec2 uTexCoordMultiplier;
uniform bool uTextureBGRA; // Default is RGBA.
uniform bool uTextureNoAlpha;
uniform float uTextureOpacity;
uniform sampler2D uTexture;
uniform bool uTextureUseExternalOES;
uniform samplerExternalOES uTextureExternalOES;
#ifndef GL_ES
uniform bool uTextureUseRect;
uniform sampler2DRect uTextureRect;
#endif

// Masking (optional)
uniform bool uMaskEnabled;
varying vec3 vMaskCoord;
uniform sampler2D uMaskTexture;

void main()
{
  vec4 color = uColor;
  if (uTextureEnabled) {
    vec2 texCoord = vTexCoord * uTexCoordMultiplier;
    if (uTextureUseExternalOES) {
      color = texture2D(uTextureExternalOES, texCoord);
#ifndef GL_ES
    } else if (uTextureUseRect) {
      color = texture2DRect(uTexture, texCoord);
#endif
    } else {
      color = texture2D(uTexture, texCoord);
    }
    if (uTextureBGRA) {
      color = color.bgra;
    }
    if (uTextureNoAlpha) {
      color = vec4(color.rgb, 1.0);
    }
    color *= uTextureOpacity;
  }
  if (uMaskEnabled) {
    color *= texture2D(uMaskTexture, vMaskCoord.xy / vMaskCoord.z).r;
  }
  gl_FragColor = color;
}

_______________________________________________
dev-platform mailing list
dev-platform@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-platform

Reply via email to