Bug 1594128 - Dynamically choose the brush kind in the shader. r=gw

This is an experiment with only image and solid to see what the infrastructure can be like.
If it works out I'll extend the it with more brush types. More work will be needed to get text rendering in there as well.

The multi-brush shader includes all brushes that it potentially needs suport for. Which brushes actually get compiled in is then specified via WR_FEATURE defines.
Since brushes can't have the same names for their entry points, they specify the function to use via a macros (WR_BRUSH_VS_FUNCTION and WR_BRUSH_FS_FUNCTION).

Differential Revision: https://phabricator.services.mozilla.com/D53725

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nicolas Silva 2019-11-21 17:37:01 +00:00
Родитель b5ce761dc6
Коммит e9fa42a649
12 изменённых файлов: 203 добавлений и 55 удалений

Просмотреть файл

@ -47,21 +47,46 @@
///
// These constants must match the BrushShaderKind enum in gpu_types.rs.
#define BRUSH_KIND_SOLID 0x1000000
#define BRUSH_KIND_IMAGE 0x2000000
#define BRUSH_KIND_TEXT 0x3000000
#define BRUSH_KIND_LINEAR_GRADIENT 0x4000000
#define BRUSH_KIND_RADIAL_GRADIENT 0x5000000
#define BRUSH_KIND_BLEND 0x6000000
#define BRUSH_KIND_MIX_BLEND 0x7000000
#define BRUSH_KIND_YV 0x8000000
#ifdef WR_FEATURE_MULTI_BRUSH
flat varying int v_brush_kind;
#endif
#ifdef WR_VERTEX_SHADER
void brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
RectWithSize segment_rect,
ivec4 prim_user_data,
int specific_resource_address,
mat4 transform,
PictureTask pic_task,
int brush_flags,
vec4 segment_data
#define FWD_DECLARE_VS_FUNCTION(name) \
void name( \
VertexInfo vi, \
int prim_address, \
RectWithSize local_rect, \
RectWithSize segment_rect, \
ivec4 prim_user_data, \
int specific_resource_address, \
mat4 transform, \
PictureTask pic_task, \
int brush_flags, \
vec4 segment_data \
);
// Forward-declare all brush vertex entry points.
FWD_DECLARE_VS_FUNCTION(image_brush_vs)
FWD_DECLARE_VS_FUNCTION(solid_brush_vs)
FWD_DECLARE_VS_FUNCTION(blend_brush_vs)
FWD_DECLARE_VS_FUNCTION(mix_blend_brush_vs)
FWD_DECLARE_VS_FUNCTION(linear_gradient_brush_vs)
FWD_DECLARE_VS_FUNCTION(radial_gradient_brush_vs)
FWD_DECLARE_VS_FUNCTION(yuv_brush_vs)
#define VECS_PER_SEGMENT 2
#define BRUSH_FLAG_PERSPECTIVE_INTERPOLATION 1
@ -72,10 +97,11 @@ void brush_vs(
#define INVALID_SEGMENT_INDEX 0xffff
// These constants must match the BrushShaderKind enum in gpu_types.rs.
#define BRUSH_KIND_SOLID 0x1000000
#define BRUSH_KIND_IMAGE 0x2000000
#define BRUSH_KIND_TEXT 0x4000000
#ifndef WR_FEATURE_MULTI_BRUSH
int vecs_per_brush(int brush_kind) {
return VECS_PER_SPECIFIC_BRUSH;
}
#endif
void main(void) {
// Load the brush instance from vertex attributes.
@ -92,7 +118,7 @@ void main(void) {
segment_data = vec4(0.0);
} else {
int segment_address = ph.specific_prim_address +
VECS_PER_SPECIFIC_BRUSH +
vecs_per_brush(instance.brush_kind) +
instance.segment_index * VECS_PER_SEGMENT;
vec4[2] segment_info = fetch_from_gpu_cache_2(segment_address);
@ -157,19 +183,36 @@ void main(void) {
#endif
// Run the specific brush VS code to write interpolators.
brush_vs(
vi,
ph.specific_prim_address,
ph.local_rect,
segment_rect,
ph.user_data,
instance.resource_address,
transform.m,
pic_task,
brush_flags,
segment_data
);
#define BRUSH_VS_PARAMS vi, ph.specific_prim_address, ph.local_rect, \
segment_rect, ph.user_data, instance.resource_address, transform.m, \
pic_task, brush_flags, segment_data
// If this shader supports multiple brushes, select the right one
// for this instance instance.
#ifdef WR_FEATURE_MULTI_BRUSH
v_brush_kind = instance.brush_kind;
switch (instance.brush_kind) {
#ifdef WR_FEATURE_IMAGE_BRUSH
case BRUSH_KIND_IMAGE:
image_brush_vs(BRUSH_VS_PARAMS);
break;
#endif
#ifdef WR_FEATURE_SOLID_BRUSH
case BRUSH_KIND_SOLID:
solid_brush_vs(BRUSH_VS_PARAMS);
break;
#endif
}
#else
WR_BRUSH_VS_FUNCTION(BRUSH_VS_PARAMS);
#endif
}
#endif
#ifdef WR_FRAGMENT_SHADER
@ -181,14 +224,41 @@ struct Fragment {
#endif
};
Fragment brush_fs();
// Foward-declare all brush entry-points.
Fragment image_brush_fs();
Fragment solid_brush_fs();
Fragment blend_brush_fs();
Fragment mix_blend_brush_fs();
Fragment linear_gradient_brush_fs();
Fragment radial_gradient_brush_fs();
Fragment yuv_brush_fs();
void main(void) {
#ifdef WR_FEATURE_DEBUG_OVERDRAW
oFragColor = WR_DEBUG_OVERDRAW_COLOR;
#else
Fragment frag;
// Run the specific brush FS code to output the color.
Fragment frag = brush_fs();
#ifdef WR_FEATURE_MULTI_BRUSH
switch (v_brush_kind) {
#ifdef WR_FEATURE_IMAGE_BRUSH
case BRUSH_KIND_IMAGE: {
frag = image_brush_fs();
break;
}
#endif
#ifdef WR_FEATURE_SOLID_BRUSH
case BRUSH_KIND_SOLID: {
frag = solid_brush_fs();
break;
}
#endif
}
#else
frag = WR_BRUSH_FS_FUNCTION();
#endif
#ifdef WR_FEATURE_ALPHA_PASS
// Apply the clip mask

Просмотреть файл

@ -2,7 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define VECS_PER_SPECIFIC_BRUSH 3
#define VECS_PER_BLEND_BRUSH 3
#define VECS_PER_SPECIFIC_BRUSH VECS_PER_BLEND_BRUSH
#define WR_BRUSH_VS_FUNCTION blend_brush_vs
#define WR_BRUSH_FS_FUNCTION blend_brush_fs
#define COMPONENT_TRANSFER_IDENTITY 0
#define COMPONENT_TRANSFER_TABLE 1
@ -29,7 +33,7 @@ flat varying vec4 vFloodColor;
#ifdef WR_VERTEX_SHADER
void brush_vs(
void blend_brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
@ -237,7 +241,7 @@ vec4 ComponentTransfer(vec4 colora) {
return colora;
}
Fragment brush_fs() {
Fragment blend_brush_fs() {
float perspective_divisor = mix(gl_FragCoord.w, 1.0, vLayerAndPerspective.y);
vec2 uv = vUv * perspective_divisor;
vec4 Cs = texture(sColor0, vec3(uv, vLayerAndPerspective.x));

Просмотреть файл

@ -2,7 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define VECS_PER_SPECIFIC_BRUSH 3
#define VECS_PER_IMAGE_BRUSH 3
#define VECS_PER_SPECIFIC_BRUSH VECS_PER_IMAGE_BRUSH
#define WR_BRUSH_VS_FUNCTION image_brush_vs
#define WR_BRUSH_FS_FUNCTION image_brush_fs
#include shared,prim_shared,brush
@ -48,7 +52,7 @@ ImageBrushData fetch_image_data(int address) {
return data;
}
void brush_vs(
void image_brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize prim_rect,
@ -238,7 +242,7 @@ vec2 compute_repeated_uvs(float perspective_divisor) {
return repeated_uv;
}
Fragment brush_fs() {
Fragment image_brush_fs() {
float perspective_divisor = mix(gl_FragCoord.w, 1.0, vLayerAndPerspective.y);
#ifdef WR_FEATURE_REPETITION

Просмотреть файл

@ -2,7 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define VECS_PER_SPECIFIC_BRUSH 2
#define VECS_PER_LINEAR_GRADIENT_BRUSH 2
#define VECS_PER_SPECIFIC_BRUSH VECS_PER_LINEAR_GRADIENT_BRUSH
#define WR_BRUSH_VS_FUNCTION linear_gradient_brush_vs
#define WR_BRUSH_FS_FUNCTION linear_gradient_brush_fs
#include shared,prim_shared,brush
@ -40,7 +44,7 @@ Gradient fetch_gradient(int address) {
);
}
void brush_vs(
void linear_gradient_brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
@ -85,7 +89,7 @@ void brush_vs(
#endif
#ifdef WR_FRAGMENT_SHADER
Fragment brush_fs() {
Fragment linear_gradient_brush_fs() {
#ifdef WR_FEATURE_ALPHA_PASS
// Handle top and left inflated edges (see brush_image).

Просмотреть файл

@ -2,7 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define VECS_PER_SPECIFIC_BRUSH 3
#define VECS_PER_MIX_BLEND_BRUSH 3
#define VECS_PER_SPECIFIC_BRUSH VECS_PER_MIX_BLEND_BRUSH
#define WR_BRUSH_VS_FUNCTION mix_blend_brush_vs
#define WR_BRUSH_FS_FUNCTION mix_blend_brush_fs
#include shared,prim_shared,brush
@ -17,7 +21,7 @@ vec2 snap_device_pos(VertexInfo vi, float device_pixel_scale) {
return vi.world_pos.xy * device_pixel_scale / max(0.0, vi.world_pos.w) + vi.snap_offset;
}
void brush_vs(
void mix_blend_brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
@ -205,7 +209,7 @@ const int MixBlendMode_Saturation = 13;
const int MixBlendMode_Color = 14;
const int MixBlendMode_Luminosity = 15;
Fragment brush_fs() {
Fragment mix_blend_brush_fs() {
vec4 Cb = textureLod(sPrevPassColor, vBackdropUv, 0.0);
vec4 Cs = textureLod(sPrevPassColor, vSrcUv, 0.0);

Просмотреть файл

@ -0,0 +1,40 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define WR_FEATURE_MULTI_BRUSH
#include shared,prim_shared
int vecs_per_brush(int brush_kind);
#ifdef WR_FEATURE_IMAGE_BRUSH
#include brush_image
#endif
#undef VECS_PER_SPECIFIC_BRUSH
#undef WR_BRUSH_VS_FUNCTION
#undef WR_BRUSH_FS_FUNCTION
#ifdef WR_FEATURE_SOLID_BRUSH
#include brush_solid
#endif
int vecs_per_brush(int brush_kind) {
int result;
switch (brush_kind) {
#ifdef WR_FEATURE_IMAGE_BRUSH
case BRUSH_KIND_IMAGE:
result = VECS_PER_IMAGE_BRUSH;
break;
#endif
#ifdef WR_FEATURE_IMAGE_BRUSH
case BRUSH_KIND_SOLID:
result = VECS_PER_SOLID_BRUSH;
break;
#endif
}
return result;
}

Просмотреть файл

@ -2,7 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define VECS_PER_SPECIFIC_BRUSH 2
#define VECS_PER_RADIAL_GRADIENT_BRUSH 2
#define VECS_PER_SPECIFIC_BRUSH VECS_PER_RADIAL_GRADIENT_BRUSH
#define WR_BRUSH_VS_FUNCTION radial_gradient_brush_vs
#define WR_BRUSH_FS_FUNCTION radial_gradient_brush_fs
#include shared,prim_shared,brush
@ -40,7 +44,7 @@ RadialGradient fetch_radial_gradient(int address) {
);
}
void brush_vs(
void radial_gradient_brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
@ -87,7 +91,7 @@ void brush_vs(
#endif
#ifdef WR_FRAGMENT_SHADER
Fragment brush_fs() {
Fragment radial_gradient_brush_fs() {
#ifdef WR_FEATURE_ALPHA_PASS
// Handle top and left inflated edges (see brush_image).

Просмотреть файл

@ -2,7 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define VECS_PER_SPECIFIC_BRUSH 1
#define VECS_PER_SOLID_BRUSH 1
#define VECS_PER_SPECIFIC_BRUSH VECS_PER_SOLID_BRUSH
#define WR_BRUSH_VS_FUNCTION solid_brush_vs
#define WR_BRUSH_FS_FUNCTION solid_brush_fs
#include shared,prim_shared,brush
@ -23,7 +27,7 @@ SolidBrush fetch_solid_primitive(int address) {
return SolidBrush(data);
}
void brush_vs(
void solid_brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
@ -47,7 +51,7 @@ void brush_vs(
#endif
#ifdef WR_FRAGMENT_SHADER
Fragment brush_fs() {
Fragment solid_brush_fs() {
vec4 color = vColor;
#ifdef WR_FEATURE_ALPHA_PASS
color *= init_transform_fs(vLocalPos);

Просмотреть файл

@ -2,7 +2,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define VECS_PER_SPECIFIC_BRUSH 1
#define VECS_PER_YUV_BRUSH 1
#define VECS_PER_SPECIFIC_BRUSH VECS_PER_YUV_BRUSH
#define WR_BRUSH_VS_FUNCTION yuv_brush_vs
#define WR_BRUSH_FS_FUNCTION yuv_brush_fs
#include shared,prim_shared,brush
@ -120,7 +124,7 @@ YuvPrimitive fetch_yuv_primitive(int address) {
return YuvPrimitive(data.x, int(data.y), int(data.z));
}
void brush_vs(
void yuv_brush_vs(
VertexInfo vi,
int prim_address,
RectWithSize local_rect,
@ -165,7 +169,7 @@ void brush_vs(
#ifdef WR_FRAGMENT_SHADER
Fragment brush_fs() {
Fragment yuv_brush_fs() {
vec3 yuv_value;
if (vFormat == YUV_FORMAT_PLANAR) {

Просмотреть файл

@ -75,6 +75,11 @@ impl BatchKind {
match self {
BatchKind::Brush(BrushBatchKind::Solid) => BrushShaderKind::Solid,
BatchKind::Brush(BrushBatchKind::Image(..)) => BrushShaderKind::Image,
BatchKind::Brush(BrushBatchKind::LinearGradient) => BrushShaderKind::LinearGradient,
BatchKind::Brush(BrushBatchKind::RadialGradient) => BrushShaderKind::RadialGradient,
BatchKind::Brush(BrushBatchKind::Blend) => BrushShaderKind::Blend,
BatchKind::Brush(BrushBatchKind::MixBlend { .. }) => BrushShaderKind::MixBlend,
BatchKind::Brush(BrushBatchKind::YuvImage(..)) => BrushShaderKind::Yuv,
BatchKind::TextRun(..) => BrushShaderKind::Text,
_ => BrushShaderKind::None,
}

Просмотреть файл

@ -73,9 +73,14 @@ impl ZBufferIdGenerator {
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum BrushShaderKind {
None = 0,
Solid = 0x1000000,
Image = 0x2000000,
Text = 0x4000000,
Solid = 0x1000000,
Image = 0x2000000,
Text = 0x3000000,
LinearGradient = 0x4000000,
RadialGradient = 0x5000000,
Blend = 0x6000000,
MixBlend = 0x7000000,
Yuv = 0x8000000,
}
#[derive(Debug, Copy, Clone)]

Просмотреть файл

@ -79,7 +79,7 @@ impl ShaderSourceParser {
/// Reads a shader source file from disk into a String.
pub fn shader_source_from_file(shader_path: &Path) -> String {
assert!(shader_path.exists(), "Shader not found");
assert!(shader_path.exists(), "Shader not found {:?}", shader_path);
let mut source = String::new();
File::open(&shader_path)
.expect("Shader not found")