Bug 1704951 - Add SubSliceIndex and allow batch filtering with it r=gfx-reviewers,lsalzman

Add a struct for identifying which sub-slice a primitive exists on,
and allow filtering of batches by this field.

Since we only ever create a single sub-slice, this change has no
effect yet, until follow up patches that enable multiple sub-slices.

Differential Revision: https://phabricator.services.mozilla.com/D111959
This commit is contained in:
Glenn Watson 2021-04-14 01:04:25 +00:00
Родитель bb6da3ed7b
Коммит 111df5d476
4 изменённых файлов: 69 добавлений и 6 удалений

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

@ -17,7 +17,7 @@ use crate::gpu_types::{PrimitiveHeader, PrimitiveHeaderIndex, TransformPaletteId
use crate::gpu_types::{ImageBrushData, get_shader_opacity, BoxShadowData};
use crate::gpu_types::{ClipMaskInstanceCommon, ClipMaskInstanceImage, ClipMaskInstanceRect, ClipMaskInstanceBoxShadow};
use crate::internal_types::{FastHashMap, Swizzle, TextureSource, Filter};
use crate::picture::{ClusterFlags, Picture3DContext, PictureCompositeMode, PicturePrimitive};
use crate::picture::{ClusterFlags, Picture3DContext, PictureCompositeMode, PicturePrimitive, SubSliceIndex};
use crate::prim_store::{DeferredResolve, PrimitiveInstanceKind, ClipData};
use crate::prim_store::{VisibleGradientTile, PrimitiveInstance, PrimitiveOpacity, SegmentInstanceIndex};
use crate::prim_store::{BrushSegment, ClipMaskKind, ClipTaskIndex};
@ -53,10 +53,12 @@ const CLIP_RECTANGLE_AREA_THRESHOLD: f32 = (CLIP_RECTANGLE_TILE_SIZE * CLIP_RECT
#[derive(Copy, Clone, Debug)]
pub struct BatchFilter {
pub rect_in_pic_space: PictureRect,
pub sub_slice_index: SubSliceIndex,
}
impl BatchFilter {
pub fn matches(&self, other: &BatchFilter) -> bool {
self.sub_slice_index == other.sub_slice_index &&
self.rect_in_pic_space.intersects(&other.rect_in_pic_space)
}
}

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

@ -14,7 +14,7 @@ use crate::gpu_types::{PrimitiveHeaders, TransformPalette, ZBufferIdGenerator};
use crate::gpu_types::TransformData;
use crate::internal_types::{FastHashMap, PlaneSplitter};
use crate::picture::{DirtyRegion, PictureUpdateState, SliceId, TileCacheInstance};
use crate::picture::{SurfaceInfo, SurfaceIndex, ROOT_SURFACE_INDEX, SurfaceRenderTasks};
use crate::picture::{SurfaceInfo, SurfaceIndex, ROOT_SURFACE_INDEX, SurfaceRenderTasks, SubSliceIndex};
use crate::picture::{BackdropKind, SubpixelMode, TileCacheLogger, RasterConfig, PictureCompositeMode};
use crate::prepare::prepare_primitives;
use crate::prim_store::{PictureIndex, PrimitiveDebugId};
@ -455,6 +455,7 @@ impl FrameBuilder {
);
default_dirty_region.add_dirty_region(
frame_context.global_screen_world_rect.cast_unit(),
SubSliceIndex::DEFAULT,
frame_context.spatial_tree,
);
frame_state.push_dirty_region(default_dirty_region);

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

@ -1765,6 +1765,7 @@ impl DirtyRegion {
pub fn add_dirty_region(
&mut self,
rect_in_pic_space: PictureRect,
sub_slice_index: SubSliceIndex,
spatial_tree: &SpatialTree,
) {
let map_pic_to_world = SpaceMapper::new_with_target(
@ -1783,6 +1784,7 @@ impl DirtyRegion {
self.filters.push(BatchFilter {
rect_in_pic_space,
sub_slice_index,
});
}
@ -1813,6 +1815,7 @@ impl DirtyRegion {
combined = combined.union(&world_rect);
filters.push(BatchFilter {
rect_in_pic_space,
sub_slice_index: filter.sub_slice_index,
});
}
@ -2199,6 +2202,27 @@ pub struct TileCacheParams {
pub compositor_surface_count: usize,
}
/// Defines which sub-slice (effectively a z-index) a primitive exists on within
/// a picture cache instance.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct SubSliceIndex(u8);
impl SubSliceIndex {
pub const DEFAULT: SubSliceIndex = SubSliceIndex(0);
pub fn new(index: usize) -> Self {
SubSliceIndex(index as u8)
}
/// Return true if this sub-slice is the primary sub-slice (for now, we assume
/// that only the primary sub-slice may be opaque and support subpixel AA, for example).
pub fn is_primary(&self) -> bool {
self.0 == 0
}
}
/// A SubSlice represents a potentially overlapping set of tiles within a picture cache. Most
/// picture cache instances will have only a single sub-slice. The exception to this is when
/// a picture cache has compositor surfaces, in which case sub slices are used to interleave
@ -2400,7 +2424,7 @@ impl TileCacheInstance {
/// Return the total number of tiles allocated by this tile cache
pub fn tile_count(&self) -> usize {
self.tile_rect.size.area() as usize
self.tile_rect.size.area() as usize * self.sub_slices.len()
}
/// Reset this tile cache with the updated parameters from a new scene
@ -2409,10 +2433,36 @@ impl TileCacheInstance {
pub fn prepare_for_new_scene(
&mut self,
params: TileCacheParams,
resource_cache: &mut ResourceCache,
) {
// We should only receive updated state for matching slice key
assert_eq!(self.slice, params.slice);
// TODO(gw): Read the compositor surface count from the params in a follow up.
let required_sub_slice_count = 1;
if self.sub_slices.len() != required_sub_slice_count {
self.tile_rect = TileRect::zero();
if self.sub_slices.len() > required_sub_slice_count {
let old_sub_slices = self.sub_slices.split_off(required_sub_slice_count);
for mut sub_slice in old_sub_slices {
for tile in sub_slice.tiles.values_mut() {
if let Some(TileSurface::Texture { descriptor: SurfaceTextureDescriptor::Native { ref mut id, .. }, .. }) = tile.surface {
if let Some(id) = id.take() {
resource_cache.destroy_compositor_tile(id);
}
}
}
}
} else {
while self.sub_slices.len() < required_sub_slice_count {
self.sub_slices.push(SubSlice::new());
}
}
}
// Store the parameters from the scene builder for this slice. Other
// params in the tile cache are retained and reused, or are always
// updated during pre/post_update.
@ -2814,7 +2864,7 @@ impl TileCacheInstance {
let mut world_culling_rect = WorldRect::zero();
let ctx = TilePreUpdateContext {
let mut ctx = TilePreUpdateContext {
pic_to_world_mapper,
fract_offset: self.fract_offset,
device_fract_offset: self.device_fract_offset,
@ -2845,6 +2895,9 @@ impl TileCacheInstance {
world_culling_rect = world_culling_rect.union(&tile.world_tile_rect);
}
}
// The background color can only be applied to the first sub-slice.
ctx.background_color = None;
}
// If compositor mode is changed, need to drop all incompatible tiles.
@ -3583,7 +3636,8 @@ impl TileCacheInstance {
let mut vis_flags = PrimitiveVisibilityFlags::empty();
// TODO(gw): Select the right sub_slice!
let sub_slice = &mut self.sub_slices[0];
let sub_slice_index = 0;
let sub_slice = &mut self.sub_slices[sub_slice_index];
if let Some(backdrop_candidate) = backdrop_candidate {
let is_suitable_backdrop = match backdrop_candidate.kind {
@ -3670,6 +3724,7 @@ impl TileCacheInstance {
prim_instance.vis.state = VisibilityState::Coarse {
filter: BatchFilter {
rect_in_pic_space: pic_clip_rect,
sub_slice_index: SubSliceIndex::new(sub_slice_index),
},
vis_flags,
};
@ -4925,6 +4980,7 @@ impl PicturePrimitive {
// surface allocation).
tile_cache.dirty_region.add_dirty_region(
tile.local_dirty_rect,
SubSliceIndex::new(sub_slice_index),
frame_context.spatial_tree,
);
@ -5012,6 +5068,7 @@ impl PicturePrimitive {
let batch_filter = BatchFilter {
rect_in_pic_space: tile.local_dirty_rect,
sub_slice_index: SubSliceIndex::new(sub_slice_index),
};
let render_task_id = frame_state.rg_builder.add().init(

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

@ -721,7 +721,10 @@ impl Document {
let tile_cache = match tile_caches.remove(&slice_id) {
Some(mut existing_tile_cache) => {
// Found an existing cache - update the cache params and reuse it
existing_tile_cache.prepare_for_new_scene(params);
existing_tile_cache.prepare_for_new_scene(
params,
resource_cache,
);
existing_tile_cache
}
None => {