From 46f43512c8e0f8accfd73401ef468c43a3e9429a Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Thu, 21 Nov 2019 17:37:08 +0000 Subject: [PATCH] Bug 1594128 - Use generic slots for text, image and solid shader varyings. r=gw The 'multi-brush' shader will have to dynamically switch between different brushes. In order to support that without needing the sum of all brush varying locations, allow aliasing a number of generic slots. This patch makes the assumption that one a vec2 and a vec4 cost the same amount of varying register space, which is suggested by the glsl specification about shader locations. If it is not the case we can add more granularity to the varying slots which are all vec4 at the moment. This also assumes that an unused varying is always optimized out. Differential Revision: https://phabricator.services.mozilla.com/D53726 --HG-- extra : moz-landing-system : lando --- gfx/wr/webrender/res/brush.glsl | 11 +++ gfx/wr/webrender/res/brush_image.glsl | 113 +++++++++++++++----------- gfx/wr/webrender/res/brush_solid.glsl | 16 ++-- 3 files changed, 85 insertions(+), 55 deletions(-) diff --git a/gfx/wr/webrender/res/brush.glsl b/gfx/wr/webrender/res/brush.glsl index ecc1dd3873f2..8920668fe763 100644 --- a/gfx/wr/webrender/res/brush.glsl +++ b/gfx/wr/webrender/res/brush.glsl @@ -61,6 +61,17 @@ flat varying int v_brush_kind; #endif +// A few varying slots for the brushes to use. +// Using these instead of adding dedicated varyings avoids using a high +// number of varyings in the multi-brush shader. +flat varying vec4 flat_varying_vec4_0; +flat varying vec4 flat_varying_vec4_1; +flat varying vec4 flat_varying_vec4_2; +flat varying vec4 flat_varying_vec4_3; +flat varying vec4 flat_varying_vec4_4; +varying vec4 varying_vec4_0; +varying vec4 varying_vec4_1; + #ifdef WR_VERTEX_SHADER #define FWD_DECLARE_VS_FUNCTION(name) \ diff --git a/gfx/wr/webrender/res/brush_image.glsl b/gfx/wr/webrender/res/brush_image.glsl index f86fdc17c0d7..eb2e5568a1e5 100644 --- a/gfx/wr/webrender/res/brush_image.glsl +++ b/gfx/wr/webrender/res/brush_image.glsl @@ -11,25 +11,28 @@ #include shared,prim_shared,brush #ifdef WR_FEATURE_ALPHA_PASS -varying vec2 vLocalPos; +#define V_LOCAL_POS varying_vec4_0.xy #endif // Interpolated UV coordinates to sample. -varying vec2 vUv; -// X = layer index to sample, Y = flag to allow perspective interpolation of UV. -flat varying vec2 vLayerAndPerspective; -// Normalized bounds of the source image in the texture. -flat varying vec4 vUvBounds; -// Normalized bounds of the source image in the texture, adjusted to avoid -// sampling artifacts. -flat varying vec4 vUvSampleBounds; +#define V_UV varying_vec4_0.zw #ifdef WR_FEATURE_ALPHA_PASS -flat varying vec4 vColor; -flat varying vec2 vMaskSwizzle; -flat varying vec2 vTileRepeat; +#define V_COLOR flat_varying_vec4_0 +#define V_MASK_SWIZZLE flat_varying_vec4_1.xy +#define V_TILE_REPEAT flat_varying_vec4_1.zw #endif +// Normalized bounds of the source image in the texture. +#define V_UV_BOUNDS flat_varying_vec4_2 +// Normalized bounds of the source image in the texture, adjusted to avoid +// sampling artifacts. +#define V_UV_SAMPLE_BOUNDS flat_varying_vec4_3 +// Layer index to sample. +#define V_LAYER flat_varying_vec4_4.x +// Flag to allow perspective interpolation of UV. +#define V_PERSPECTIVE flat_varying_vec4_4.y + #ifdef WR_VERTEX_SHADER // Must match the AlphaType enum. @@ -112,14 +115,15 @@ void image_brush_vs( } float perspective_interpolate = (brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0 ? 1.0 : 0.0; - vLayerAndPerspective = vec2(res.layer, perspective_interpolate); + V_LAYER = res.layer; + V_PERSPECTIVE = perspective_interpolate; // Handle case where the UV coords are inverted (e.g. from an // external image). vec2 min_uv = min(uv0, uv1); vec2 max_uv = max(uv0, uv1); - vUvSampleBounds = vec4( + V_UV_SAMPLE_BOUNDS = vec4( min_uv + vec2(0.5), max_uv - vec2(0.5) ) / texture_size.xyxy; @@ -151,23 +155,23 @@ void image_brush_vs( } #endif - // Offset and scale vUv here to avoid doing it in the fragment shader. + // Offset and scale V_UV here to avoid doing it in the fragment shader. vec2 repeat = local_rect.size / stretch_size; - vUv = mix(uv0, uv1, f) - min_uv; - vUv /= texture_size; - vUv *= repeat.xy; + V_UV = mix(uv0, uv1, f) - min_uv; + V_UV /= texture_size; + V_UV *= repeat.xy; if (perspective_interpolate == 0.0) { - vUv *= vi.world_pos.w; + V_UV *= vi.world_pos.w; } #ifdef WR_FEATURE_TEXTURE_RECT - vUvBounds = vec4(0.0, 0.0, vec2(textureSize(sColor0))); + V_UV_BOUNDS = vec4(0.0, 0.0, vec2(textureSize(sColor0))); #else - vUvBounds = vec4(min_uv, max_uv) / texture_size.xyxy; + V_UV_BOUNDS = vec4(min_uv, max_uv) / texture_size.xyxy; #endif #ifdef WR_FEATURE_ALPHA_PASS - vTileRepeat = repeat.xy; + V_TILE_REPEAT = repeat.xy; float opacity = float(prim_user_data.z) / 65535.0; switch (blend_mode) { @@ -183,31 +187,31 @@ void image_brush_vs( switch (color_mode) { case COLOR_MODE_ALPHA: case COLOR_MODE_BITMAP: - vMaskSwizzle = vec2(0.0, 1.0); - vColor = image_data.color; + V_MASK_SWIZZLE = vec2(0.0, 1.0); + V_COLOR = image_data.color; break; case COLOR_MODE_SUBPX_BG_PASS2: case COLOR_MODE_SUBPX_DUAL_SOURCE: case COLOR_MODE_IMAGE: - vMaskSwizzle = vec2(1.0, 0.0); - vColor = image_data.color; + V_MASK_SWIZZLE = vec2(1.0, 0.0); + V_COLOR = image_data.color; break; case COLOR_MODE_SUBPX_CONST_COLOR: case COLOR_MODE_SUBPX_BG_PASS0: case COLOR_MODE_COLOR_BITMAP: - vMaskSwizzle = vec2(1.0, 0.0); - vColor = vec4(image_data.color.a); + V_MASK_SWIZZLE = vec2(1.0, 0.0); + V_COLOR = vec4(image_data.color.a); break; case COLOR_MODE_SUBPX_BG_PASS1: - vMaskSwizzle = vec2(-1.0, 1.0); - vColor = vec4(image_data.color.a) * image_data.background_color; + V_MASK_SWIZZLE = vec2(-1.0, 1.0); + V_COLOR = vec4(image_data.color.a) * image_data.background_color; break; default: - vMaskSwizzle = vec2(0.0); - vColor = vec4(1.0); + V_MASK_SWIZZLE = vec2(0.0); + V_COLOR = vec4(1.0); } - vLocalPos = vi.local_pos; + V_LOCAL_POS = vi.local_pos; #endif } #endif @@ -215,62 +219,62 @@ void image_brush_vs( #ifdef WR_FRAGMENT_SHADER vec2 compute_repeated_uvs(float perspective_divisor) { - vec2 uv_size = vUvBounds.zw - vUvBounds.xy; + vec2 uv_size = V_UV_BOUNDS.zw - V_UV_BOUNDS.xy; #ifdef WR_FEATURE_ALPHA_PASS // This prevents the uv on the top and left parts of the primitive that was inflated // for anti-aliasing purposes from going beyound the range covered by the regular // (non-inflated) primitive. - vec2 local_uv = max(vUv * perspective_divisor, vec2(0.0)); + vec2 local_uv = max(V_UV * perspective_divisor, vec2(0.0)); // Handle horizontal and vertical repetitions. - vec2 repeated_uv = mod(local_uv, uv_size) + vUvBounds.xy; + vec2 repeated_uv = mod(local_uv, uv_size) + V_UV_BOUNDS.xy; // This takes care of the bottom and right inflated parts. // We do it after the modulo because the latter wraps around the values exactly on // the right and bottom edges, which we do not want. - if (local_uv.x >= vTileRepeat.x * uv_size.x) { - repeated_uv.x = vUvBounds.z; + if (local_uv.x >= V_TILE_REPEAT.x * uv_size.x) { + repeated_uv.x = V_UV_BOUNDS.z; } - if (local_uv.y >= vTileRepeat.y * uv_size.y) { - repeated_uv.y = vUvBounds.w; + if (local_uv.y >= V_TILE_REPEAT.y * uv_size.y) { + repeated_uv.y = V_UV_BOUNDS.w; } #else - vec2 repeated_uv = mod(vUv * perspective_divisor, uv_size) + vUvBounds.xy; + vec2 repeated_uv = mod(V_UV * perspective_divisor, uv_size) + V_UV_BOUNDS.xy; #endif return repeated_uv; } Fragment image_brush_fs() { - float perspective_divisor = mix(gl_FragCoord.w, 1.0, vLayerAndPerspective.y); + float perspective_divisor = mix(gl_FragCoord.w, 1.0, V_PERSPECTIVE); #ifdef WR_FEATURE_REPETITION vec2 repeated_uv = compute_repeated_uvs(perspective_divisor); #else - vec2 repeated_uv = vUv * perspective_divisor + vUvBounds.xy; + vec2 repeated_uv = V_UV * perspective_divisor + V_UV_BOUNDS.xy; #endif // Clamp the uvs to avoid sampling artifacts. - vec2 uv = clamp(repeated_uv, vUvSampleBounds.xy, vUvSampleBounds.zw); + vec2 uv = clamp(repeated_uv, V_UV_SAMPLE_BOUNDS.xy, V_UV_SAMPLE_BOUNDS.zw); - vec4 texel = TEX_SAMPLE(sColor0, vec3(uv, vLayerAndPerspective.x)); + vec4 texel = TEX_SAMPLE(sColor0, vec3(uv, V_LAYER)); Fragment frag; #ifdef WR_FEATURE_ALPHA_PASS #ifdef WR_FEATURE_ANTIALIASING - float alpha = init_transform_fs(vLocalPos); + float alpha = init_transform_fs(V_LOCAL_POS); #else float alpha = 1.0; #endif - texel.rgb = texel.rgb * vMaskSwizzle.x + texel.aaa * vMaskSwizzle.y; + texel.rgb = texel.rgb * V_MASK_SWIZZLE.x + texel.aaa * V_MASK_SWIZZLE.y; vec4 alpha_mask = texel * alpha; - frag.color = vColor * alpha_mask; + frag.color = V_COLOR * alpha_mask; #ifdef WR_FEATURE_DUAL_SOURCE_BLENDING - frag.blend = alpha_mask * vColor.a; + frag.blend = alpha_mask * V_COLOR.a; #endif #else frag.color = texel; @@ -279,3 +283,14 @@ Fragment image_brush_fs() { return frag; } #endif + +// Undef macro names that could be re-defined by other shaders. +#undef V_LOCAL_POS +#undef V_UV +#undef V_COLOR +#undef V_MASK_SWIZZLE +#undef V_TILE_REPEAT +#undef V_UV_BOUNDS +#undef V_UV_SAMPLE_BOUNDS +#undef V_LAYER +#undef V_PERSPECTIVE diff --git a/gfx/wr/webrender/res/brush_solid.glsl b/gfx/wr/webrender/res/brush_solid.glsl index f5ba7eae13f2..86713b04d125 100644 --- a/gfx/wr/webrender/res/brush_solid.glsl +++ b/gfx/wr/webrender/res/brush_solid.glsl @@ -10,10 +10,10 @@ #include shared,prim_shared,brush -flat varying vec4 vColor; +#define V_COLOR flat_varying_vec4_0 #ifdef WR_FEATURE_ALPHA_PASS -varying vec2 vLocalPos; +#define V_LOCAL_POS varying_vec4_0.xy #endif #ifdef WR_VERTEX_SHADER @@ -42,20 +42,24 @@ void solid_brush_vs( SolidBrush prim = fetch_solid_primitive(prim_address); float opacity = float(prim_user_data.x) / 65535.0; - vColor = prim.color * opacity; + V_COLOR = prim.color * opacity; #ifdef WR_FEATURE_ALPHA_PASS - vLocalPos = vi.local_pos; + V_LOCAL_POS = vi.local_pos; #endif } #endif #ifdef WR_FRAGMENT_SHADER Fragment solid_brush_fs() { - vec4 color = vColor; + vec4 color = V_COLOR; #ifdef WR_FEATURE_ALPHA_PASS - color *= init_transform_fs(vLocalPos); + color *= init_transform_fs(V_LOCAL_POS); #endif return Fragment(color); } #endif + +// Undef macro names that could be re-defined by other shaders. +#undef V_COLOR +#undef V_LOCAL_POS