Backed out changeset d8f3596e358e (bug 1757876) for causing wr3 failures in css-transforms/perspective-split-by-zero-w CLOSED TREE

This commit is contained in:
smolnar 2022-03-10 08:09:46 +02:00
Родитель 9fb3014aa3
Коммит 5ca48a83e1
11 изменённых файлов: 774 добавлений и 849 удалений

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -4,7 +4,7 @@
use api::{ColorF, DebugFlags, FontRenderMode, PremultipliedColorF};
use api::units::*;
use crate::batch::{BatchBuilder, AlphaBatchBuilder, AlphaBatchContainer, CommandBufferBuilder};
use crate::batch::{BatchBuilder, AlphaBatchBuilder, AlphaBatchContainer};
use crate::clip::{ClipStore, ClipChainStack};
use crate::spatial_tree::{SpatialTree, SpatialNodeIndex};
use crate::composite::{CompositorKind, CompositeState, CompositeStatePreallocator};
@ -15,17 +15,17 @@ use crate::gpu_types::TransformData;
use crate::internal_types::{FastHashMap, PlaneSplitter, FrameId, FrameStamp};
use crate::picture::{DirtyRegion, SliceId, TileCacheInstance};
use crate::picture::{SurfaceInfo, SurfaceIndex, SurfaceRenderTasks, SubSliceIndex};
use crate::picture::{SubpixelMode, RasterConfig, PictureCompositeMode};
use crate::picture::{BackdropKind, SubpixelMode, RasterConfig, PictureCompositeMode};
use crate::prepare::prepare_primitives;
use crate::prim_store::{PictureIndex, PrimitiveDebugId};
use crate::prim_store::{DeferredResolve, PrimitiveInstance, PrimitiveInstanceIndex};
use crate::prim_store::{DeferredResolve, PrimitiveInstance};
use crate::profiler::{self, TransactionProfile};
use crate::render_backend::{DataStores, ScratchBuffer};
use crate::render_target::{RenderTarget, PictureCacheTarget, TextureCacheRenderTarget};
use crate::render_target::{RenderTargetContext, RenderTargetKind, AlphaRenderTarget, ColorRenderTarget};
use crate::render_task_graph::{RenderTaskId, RenderTaskGraph, Pass, SubPassSurface};
use crate::render_task_graph::{RenderPass, RenderTaskGraphBuilder};
use crate::render_task::{RenderTaskKind, StaticRenderTaskSurface};
use crate::render_task::{RenderTaskLocation, RenderTaskKind, StaticRenderTaskSurface};
use crate::resource_cache::{ResourceCache};
use crate::scene::{BuiltScene, SceneProperties};
use crate::space::SpaceMapper;
@ -127,7 +127,6 @@ pub struct FrameScratchBuffer {
dirty_region_stack: Vec<DirtyRegion>,
surface_stack: Vec<(PictureIndex, SurfaceIndex)>,
clip_chain_stack: ClipChainStack,
cmd_buffer_stack: Vec<CommandBufferBuilder>,
}
impl Default for FrameScratchBuffer {
@ -136,7 +135,6 @@ impl Default for FrameScratchBuffer {
dirty_region_stack: Vec::new(),
surface_stack: Vec::new(),
clip_chain_stack: ClipChainStack::new(),
cmd_buffer_stack: Vec::new(),
}
}
}
@ -146,7 +144,6 @@ impl FrameScratchBuffer {
self.dirty_region_stack.clear();
self.surface_stack.clear();
self.clip_chain_stack.clear();
self.cmd_buffer_stack.clear();
}
}
@ -183,7 +180,6 @@ pub struct FrameBuildingState<'a> {
pub composite_state: &'a mut CompositeState,
pub num_visible_primitives: u32,
pub plane_splitters: &'a mut [PlaneSplitter],
pub cmd_buffer_stack: Vec<CommandBufferBuilder>,
}
impl<'a> FrameBuildingState<'a> {
@ -213,6 +209,7 @@ impl<'a> FrameBuildingState<'a> {
let surface = &mut self.surfaces[surface_index.0];
assert!(surface.render_tasks.is_none());
surface.render_tasks = Some(SurfaceRenderTasks::Tiled(tasks));
// TODO(gw): Include the dirty rect here, to reduce child surface sizes
surface.clipping_rect = clipping_rect;
}
@ -271,41 +268,6 @@ impl<'a> FrameBuildingState<'a> {
self.rg_builder,
);
}
pub fn push_surface(
&mut self,
cmd_buffer_builder: CommandBufferBuilder,
) {
self.cmd_buffer_stack.push(cmd_buffer_builder);
}
pub fn push_prim(
&mut self,
prim_instance_index: PrimitiveInstanceIndex,
spatial_node_index: SpatialNodeIndex,
pic_coverage_rect: PictureRect,
tile_rect: crate::picture::TileRect,
sub_slice_index: SubSliceIndex,
gpu_address: Option<crate::gpu_cache::GpuCacheAddress>,
) -> bool {
self.cmd_buffer_stack
.last_mut()
.unwrap()
.push_prim(
prim_instance_index,
spatial_node_index,
pic_coverage_rect,
tile_rect,
sub_slice_index,
gpu_address,
)
}
pub fn pop_surface(
&mut self,
) -> CommandBufferBuilder {
self.cmd_buffer_stack.pop().unwrap()
}
}
/// Immutable context of a picture when processing children.
@ -504,7 +466,6 @@ impl FrameBuilder {
composite_state,
num_visible_primitives: 0,
plane_splitters: &mut scene.plane_splitters,
cmd_buffer_stack: scratch.frame.cmd_buffer_stack.take(),
};
// Push a default dirty region which culls primitives
@ -515,6 +476,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);
@ -554,8 +516,6 @@ impl FrameBuilder {
pic.restore_context(
prim_list,
pic_context,
&scene.prim_instances,
&frame_context,
&mut frame_state,
);
}
@ -566,7 +526,6 @@ impl FrameBuilder {
profile.set(profiler::VISIBLE_PRIMITIVES, frame_state.num_visible_primitives);
scratch.frame.dirty_region_stack = frame_state.dirty_region_stack.take();
scratch.frame.cmd_buffer_stack = frame_state.cmd_buffer_stack.take();
{
profile_marker!("BlockOnResources");
@ -699,10 +658,12 @@ impl FrameBuilder {
&mut ctx,
gpu_cache,
&render_tasks,
&mut deferred_resolves,
&scene.clip_store,
&mut transform_palette,
&mut prim_headers,
&mut z_generator,
&mut composite_state,
scene.config.gpu_supports_fast_clears,
&scene.prim_instances,
);
@ -826,10 +787,12 @@ pub fn build_render_pass(
ctx: &mut RenderTargetContext,
gpu_cache: &mut GpuCache,
render_tasks: &RenderTaskGraph,
deferred_resolves: &mut Vec<DeferredResolve>,
clip_store: &ClipStore,
transforms: &mut TransformPalette,
prim_headers: &mut PrimitiveHeaders,
z_generator: &mut ZBufferIdGenerator,
composite_state: &mut CompositeState,
gpu_supports_fast_clears: bool,
prim_instances: &[PrimitiveInstance],
) -> RenderPass {
@ -839,6 +802,11 @@ pub fn build_render_pass(
// build_render_pass code as closely as possible, to make the review
// simpler and reduce chance of regressions. However, future work should
// include refactoring this to more closely match the built frame graph.
// Collect a list of picture cache tasks, keyed by picture index.
// This allows us to only walk that picture root once, adding the
// primitives to all relevant batches at the same time.
let mut picture_cache_tasks = FastHashMap::default();
let mut pass = RenderPass::new(src_pass);
for sub_pass in &src_pass.sub_passes {
@ -889,74 +857,26 @@ pub fn build_render_pass(
}
}
}
SubPassSurface::Persistent { surface: StaticRenderTaskSurface::PictureCache { ref surface, .. }, .. } => {
SubPassSurface::Persistent { surface: StaticRenderTaskSurface::PictureCache { .. }, .. } => {
assert_eq!(sub_pass.task_ids.len(), 1);
let task_id = sub_pass.task_ids[0];
let task = &render_tasks[task_id];
let target_rect = task.get_target_rect();
match task.kind {
RenderTaskKind::Picture(ref pic_task) => {
let cmd_buffer = pic_task.cmd_buffer.as_ref().expect("bug: no cmd buffer set for picture!");
let scissor_rect = pic_task.scissor_rect.expect("bug: must be set for cache tasks");
let valid_rect = pic_task.valid_rect.expect("bug: must be set for cache tasks");
let batcher = AlphaBatchBuilder::new(
screen_size,
ctx.break_advanced_blend_batches,
ctx.batch_lookback_count,
task_id,
task_id.into(),
);
let mut batch_builder = BatchBuilder::new(batcher);
cmd_buffer.iter_prims(&mut |prim_instance_index, spatial_node_index, gpu_address| {
let prim_instance = &prim_instances[prim_instance_index.0 as usize];
batch_builder.add_prim_to_batch(
prim_instance,
gpu_address,
spatial_node_index,
ctx,
gpu_cache,
render_tasks,
prim_headers,
transforms,
pic_task.raster_spatial_node_index,
pic_task.surface_spatial_node_index,
z_generator,
);
});
let batcher = batch_builder.finalize();
let mut batch_containers = Vec::new();
let mut alpha_batch_container = AlphaBatchContainer::new(Some(scissor_rect));
batcher.build(
&mut batch_containers,
&mut alpha_batch_container,
target_rect,
None,
);
debug_assert!(batch_containers.is_empty());
let target = PictureCacheTarget {
surface: surface.clone(),
clear_color: pic_task.clear_color,
alpha_batch_container,
dirty_rect: scissor_rect,
valid_rect,
};
pass.picture_cache.push(target);
// For picture cache tiles, just store them in the map
// of picture cache tasks, to be handled below.
let pic_index = match task.kind {
RenderTaskKind::Picture(ref info) => {
info.pic_index
}
_ => {
unreachable!();
}
};
picture_cache_tasks
.entry(pic_index)
.or_insert_with(Vec::new)
.push(task_id);
}
SubPassSurface::Persistent { surface: StaticRenderTaskSurface::TextureCache { target_kind, texture, .. } } => {
let texture = pass.texture_cache
@ -974,22 +894,157 @@ pub fn build_render_pass(
}
}
// For each picture in this pass that has picture cache tiles, create
// a batcher per task, and then build batches for each of the tasks
// at the same time.
for (pic_index, task_ids) in picture_cache_tasks {
profile_scope!("picture_cache_task");
let pic = &ctx.prim_store.pictures[pic_index.0];
// Extract raster/surface spatial nodes for this surface.
let (root_spatial_node_index, surface_spatial_node_index, tile_cache) = match pic.raster_config {
Some(RasterConfig { surface_index, composite_mode: PictureCompositeMode::TileCache { slice_id }, .. }) => {
let surface = &ctx.surfaces[surface_index.0];
(
surface.raster_spatial_node_index,
surface.surface_spatial_node_index,
&ctx.tile_caches[&slice_id],
)
}
_ => {
unreachable!();
}
};
// Create an alpha batcher for each of the tasks of this picture.
let mut batchers = Vec::new();
for task_id in &task_ids {
let task_id = *task_id;
let batch_filter = match render_tasks[task_id].kind {
RenderTaskKind::Picture(ref info) => info.batch_filter,
_ => unreachable!(),
};
batchers.push(AlphaBatchBuilder::new(
screen_size,
ctx.break_advanced_blend_batches,
ctx.batch_lookback_count,
task_id,
task_id.into(),
batch_filter,
0,
));
}
// Run the batch creation code for this picture, adding items to
// all relevant per-task batchers.
let mut batch_builder = BatchBuilder::new(batchers);
{
profile_scope!("add_pic_to_batch");
batch_builder.add_pic_to_batch(
pic,
ctx,
gpu_cache,
render_tasks,
deferred_resolves,
prim_headers,
transforms,
root_spatial_node_index,
surface_spatial_node_index,
z_generator,
composite_state,
prim_instances,
);
}
// Create picture cache targets, one per render task, and assign
// the correct batcher to them.
let batchers = batch_builder.finalize();
for (task_id, batcher) in task_ids.into_iter().zip(batchers.into_iter()) {
profile_scope!("task");
let task = &render_tasks[task_id];
let target_rect = task.get_target_rect();
match task.location {
RenderTaskLocation::Static { surface: StaticRenderTaskSurface::PictureCache { ref surface, .. }, .. } => {
// TODO(gw): The interface here is a bit untidy since it's
// designed to support batch merging, which isn't
// relevant for picture cache targets. We
// can restructure / tidy this up a bit.
let (scissor_rect, valid_rect, clear_color) = match render_tasks[task_id].kind {
RenderTaskKind::Picture(ref info) => {
let mut clear_color = ColorF::TRANSPARENT;
// TODO(gw): The way we check the batch filter for is_primary is a bit hacky, tidy up somehow?
if let Some(batch_filter) = info.batch_filter {
if batch_filter.sub_slice_index.is_primary() {
if let Some(background_color) = tile_cache.background_color {
clear_color = background_color;
}
// If this picture cache has a valid color backdrop, we will use
// that as the clear color, skipping the draw of the backdrop
// primitive (and anything prior to it) during batching.
if let Some(BackdropKind::Color { color }) = tile_cache.backdrop.kind {
clear_color = color;
}
}
}
(
info.scissor_rect.expect("bug: must be set for cache tasks"),
info.valid_rect.expect("bug: must be set for cache tasks"),
clear_color,
)
}
_ => unreachable!(),
};
let mut batch_containers = Vec::new();
let mut alpha_batch_container = AlphaBatchContainer::new(Some(scissor_rect));
batcher.build(
&mut batch_containers,
&mut alpha_batch_container,
target_rect,
None,
);
debug_assert!(batch_containers.is_empty());
let target = PictureCacheTarget {
surface: surface.clone(),
clear_color: Some(clear_color),
alpha_batch_container,
dirty_rect: scissor_rect,
valid_rect,
};
pass.picture_cache.push(target);
}
_ => {
unreachable!()
}
}
}
}
pass.color.build(
ctx,
gpu_cache,
render_tasks,
deferred_resolves,
prim_headers,
transforms,
z_generator,
composite_state,
prim_instances,
);
pass.alpha.build(
ctx,
gpu_cache,
render_tasks,
deferred_resolves,
prim_headers,
transforms,
z_generator,
composite_state,
prim_instances,
);

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

@ -13,8 +13,6 @@ use crate::renderer::{FullFrameStats, PipelineInfo};
use crate::gpu_cache::GpuCacheUpdateList;
use crate::frame_builder::Frame;
use crate::profiler::TransactionProfile;
use crate::spatial_tree::SpatialNodeIndex;
use crate::prim_store::PrimitiveInstanceIndex;
use fxhash::FxHasher;
use plane_split::BspSplitter;
use smallvec::SmallVec;
@ -171,17 +169,14 @@ impl FrameStamp {
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "capture", derive(Serialize))]
pub struct PlaneSplitAnchor {
pub spatial_node_index: SpatialNodeIndex,
pub instance_index: PrimitiveInstanceIndex,
pub cluster_index: usize,
pub instance_index: usize,
}
impl PlaneSplitAnchor {
pub fn new(
spatial_node_index: SpatialNodeIndex,
instance_index: PrimitiveInstanceIndex,
) -> Self {
pub fn new(cluster_index: usize, instance_index: usize) -> Self {
PlaneSplitAnchor {
spatial_node_index,
cluster_index,
instance_index,
}
}
@ -190,8 +185,8 @@ impl PlaneSplitAnchor {
impl Default for PlaneSplitAnchor {
fn default() -> Self {
PlaneSplitAnchor {
spatial_node_index: SpatialNodeIndex::INVALID,
instance_index: PrimitiveInstanceIndex(!0),
cluster_index: 0,
instance_index: 0,
}
}
}

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

@ -99,7 +99,7 @@ use api::{PropertyBinding, PropertyBindingId, FilterPrimitive, RasterSpace};
use api::{DebugFlags, ImageKey, ColorF, ColorU, PrimitiveFlags};
use api::{ImageRendering, ColorDepth, YuvRangedColorSpace, YuvFormat, AlphaType};
use api::units::*;
use crate::batch::CommandBufferBuilder;
use crate::batch::BatchFilter;
use crate::box_shadow::BLUR_SAMPLE_SCALE;
use crate::clip::{ClipStore, ClipChainInstance, ClipChainId, ClipInstance};
use crate::spatial_tree::{SpatialTree, CoordinateSpaceMapping, SpatialNodeIndex, VisibleFace};
@ -555,17 +555,6 @@ impl PrimitiveDependencyInfo {
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct TileId(pub usize);
/// Uniquely identifies a tile within a picture cache slice
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Debug, Copy, Clone, PartialEq, Hash, Eq)]
pub struct TileKey {
// Tile index (x,y)
pub tile_offset: TileOffset,
// Sub-slice (z)
pub sub_slice_index: SubSliceIndex,
}
/// A descriptor for the kind of texture that a picture cache tile will
/// be drawn into.
#[derive(Debug)]
@ -1534,6 +1523,9 @@ impl TileDescriptor {
/// Represents the dirty region of a tile cache picture.
#[derive(Clone)]
pub struct DirtyRegion {
/// The individual filters that make up this region.
pub filters: Vec<BatchFilter>,
/// The overall dirty rect, a combination of dirty_rects
pub combined: WorldRect,
@ -1547,6 +1539,7 @@ impl DirtyRegion {
spatial_node_index: SpatialNodeIndex,
) -> Self {
DirtyRegion {
filters: Vec::with_capacity(16),
combined: WorldRect::zero(),
spatial_node_index,
}
@ -1557,6 +1550,7 @@ impl DirtyRegion {
&mut self,
spatial_node_index: SpatialNodeIndex,
) {
self.filters.clear();
self.combined = WorldRect::zero();
self.spatial_node_index = spatial_node_index;
}
@ -1566,6 +1560,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(
@ -1581,6 +1576,11 @@ impl DirtyRegion {
// Include this in the overall dirty rect
self.combined = self.combined.union(&world_rect);
self.filters.push(BatchFilter {
rect_in_pic_space,
sub_slice_index,
});
}
}
@ -1699,7 +1699,7 @@ pub struct TileCacheParams {
/// a picture cache instance.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct SubSliceIndex(u8);
impl SubSliceIndex {
@ -3402,10 +3402,12 @@ impl TileCacheInstance {
}
}
prim_instance.vis.state = VisibilityState::Visible {
prim_instance.vis.state = VisibilityState::Coarse {
filter: BatchFilter {
rect_in_pic_space: pic_coverage_rect,
sub_slice_index: SubSliceIndex::new(sub_slice_index),
},
vis_flags,
tile_rect: TileRect::new(p0, p1),
sub_slice_index: SubSliceIndex::new(sub_slice_index),
};
}
@ -3665,6 +3667,7 @@ pub enum SurfaceRenderTasks {
/// information about the contents of the surface, which
/// will allow surfaces to be cached / retained between
/// frames and display lists.
#[derive(Debug)]
pub struct SurfaceInfo {
/// A local rect defining the size of this surface, in the
/// coordinate system of the surface itself.
@ -4086,6 +4089,7 @@ pub enum Picture3DContext<C> {
#[cfg_attr(feature = "capture", derive(Serialize))]
pub struct OrderedPictureChild {
pub anchor: PlaneSplitAnchor,
pub spatial_node_index: SpatialNodeIndex,
pub gpu_address: GpuCacheAddress,
}
@ -4491,11 +4495,10 @@ impl PicturePrimitive {
match self.raster_config {
Some(RasterConfig { surface_index, composite_mode: PictureCompositeMode::TileCache { slice_id }, .. }) => {
let mut cmd_buffer_builder = CommandBufferBuilder::new_tiled();
let tile_cache = tile_caches.get_mut(&slice_id).unwrap();
let mut debug_info = SliceDebugInfo::new();
let mut surface_tasks = Vec::with_capacity(tile_cache.tile_count());
let mut surface_local_dirty_rect = PictureRect::zero();
let mut surface_local_rect = PictureRect::zero();
let device_pixel_scale = frame_state
.surfaces[surface_index.0]
.device_pixel_scale;
@ -4510,6 +4513,8 @@ impl PicturePrimitive {
for (sub_slice_index, sub_slice) in tile_cache.sub_slices.iter_mut().enumerate() {
for tile in sub_slice.tiles.values_mut() {
surface_local_rect = surface_local_rect.union(&tile.current_descriptor.local_valid_rect);
if tile.is_visible {
// Get the world space rect that this tile will actually occupy on screen
let world_draw_rect = world_clip_rect.intersection(&tile.world_valid_rect);
@ -4646,8 +4651,6 @@ impl PicturePrimitive {
.intersection(&tile.current_descriptor.local_valid_rect)
.unwrap_or_else(PictureRect::zero);
surface_local_dirty_rect = surface_local_dirty_rect.union(&tile.local_dirty_rect);
// Update the world/device dirty rect
let world_dirty_rect = map_pic_to_world.map(&tile.local_dirty_rect).expect("bug");
@ -4670,19 +4673,12 @@ impl PicturePrimitive {
// surface allocation).
tile_cache.dirty_region.add_dirty_region(
tile.local_dirty_rect,
SubSliceIndex::new(sub_slice_index),
frame_context.spatial_tree,
);
// Ensure that this texture is allocated.
if let TileSurface::Texture { ref mut descriptor } = tile.surface.as_mut().unwrap() {
cmd_buffer_builder.add_tile(
TileKey {
tile_offset: tile.tile_offset,
sub_slice_index: SubSliceIndex::new(sub_slice_index),
},
tile.local_dirty_rect,
);
match descriptor {
SurfaceTextureDescriptor::TextureCache { ref mut handle } => {
@ -4776,26 +4772,11 @@ impl PicturePrimitive {
let task_size = tile_cache.current_tile_size;
let tile_key = TileKey {
let batch_filter = BatchFilter {
rect_in_pic_space: tile.local_dirty_rect,
sub_slice_index: SubSliceIndex::new(sub_slice_index),
tile_offset: tile.tile_offset,
};
let mut clear_color = ColorF::TRANSPARENT;
if SubSliceIndex::new(sub_slice_index).is_primary() {
if let Some(background_color) = tile_cache.background_color {
clear_color = background_color;
}
// If this picture cache has a valid color backdrop, we will use
// that as the clear color, skipping the draw of the backdrop
// primitive (and anything prior to it) during batching.
if let Some(BackdropKind::Color { color }) = tile_cache.backdrop.kind {
clear_color = color;
}
}
let render_task_id = frame_state.rg_builder.add().init(
RenderTask::new(
RenderTaskLocation::Static {
@ -4807,14 +4788,13 @@ impl PicturePrimitive {
RenderTaskKind::new_picture(
task_size,
tile_cache.current_tile_size.to_f32(),
pic_index,
content_origin,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
Some(tile_key),
Some(batch_filter),
Some(scissor_rect),
Some(valid_rect),
Some(clear_color),
)
),
);
@ -4909,11 +4889,7 @@ impl PicturePrimitive {
frame_state.init_surface_tiled(
surface_index,
surface_tasks,
surface_local_dirty_rect,
);
frame_state.push_surface(
cmd_buffer_builder,
surface_local_rect,
);
}
Some(ref mut raster_config) => {
@ -4962,9 +4938,6 @@ impl PicturePrimitive {
};
let device_pixel_scale = frame_state.surfaces[raster_config.surface_index.0].device_pixel_scale;
let cmd_buffer_builder = CommandBufferBuilder::new_simple(
surface_rects.clipped_local,
);
let primary_render_task_id;
match raster_config.composite_mode {
@ -5000,14 +4973,13 @@ impl PicturePrimitive {
RenderTaskKind::new_picture(
surface_rects.task_size,
surface_rects.unclipped.size(),
pic_index,
device_rect.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
None,
)
).with_uv_rect_kind(surface_rects.uv_rect_kind)
);
@ -5042,14 +5014,13 @@ impl PicturePrimitive {
RenderTaskKind::new_picture(
surface_rects.task_size,
surface_rects.unclipped.size(),
pic_index,
device_rect.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
None,
),
).with_uv_rect_kind(surface_rects.uv_rect_kind)
);
@ -5185,14 +5156,13 @@ impl PicturePrimitive {
RenderTaskKind::new_picture(
task_size,
surface_rects.unclipped.size(),
pic_index,
surface_rects.clipped.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
None,
)
).with_uv_rect_kind(surface_rects.uv_rect_kind)
);
@ -5207,20 +5177,20 @@ impl PicturePrimitive {
);
}
PictureCompositeMode::Filter(..) => {
let render_task_id = frame_state.rg_builder.add().init(
RenderTask::new_dynamic(
surface_rects.task_size,
RenderTaskKind::new_picture(
surface_rects.task_size,
surface_rects.unclipped.size(),
pic_index,
surface_rects.clipped.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
None,
)
).with_uv_rect_kind(surface_rects.uv_rect_kind)
);
@ -5235,20 +5205,20 @@ impl PicturePrimitive {
);
}
PictureCompositeMode::ComponentTransferFilter(..) => {
let render_task_id = frame_state.rg_builder.add().init(
RenderTask::new_dynamic(
surface_rects.task_size,
RenderTaskKind::new_picture(
surface_rects.task_size,
surface_rects.unclipped.size(),
pic_index,
surface_rects.clipped.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
None,
)
).with_uv_rect_kind(surface_rects.uv_rect_kind)
);
@ -5264,20 +5234,20 @@ impl PicturePrimitive {
}
PictureCompositeMode::MixBlend(..) |
PictureCompositeMode::Blit(_) => {
let render_task_id = frame_state.rg_builder.add().init(
RenderTask::new_dynamic(
surface_rects.task_size,
RenderTaskKind::new_picture(
surface_rects.task_size,
surface_rects.unclipped.size(),
pic_index,
surface_rects.clipped.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
None,
)
).with_uv_rect_kind(surface_rects.uv_rect_kind)
);
@ -5298,14 +5268,13 @@ impl PicturePrimitive {
RenderTaskKind::new_picture(
surface_rects.task_size,
surface_rects.unclipped.size(),
pic_index,
surface_rects.clipped.min,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
None,
None,
None,
None,
)
).with_uv_rect_kind(surface_rects.uv_rect_kind)
);
@ -5332,8 +5301,6 @@ impl PicturePrimitive {
}
}
frame_state.push_surface(cmd_buffer_builder);
self.primary_render_task_id = primary_render_task_id;
}
None => {}
@ -5428,8 +5395,6 @@ impl PicturePrimitive {
&mut self,
prim_list: PrimitiveList,
context: PictureContext,
prim_instances: &[PrimitiveInstance],
frame_context: &FrameBuildingContext,
frame_state: &mut FrameBuildingState,
) {
// Pop any dirty regions this picture set
@ -5437,76 +5402,6 @@ impl PicturePrimitive {
frame_state.pop_dirty_region();
}
match self.raster_config {
Some(RasterConfig { surface_index, .. }) => {
let mut cmd_buffer_builder = frame_state.pop_surface();
let surface = &mut frame_state.surfaces[surface_index.0];
fn set_task_cmd_buffer(
render_task: &mut RenderTask,
cmd_buffer_builder: &mut CommandBufferBuilder,
) {
match render_task.kind {
RenderTaskKind::Picture(ref mut pic_task) => {
pic_task.cmd_buffer = Some(cmd_buffer_builder.take_cmd_buffer(pic_task.tile_key));
}
_ => {
unreachable!();
}
}
}
match surface.render_tasks {
Some(SurfaceRenderTasks::Tiled(ref tasks)) => {
for task_id in tasks {
let task = frame_state.rg_builder.get_task_mut(*task_id);
set_task_cmd_buffer(task, &mut cmd_buffer_builder);
}
}
Some(SurfaceRenderTasks::Simple(task_id)) => {
let task = frame_state.rg_builder.get_task_mut(task_id);
set_task_cmd_buffer(task, &mut cmd_buffer_builder);
}
Some(SurfaceRenderTasks::Chained { port_task_id, .. }) => {
let task = frame_state.rg_builder.get_task_mut(port_task_id);
set_task_cmd_buffer(task, &mut cmd_buffer_builder);
}
_ => {
panic!("bug: no render tasks initialized for surface");
}
}
}
None => {}
}
if let Picture3DContext::In { root_data: Some(ref mut list), plane_splitter_index, .. } = self.context_3d {
let splitter = &mut frame_state.plane_splitters[plane_splitter_index.0];
// Resolve split planes via BSP
PicturePrimitive::resolve_split_planes(
splitter,
list,
&mut frame_state.gpu_cache,
&frame_context.spatial_tree,
);
// Add the child prims to the relevant command buffers
for child in list {
let child_prim_instance = &prim_instances[child.anchor.instance_index.0 as usize];
if let VisibilityState::Visible { tile_rect, sub_slice_index, .. } = child_prim_instance.vis.state {
frame_state.push_prim(
child.anchor.instance_index,
child.anchor.spatial_node_index,
child_prim_instance.vis.clip_chain.pic_coverage_rect,
tile_rect,
sub_slice_index,
Some(child.gpu_address),
);
}
}
}
self.prim_list = prim_list;
}
@ -5580,12 +5475,16 @@ impl PicturePrimitive {
true
}
fn resolve_split_planes(
pub fn resolve_split_planes(
&mut self,
splitter: &mut PlaneSplitter,
ordered: &mut Vec<OrderedPictureChild>,
gpu_cache: &mut GpuCache,
spatial_tree: &SpatialTree,
) {
let ordered = match self.context_3d {
Picture3DContext::In { root_data: Some(ref mut list), .. } => list,
_ => panic!("Expected to find 3D context root"),
};
ordered.clear();
// Process the accumulated split planes and order them for rendering.
@ -5593,8 +5492,10 @@ impl PicturePrimitive {
let sorted = splitter.sort(vec3(0.0, 0.0, 1.0));
ordered.reserve(sorted.len());
for poly in sorted {
let cluster = &self.prim_list.clusters[poly.anchor.cluster_index];
let spatial_node_index = cluster.spatial_node_index;
let transform = match spatial_tree
.get_world_transform(poly.anchor.spatial_node_index)
.get_world_transform(spatial_node_index)
.inverse()
{
Some(transform) => transform.into_transform(),
@ -5628,6 +5529,7 @@ impl PicturePrimitive {
ordered.push(OrderedPictureChild {
anchor: poly.anchor,
spatial_node_index,
gpu_address,
});
}
@ -5952,6 +5854,16 @@ impl PicturePrimitive {
frame_state: &mut FrameBuildingState,
data_stores: &mut DataStores,
) -> bool {
if let Picture3DContext::In { root_data: Some(..), plane_splitter_index, .. } = self.context_3d {
let splitter = &mut frame_state.plane_splitters[plane_splitter_index.0];
self.resolve_split_planes(
splitter,
&mut frame_state.gpu_cache,
&frame_context.spatial_tree,
);
}
let raster_config = match self.raster_config {
Some(ref mut raster_config) => raster_config,
None => {

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

@ -53,7 +53,7 @@ pub fn prepare_primitives(
prim_instances: &mut Vec<PrimitiveInstance>,
) {
profile_scope!("prepare_primitives");
for cluster in &mut prim_list.clusters {
for (cluster_index, cluster) in prim_list.clusters.iter_mut().enumerate() {
if !cluster.flags.contains(ClusterFlags::IS_VISIBLE) {
continue;
}
@ -73,27 +73,37 @@ pub fn prepare_primitives(
VisibilityState::Culled => {
continue;
}
VisibilityState::Visible { tile_rect, sub_slice_index, .. } => {
if !frame_state.push_prim(
PrimitiveInstanceIndex(prim_instance_index as u32),
cluster.spatial_node_index,
prim_instance.vis.clip_chain.pic_coverage_rect,
tile_rect,
sub_slice_index,
None,
) {
VisibilityState::Coarse { ref filter, vis_flags } => {
// The original coarse state was calculated during the initial visibility pass.
// However, it's possible that the dirty rect has got smaller, if tiles were not
// dirty. Intersecting with the dirty rect here eliminates preparing any primitives
// outside the dirty rect, and reduces the size of any off-screen surface allocations
// for clip masks / render tasks that we make.
// Clear the current visibiilty mask, and build a more detailed one based on the dirty rect
// regions below.
let dirty_region = frame_state.current_dirty_region();
let is_in_dirty_region = dirty_region.filters
.iter()
.any(|region_filter| region_filter.matches(filter));
if is_in_dirty_region {
prim_instance.vis.state = VisibilityState::Detailed {
filter: *filter,
vis_flags,
}
} else {
prim_instance.clear_visibility();
continue;
}
}
VisibilityState::PassThrough => {
VisibilityState::Detailed { .. } => {
// Was already set to detailed (picture caching disabled or a root element)
}
VisibilityState::PassThrough => {}
}
let plane_split_anchor = PlaneSplitAnchor::new(
cluster.spatial_node_index,
PrimitiveInstanceIndex(prim_instance_index as u32),
);
let plane_split_anchor = PlaneSplitAnchor::new(cluster_index, prim_instance_index);
if prepare_prim_for_render(
store,
@ -176,8 +186,6 @@ fn prepare_prim_for_render(
.restore_context(
prim_list,
pic_context_for_children,
prim_instances,
frame_context,
frame_state,
);
}
@ -362,13 +370,14 @@ fn prepare_interned_prim_for_render(
let allow_subpixel = match prim_instance.vis.state {
VisibilityState::Culled |
VisibilityState::Unset |
VisibilityState::Coarse { .. } |
VisibilityState::PassThrough => {
panic!("bug: invalid visibility state");
}
VisibilityState::Visible { sub_slice_index, .. } => {
VisibilityState::Detailed { ref filter, .. } => {
// For now, we only allow subpixel AA on primary sub-slices. In future we
// may support other sub-slices if we find content that does this.
if sub_slice_index.is_primary() {
if filter.sub_slice_index.is_primary() {
match pic_context.subpixel_mode {
SubpixelMode::Allow => true,
SubpixelMode::Deny => false,

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

@ -1058,11 +1058,6 @@ pub enum PrimitiveInstanceKind {
},
}
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct PrimitiveInstanceIndex(pub u32);
#[derive(Debug)]
#[cfg_attr(feature = "capture", derive(Serialize))]
pub struct PrimitiveInstance {
@ -1466,7 +1461,7 @@ fn test_struct_sizes() {
// test expectations and move on.
// (b) You made a structure larger. This is not necessarily a problem, but should only
// be done with care, and after checking if talos performance regresses badly.
assert_eq!(mem::size_of::<PrimitiveInstance>(), 152, "PrimitiveInstance size changed");
assert_eq!(mem::size_of::<PrimitiveInstance>(), 160, "PrimitiveInstance size changed");
assert_eq!(mem::size_of::<PrimitiveInstanceKind>(), 24, "PrimitiveInstanceKind size changed");
assert_eq!(mem::size_of::<PrimitiveTemplate>(), 56, "PrimitiveTemplate size changed");
assert_eq!(mem::size_of::<PrimitiveTemplateKind>(), 28, "PrimitiveTemplateKind size changed");

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

@ -9,13 +9,14 @@ use crate::batch::{AlphaBatchBuilder, AlphaBatchContainer, BatchTextures};
use crate::batch::{ClipBatcher, BatchBuilder};
use crate::spatial_tree::SpatialTree;
use crate::clip::ClipStore;
use crate::composite::CompositeState;
use crate::frame_builder::{FrameGlobalResources};
use crate::gpu_cache::{GpuCache, GpuCacheAddress};
use crate::gpu_types::{BorderInstance, SvgFilterInstance, BlurDirection, BlurInstance, PrimitiveHeaders, ScalingInstance};
use crate::gpu_types::{TransformPalette, ZBufferIdGenerator};
use crate::internal_types::{FastHashMap, TextureSource, CacheTextureId};
use crate::picture::{SliceId, SurfaceInfo, ResolvedSurfaceTexture, TileCacheInstance};
use crate::prim_store::{PrimitiveInstance, PrimitiveStore, PrimitiveScratchBuffer};
use crate::prim_store::{PrimitiveInstance, PrimitiveStore, DeferredResolve, PrimitiveScratchBuffer};
use crate::prim_store::gradient::{
FastLinearGradientInstance, LinearGradientInstance, RadialGradientInstance,
ConicGradientInstance,
@ -93,9 +94,11 @@ pub trait RenderTarget {
_ctx: &mut RenderTargetContext,
_gpu_cache: &mut GpuCache,
_render_tasks: &RenderTaskGraph,
_deferred_resolves: &mut Vec<DeferredResolve>,
_prim_headers: &mut PrimitiveHeaders,
_transforms: &mut TransformPalette,
_z_generator: &mut ZBufferIdGenerator,
_composite_state: &mut CompositeState,
_prim_instances: &[PrimitiveInstance],
) {
}
@ -170,9 +173,11 @@ impl<T: RenderTarget> RenderTargetList<T> {
ctx: &mut RenderTargetContext,
gpu_cache: &mut GpuCache,
render_tasks: &RenderTaskGraph,
deferred_resolves: &mut Vec<DeferredResolve>,
prim_headers: &mut PrimitiveHeaders,
transforms: &mut TransformPalette,
z_generator: &mut ZBufferIdGenerator,
composite_state: &mut CompositeState,
prim_instances: &[PrimitiveInstance],
) {
if self.targets.is_empty() {
@ -184,9 +189,11 @@ impl<T: RenderTarget> RenderTargetList<T> {
ctx,
gpu_cache,
render_tasks,
deferred_resolves,
prim_headers,
transforms,
z_generator,
composite_state,
prim_instances,
);
}
@ -247,9 +254,11 @@ impl RenderTarget for ColorRenderTarget {
ctx: &mut RenderTargetContext,
gpu_cache: &mut GpuCache,
render_tasks: &RenderTaskGraph,
deferred_resolves: &mut Vec<DeferredResolve>,
prim_headers: &mut PrimitiveHeaders,
transforms: &mut TransformPalette,
z_generator: &mut ZBufferIdGenerator,
composite_state: &mut CompositeState,
prim_instances: &[PrimitiveInstance],
) {
profile_scope!("build");
@ -261,6 +270,19 @@ impl RenderTarget for ColorRenderTarget {
match task.kind {
RenderTaskKind::Picture(ref pic_task) => {
let pic = &ctx.prim_store.pictures[pic_task.pic_index.0];
let raster_spatial_node_index = match pic.raster_config {
Some(ref raster_config) => {
let surface = &ctx.surfaces[raster_config.surface_index.0];
surface.raster_spatial_node_index
}
None => {
// This must be the main framebuffer
ctx.root_spatial_node_index
}
};
let target_rect = task.get_target_rect();
let scissor_rect = if pic_task.can_merge {
@ -269,6 +291,18 @@ impl RenderTarget for ColorRenderTarget {
Some(target_rect)
};
// Typical workloads have a single or a few batch builders with a
// large number of batches (regular pictres) and a higher number
// of batch builders with only a single or two batches (for example
// rendering isolated primitives to compute their shadows).
// We can easily guess which category we are in for each picture
// by checking whether it has multiple clusters.
let prealloc_batch_count = if pic.prim_list.clusters.len() > 1 {
128
} else {
0
};
// TODO(gw): The type names of AlphaBatchBuilder and BatchBuilder
// are still confusing. Once more of the picture caching
// improvement code lands, the AlphaBatchBuilder and
@ -280,38 +314,39 @@ impl RenderTarget for ColorRenderTarget {
ctx.batch_lookback_count,
*task_id,
(*task_id).into(),
None,
prealloc_batch_count,
);
let mut batch_builder = BatchBuilder::new(alpha_batch_builder);
let mut batch_builder = BatchBuilder::new(
vec![alpha_batch_builder],
);
let cmd_buffer = pic_task.cmd_buffer.as_ref().expect("bug: no cmd buffer set for picture!");
batch_builder.add_pic_to_batch(
pic,
ctx,
gpu_cache,
render_tasks,
deferred_resolves,
prim_headers,
transforms,
raster_spatial_node_index,
pic_task.surface_spatial_node_index,
z_generator,
composite_state,
prim_instances,
);
cmd_buffer.iter_prims(&mut |prim_instance_index, spatial_node_index, gpu_address| {
let prim_instance = &prim_instances[prim_instance_index.0 as usize];
let alpha_batch_builders = batch_builder.finalize();
batch_builder.add_prim_to_batch(
prim_instance,
gpu_address,
spatial_node_index,
ctx,
gpu_cache,
render_tasks,
prim_headers,
transforms,
pic_task.raster_spatial_node_index,
pic_task.surface_spatial_node_index,
z_generator,
for batcher in alpha_batch_builders {
batcher.build(
&mut self.alpha_batch_containers,
&mut merged_batches,
target_rect,
scissor_rect,
);
});
let alpha_batch_builder = batch_builder.finalize();
alpha_batch_builder.build(
&mut self.alpha_batch_containers,
&mut merged_batches,
target_rect,
scissor_rect,
);
}
}
_ => {
unreachable!();

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

@ -6,16 +6,16 @@ use api::{CompositeOperator, FilterPrimitive, FilterPrimitiveInput, FilterPrimit
use api::{LineStyle, LineOrientation, ClipMode, MixBlendMode, ColorF, ColorSpace};
use api::MAX_RENDER_TASK_SIZE;
use api::units::*;
use crate::batch::CommandBuffer;
use crate::batch::BatchFilter;
use crate::clip::{ClipDataStore, ClipItemKind, ClipStore, ClipNodeRange};
use crate::spatial_tree::SpatialNodeIndex;
use crate::filterdata::SFilterData;
use crate::frame_builder::{FrameBuilderConfig};
use crate::frame_builder::FrameBuilderConfig;
use crate::gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
use crate::gpu_types::{BorderInstance, ImageSource, UvRectKind};
use crate::internal_types::{CacheTextureId, FastHashMap, TextureSource, Swizzle};
use crate::picture::{ResolvedSurfaceTexture, SurfaceInfo, TileKey};
use crate::prim_store::ClipData;
use crate::picture::{ResolvedSurfaceTexture, SurfaceInfo};
use crate::prim_store::{ClipData, PictureIndex};
use crate::prim_store::gradient::{
FastLinearGradientTask, RadialGradientTask,
ConicGradientTask, LinearGradientTask,
@ -166,16 +166,14 @@ pub struct ClipRegionTask {
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct PictureTask {
pub pic_index: PictureIndex,
pub can_merge: bool,
pub content_origin: DevicePoint,
pub surface_spatial_node_index: SpatialNodeIndex,
pub raster_spatial_node_index: SpatialNodeIndex,
pub device_pixel_scale: DevicePixelScale,
pub tile_key: Option<TileKey>,
pub clear_color: Option<ColorF>,
pub batch_filter: Option<BatchFilter>,
pub scissor_rect: Option<DeviceIntRect>,
pub valid_rect: Option<DeviceIntRect>,
pub cmd_buffer: Option<CommandBuffer>,
}
#[derive(Debug)]
@ -382,14 +380,13 @@ impl RenderTaskKind {
pub fn new_picture(
size: DeviceIntSize,
unclipped_size: DeviceSize,
pic_index: PictureIndex,
content_origin: DevicePoint,
surface_spatial_node_index: SpatialNodeIndex,
raster_spatial_node_index: SpatialNodeIndex,
device_pixel_scale: DevicePixelScale,
tile_key: Option<TileKey>,
batch_filter: Option<BatchFilter>,
scissor_rect: Option<DeviceIntRect>,
valid_rect: Option<DeviceIntRect>,
clear_color: Option<ColorF>,
) -> Self {
render_task_sanity_check(&size);
@ -397,16 +394,14 @@ impl RenderTaskKind {
size.height as f32 >= unclipped_size.height;
RenderTaskKind::Picture(PictureTask {
pic_index,
content_origin,
can_merge,
surface_spatial_node_index,
raster_spatial_node_index,
device_pixel_scale,
tile_key,
batch_filter,
scissor_rect,
valid_rect,
cmd_buffer: None,
clear_color,
})
}

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

@ -54,7 +54,7 @@ impl CoordinateSystem {
#[derive(Debug, Copy, Clone, Eq, Hash, MallocSizeOf, PartialEq)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct SpatialNodeIndex(pub u32);
pub struct SpatialNodeIndex(u32);
impl SpatialNodeIndex {
pub const INVALID: SpatialNodeIndex = SpatialNodeIndex(u32::MAX);

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

@ -10,6 +10,7 @@
use api::{DebugFlags};
use api::units::*;
use std::{usize};
use crate::batch::BatchFilter;
use crate::clip::{ClipStore, ClipChainStack};
use crate::composite::CompositeState;
use crate::spatial_tree::{SpatialTree, SpatialNodeIndex};
@ -17,7 +18,7 @@ use crate::clip::{ClipInstance, ClipChainInstance};
use crate::frame_builder::FrameBuilderConfig;
use crate::gpu_cache::GpuCache;
use crate::picture::{PictureCompositeMode, ClusterFlags, SurfaceInfo, TileCacheInstance};
use crate::picture::{SurfaceIndex, RasterConfig, TileRect, SubSliceIndex};
use crate::picture::{SurfaceIndex, RasterConfig};
use crate::prim_store::{ClipTaskIndex, PictureIndex, PrimitiveInstanceKind};
use crate::prim_store::{PrimitiveStore, PrimitiveInstance};
use crate::render_backend::{DataStores, ScratchBuffer};
@ -96,17 +97,26 @@ pub enum VisibilityState {
/// A picture that doesn't have a surface - primitives are composed into the
/// parent picture with a surface.
PassThrough,
/// A primitive that has been found to be visible
Visible {
/// During picture cache dependency update, was found to be intersecting with one
/// or more visible tiles. The rect in picture cache space is stored here to allow
/// the detailed calculations below.
Coarse {
/// Information about which tile batchers this prim should be added to
filter: BatchFilter,
/// A set of flags that define how this primitive should be handled
/// during batching of visible primitives.
vis_flags: PrimitiveVisibilityFlags,
},
/// Once coarse visibility is resolved, this will be set if the primitive
/// intersected any dirty rects, otherwise prim will be culled.
Detailed {
/// Information about which tile batchers this prim should be added to
filter: BatchFilter,
/// Tiles that this primitive intersects with
tile_rect: TileRect,
/// Sub-slice within the picture cache that this prim exists on
sub_slice_index: SubSliceIndex,
/// A set of flags that define how this primitive should be handled
/// during batching of visible primitives.
vis_flags: PrimitiveVisibilityFlags,
},
}

Двоичные данные
gfx/wr/wrench/reftests/filters/blend-clipped.png

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 2.4 KiB

После

Ширина:  |  Высота:  |  Размер: 2.1 KiB