mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-03 04:27:41 +00:00
Bug 1894106 - Supply tile rect to composite shader in device space. r=gfx-reviewers,gw
Currently the composite shader takes as input the tile rect in local space, a local-to-device, transform, and the clip rect in device space. The shader will then transform the local rect in to device space and then clip it. On the CPU side, that clip rect was calculated by transforming the same tile rect in to device space using the same transform. (And intersecting with additional rects too). However, performing the same floating point calculations on the CPU and GPU can produce slightly different results. Discrepancies between the device rect as calculated by the CPU and GPU were causing the tiles to occasionally be clipped fractionally smaller than intended, which was resulting in visible seams whilst zooming a page. To fix this, we supply the tile rect in device space to the shader, meaning the transformation is only ever calculated on the CPU. As the transform could contain a negative scale to indicate a flip, we replace it with a "flip" input for each axis. Differential Revision: https://phabricator.services.mozilla.com/D211989
This commit is contained in:
parent
001af07af3
commit
a9a71d0ad7
@ -45,11 +45,11 @@ uniform mediump vec2 uTextureSize;
|
||||
// CPU side data is in CompositeInstance (gpu_types.rs) and is
|
||||
// converted to GPU data using desc::COMPOSITE (renderer.rs) by
|
||||
// filling vaos.composite_vao with VertexArrayKind::Composite.
|
||||
PER_INSTANCE attribute vec4 aLocalRect;
|
||||
PER_INSTANCE attribute vec4 aDeviceRect;
|
||||
PER_INSTANCE attribute vec4 aDeviceClipRect;
|
||||
PER_INSTANCE attribute vec4 aColor;
|
||||
PER_INSTANCE attribute vec4 aParams;
|
||||
PER_INSTANCE attribute vec4 aTransform;
|
||||
PER_INSTANCE attribute vec2 aFlip;
|
||||
|
||||
#ifdef WR_FEATURE_YUV
|
||||
// YUV treats these as a UV clip rect (clamp)
|
||||
@ -60,10 +60,6 @@ PER_INSTANCE attribute vec4 aUvRect2;
|
||||
PER_INSTANCE attribute vec4 aUvRect0;
|
||||
#endif
|
||||
|
||||
vec2 apply_transform(vec2 p, vec4 transform) {
|
||||
return p * transform.xy + transform.zw;
|
||||
}
|
||||
|
||||
#ifdef WR_FEATURE_YUV
|
||||
YuvPrimitive fetch_yuv_primitive() {
|
||||
// From ExternalSurfaceDependency::Yuv:
|
||||
@ -75,16 +71,17 @@ YuvPrimitive fetch_yuv_primitive() {
|
||||
#endif
|
||||
|
||||
void main(void) {
|
||||
// Get world position
|
||||
vec2 world_p0 = apply_transform(aLocalRect.xy, aTransform);
|
||||
vec2 world_p1 = apply_transform(aLocalRect.zw, aTransform);
|
||||
vec2 world_pos = mix(world_p0, world_p1, aPosition.xy);
|
||||
// Flip device rect if required
|
||||
vec4 device_rect = mix(aDeviceRect.xyzw, aDeviceRect.zwxy, aFlip.xyxy);
|
||||
|
||||
// Get world position
|
||||
vec2 world_pos = mix(device_rect.xy, device_rect.zw, aPosition.xy);
|
||||
|
||||
// Clip the position to the world space clip rect
|
||||
vec2 clipped_world_pos = clamp(world_pos, aDeviceClipRect.xy, aDeviceClipRect.zw);
|
||||
|
||||
// Derive the normalized UV from the clipped vertex position
|
||||
vec2 uv = (clipped_world_pos - world_p0) / (world_p1 - world_p0);
|
||||
vec2 uv = (clipped_world_pos - device_rect.xy) / (device_rect.zw - device_rect.xy);
|
||||
|
||||
#ifdef WR_FEATURE_YUV
|
||||
YuvPrimitive prim = fetch_yuv_primitive();
|
||||
|
@ -252,17 +252,6 @@ pub struct CompositorTransform {
|
||||
pub ty: f32,
|
||||
}
|
||||
|
||||
impl CompositorTransform {
|
||||
pub fn identity() -> Self {
|
||||
CompositorTransform {
|
||||
sx: 1.0,
|
||||
sy: 1.0,
|
||||
tx: 0.0,
|
||||
ty: 0.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ScaleOffset> for CompositorTransform {
|
||||
fn from(scale_offset: ScaleOffset) -> Self {
|
||||
CompositorTransform {
|
||||
@ -280,8 +269,8 @@ impl From<ScaleOffset> for CompositorTransform {
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct CompositeInstance {
|
||||
// Picture space destination rectangle of surface
|
||||
rect: PictureRect,
|
||||
// Device space destination rectangle of surface
|
||||
rect: DeviceRect,
|
||||
// Device space destination clip rect for this surface
|
||||
clip_rect: DeviceRect,
|
||||
// Color for solid color tiles, white otherwise
|
||||
@ -297,16 +286,16 @@ pub struct CompositeInstance {
|
||||
// UV rectangles (pixel space) for color / yuv texture planes
|
||||
uv_rects: [TexelRect; 3],
|
||||
|
||||
// A 2d scale + offset transform for the rect
|
||||
transform: CompositorTransform,
|
||||
// Whether to flip the x and y axis respectively, where 0.0 is no-flip and 1.0 is flip.
|
||||
flip: (f32, f32),
|
||||
}
|
||||
|
||||
impl CompositeInstance {
|
||||
pub fn new(
|
||||
rect: PictureRect,
|
||||
rect: DeviceRect,
|
||||
clip_rect: DeviceRect,
|
||||
color: PremultipliedColorF,
|
||||
transform: CompositorTransform,
|
||||
flip: (bool, bool),
|
||||
) -> Self {
|
||||
let uv = TexelRect::new(0.0, 0.0, 1.0, 1.0);
|
||||
CompositeInstance {
|
||||
@ -318,16 +307,16 @@ impl CompositeInstance {
|
||||
yuv_format: 0.0,
|
||||
yuv_channel_bit_depth: 0.0,
|
||||
uv_rects: [uv, uv, uv],
|
||||
transform,
|
||||
flip: (flip.0.into(), flip.1.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_rgb(
|
||||
rect: PictureRect,
|
||||
rect: DeviceRect,
|
||||
clip_rect: DeviceRect,
|
||||
color: PremultipliedColorF,
|
||||
uv_rect: TexelRect,
|
||||
transform: CompositorTransform,
|
||||
flip: (bool, bool),
|
||||
) -> Self {
|
||||
CompositeInstance {
|
||||
rect,
|
||||
@ -338,18 +327,18 @@ impl CompositeInstance {
|
||||
yuv_format: 0.0,
|
||||
yuv_channel_bit_depth: 0.0,
|
||||
uv_rects: [uv_rect, uv_rect, uv_rect],
|
||||
transform,
|
||||
flip: (flip.0.into(), flip.1.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_yuv(
|
||||
rect: PictureRect,
|
||||
rect: DeviceRect,
|
||||
clip_rect: DeviceRect,
|
||||
yuv_color_space: YuvRangedColorSpace,
|
||||
yuv_format: YuvFormat,
|
||||
yuv_channel_bit_depth: u32,
|
||||
uv_rects: [TexelRect; 3],
|
||||
transform: CompositorTransform,
|
||||
flip: (bool, bool),
|
||||
) -> Self {
|
||||
CompositeInstance {
|
||||
rect,
|
||||
@ -360,7 +349,7 @@ impl CompositeInstance {
|
||||
yuv_format: pack_as_float(yuv_format as u32),
|
||||
yuv_channel_bit_depth: pack_as_float(yuv_channel_bit_depth),
|
||||
uv_rects,
|
||||
transform,
|
||||
flip: (flip.0.into(), flip.1.into()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ use glyph_rasterizer::GlyphFormat;
|
||||
use crate::gpu_cache::{GpuCacheUpdate, GpuCacheUpdateList};
|
||||
use crate::gpu_cache::{GpuCacheDebugChunk, GpuCacheDebugCmd};
|
||||
use crate::gpu_types::{ScalingInstance, SvgFilterInstance, SVGFEFilterInstance, CopyInstance, PrimitiveInstanceData};
|
||||
use crate::gpu_types::{BlurInstance, ClearInstance, CompositeInstance, CompositorTransform};
|
||||
use crate::gpu_types::{BlurInstance, ClearInstance, CompositeInstance};
|
||||
use crate::internal_types::{TextureSource, TextureCacheCategory, FrameId};
|
||||
#[cfg(any(feature = "capture", feature = "replay"))]
|
||||
use crate::internal_types::DebugOutput;
|
||||
@ -3043,7 +3043,7 @@ impl Renderer {
|
||||
];
|
||||
|
||||
let instance = CompositeInstance::new_yuv(
|
||||
surface_rect.cast_unit().to_f32(),
|
||||
surface_rect.to_f32(),
|
||||
surface_rect.to_f32(),
|
||||
// z-id is not relevant when updating a native compositor surface.
|
||||
// TODO(gw): Support compositor surfaces without z-buffer, for memory / perf win here.
|
||||
@ -3051,7 +3051,7 @@ impl Renderer {
|
||||
format,
|
||||
channel_bit_depth,
|
||||
uv_rects,
|
||||
CompositorTransform::identity(),
|
||||
(false, false),
|
||||
);
|
||||
|
||||
( textures, instance )
|
||||
@ -3074,11 +3074,11 @@ impl Renderer {
|
||||
let textures = BatchTextures::composite_rgb(plane.texture);
|
||||
let uv_rect = self.texture_resolver.get_uv_rect(&textures.input.colors[0], plane.uv_rect);
|
||||
let instance = CompositeInstance::new_rgb(
|
||||
surface_rect.cast_unit().to_f32(),
|
||||
surface_rect.to_f32(),
|
||||
surface_rect.to_f32(),
|
||||
PremultipliedColorF::WHITE,
|
||||
uv_rect,
|
||||
CompositorTransform::identity(),
|
||||
(false, false),
|
||||
);
|
||||
|
||||
( textures, instance )
|
||||
@ -3137,8 +3137,9 @@ impl Renderer {
|
||||
let tile = &composite_state.tiles[item.key];
|
||||
|
||||
let clip_rect = item.rectangle;
|
||||
let tile_rect = tile.local_rect;
|
||||
let transform = composite_state.get_device_transform(tile.transform_index).into();
|
||||
let transform = composite_state.get_device_transform(tile.transform_index);
|
||||
let tile_rect = transform.map_rect(&tile.local_rect);
|
||||
let flip = (transform.scale.x < 0.0, transform.scale.y < 0.0);
|
||||
|
||||
// Work out the draw params based on the tile surface
|
||||
let (instance, textures, shader_params) = match tile.surface {
|
||||
@ -3149,7 +3150,7 @@ impl Renderer {
|
||||
tile_rect,
|
||||
clip_rect,
|
||||
color.premultiplied(),
|
||||
transform,
|
||||
flip,
|
||||
);
|
||||
let features = instance.get_rgb_features();
|
||||
(
|
||||
@ -3163,7 +3164,7 @@ impl Renderer {
|
||||
tile_rect,
|
||||
clip_rect,
|
||||
PremultipliedColorF::WHITE,
|
||||
transform,
|
||||
flip,
|
||||
);
|
||||
let features = instance.get_rgb_features();
|
||||
(
|
||||
@ -3207,7 +3208,7 @@ impl Renderer {
|
||||
format,
|
||||
channel_bit_depth,
|
||||
uv_rects,
|
||||
transform,
|
||||
flip,
|
||||
),
|
||||
textures,
|
||||
(
|
||||
@ -3225,7 +3226,7 @@ impl Renderer {
|
||||
clip_rect,
|
||||
PremultipliedColorF::WHITE,
|
||||
uv_rect,
|
||||
transform,
|
||||
flip,
|
||||
);
|
||||
let features = instance.get_rgb_features();
|
||||
(
|
||||
@ -3248,7 +3249,7 @@ impl Renderer {
|
||||
tile_rect,
|
||||
clip_rect,
|
||||
PremultipliedColorF::BLACK,
|
||||
transform,
|
||||
flip,
|
||||
);
|
||||
let features = instance.get_rgb_features();
|
||||
(
|
||||
|
@ -725,7 +725,7 @@ pub mod desc {
|
||||
}],
|
||||
instance_attributes: &[
|
||||
VertexAttribute {
|
||||
name: "aLocalRect",
|
||||
name: "aDeviceRect",
|
||||
count: 4,
|
||||
kind: VertexAttributeKind::F32,
|
||||
},
|
||||
@ -760,8 +760,8 @@ pub mod desc {
|
||||
kind: VertexAttributeKind::F32,
|
||||
},
|
||||
VertexAttribute {
|
||||
name: "aTransform",
|
||||
count: 4,
|
||||
name: "aFlip",
|
||||
count: 2,
|
||||
kind: VertexAttributeKind::F32,
|
||||
},
|
||||
],
|
||||
|
Loading…
x
Reference in New Issue
Block a user