зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
9fb3014aa3
Коммит
5ca48a83e1
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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
Двоичные данные
gfx/wr/wrench/reftests/filters/blend-clipped.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 2.4 KiB После Ширина: | Высота: | Размер: 2.1 KiB |
Загрузка…
Ссылка в новой задаче