Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async scene building. #2362

Merged
merged 18 commits into from Feb 22, 2018
Merged
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Move the scene builder to its own file.

  • Loading branch information
nical committed Feb 21, 2018
commit be67702bf02f01bb1d52933a727bc6a3aa78ff9c
@@ -22,9 +22,9 @@ use prim_store::ScrollNodeAndClipChain;
use profiler::{GpuCacheProfileCounters, TextureCacheProfileCounters};
use resource_cache::{FontInstanceMap,ResourceCache, TiledImageMap};
use scene::{Scene, StackingContextHelpers, ScenePipeline, SceneProperties};
use scene_builder::{SceneRequest, BuiltScene};
use tiling::{CompositeOps, Frame};
use renderer::PipelineInfo;
use render_backend::{SceneRequest, BuiltScene};

use std::sync::Arc;

This comment has been minimized.

@mrobinson

mrobinson Feb 20, 2018

Member

This should probably go with the rest of the use statements.


@@ -1086,6 +1086,8 @@ impl FrameContext {
.discard_frame_state_for_pipeline(pipeline_id);
}

// When changing this, please make the same modification to build_scene,
// which will soon replace this method completely.
pub fn create_frame_builder(
&mut self,
old_builder: FrameBuilder,
@@ -1170,88 +1172,6 @@ impl FrameContext {
frame_builder
}

// WIP: There is no reason for this to be in FrameContext other than making it easier
// to keep in sync with changes with the create_frame_builder method above.
// This will soon replace the method above and move somewhere else.
pub fn create_frame_builder_async(
config: &FrameBuilderConfig,
mut request: SceneRequest,
) -> BuiltScene {
let inner_rect = request.view.inner_rect;
let window_size = request.view.window_size;
let device_pixel_scale = request.view.accumulated_scale_factor();

let mut pipeline_epoch_map = FastHashMap::default();
let mut clip_scroll_tree = ClipScrollTree::new();

let frame_builder = {
// Creating the borrow here brings happiness to the borrow checker.
let scene = &mut request.scene;
// We checked that the root pipeline is available on the render backend.
let root_pipeline_id = scene.root_pipeline_id.unwrap();
let root_pipeline = scene.pipelines.get(&root_pipeline_id).unwrap();

let background_color = root_pipeline
.background_color
.and_then(|color| if color.a > 0.0 { Some(color) } else { None });

let root_epoch = scene.pipeline_epochs[&root_pipeline_id];
pipeline_epoch_map.insert(root_pipeline_id, root_epoch);

let mut roller = FlattenContext {
scene,
// WIP, we're not really recycling anything here, clean this up.
builder: FrameBuilder::empty().recycle(
inner_rect,
background_color,
window_size,
*config,
),
clip_scroll_tree: &mut clip_scroll_tree,
font_instances: request.font_instances,
tiled_image_map: request.tiled_image_map,
pipeline_epochs: Vec::new(),
replacements: Vec::new(),
output_pipelines: &request.output_pipelines,
id_to_index_mapper: ClipIdToIndexMapper::new(),
};

roller.builder.push_root(
root_pipeline_id,
&root_pipeline.viewport_size,
&root_pipeline.content_size,
roller.clip_scroll_tree,
&mut roller.id_to_index_mapper,
);

roller.builder.setup_viewport_offset(
inner_rect,
device_pixel_scale,
roller.clip_scroll_tree,
);

roller.flatten_root(
&mut root_pipeline.display_list.iter(),
root_pipeline_id,
&root_pipeline.viewport_size,
);

debug_assert!(roller.builder.picture_stack.is_empty());

pipeline_epoch_map.extend(roller.pipeline_epochs.drain(..));

roller.builder
};

BuiltScene {
scene: request.scene,
frame_builder,
clip_scroll_tree,
pipeline_epoch_map,
removed_pipelines: request.removed_pipelines,
}
}

pub fn update_epoch(&mut self, pipeline_id: PipelineId, epoch: Epoch) {
self.pipeline_epoch_map.insert(pipeline_id, epoch);
}
@@ -1303,3 +1223,83 @@ impl FrameContext {
(hit_tester, self.make_rendered_document(frame, removed_pipelines))
}
}


pub fn build_scene(
config: &FrameBuilderConfig,
mut request: SceneRequest,
) -> BuiltScene {
let inner_rect = request.view.inner_rect;
let window_size = request.view.window_size;
let device_pixel_scale = request.view.accumulated_scale_factor();

let mut pipeline_epoch_map = FastHashMap::default();
let mut clip_scroll_tree = ClipScrollTree::new();

let frame_builder = {
// Creating the borrow here brings happiness to the borrow checker.
let scene = &mut request.scene;
// We checked that the root pipeline is available on the render backend.
let root_pipeline_id = scene.root_pipeline_id.unwrap();
let root_pipeline = scene.pipelines.get(&root_pipeline_id).unwrap();

let background_color = root_pipeline
.background_color
.and_then(|color| if color.a > 0.0 { Some(color) } else { None });

let root_epoch = scene.pipeline_epochs[&root_pipeline_id];
pipeline_epoch_map.insert(root_pipeline_id, root_epoch);

let mut roller = FlattenContext {
scene,
// WIP, we're not really recycling anything here, clean this up.
builder: FrameBuilder::empty().recycle(
inner_rect,
background_color,
window_size,
*config,
),
clip_scroll_tree: &mut clip_scroll_tree,
font_instances: request.font_instances,
tiled_image_map: request.tiled_image_map,
pipeline_epochs: Vec::new(),
replacements: Vec::new(),
output_pipelines: &request.output_pipelines,
id_to_index_mapper: ClipIdToIndexMapper::new(),
};

roller.builder.push_root(
root_pipeline_id,
&root_pipeline.viewport_size,
&root_pipeline.content_size,
roller.clip_scroll_tree,
&mut roller.id_to_index_mapper,
);

roller.builder.setup_viewport_offset(
inner_rect,
device_pixel_scale,
roller.clip_scroll_tree,
);

roller.flatten_root(
&mut root_pipeline.display_list.iter(),
root_pipeline_id,
&root_pipeline.viewport_size,
);

debug_assert!(roller.builder.picture_stack.is_empty());

pipeline_epoch_map.extend(roller.pipeline_epochs.drain(..));

roller.builder
};

BuiltScene {
scene: request.scene,
frame_builder,
clip_scroll_tree,
pipeline_epoch_map,
removed_pipelines: request.removed_pipelines,
}
}
@@ -90,6 +90,7 @@ mod render_task;
mod renderer;
mod resource_cache;
mod scene;
mod scene_builder;
mod segment;
mod spring;
mod texture_allocator;
@@ -7,11 +7,10 @@ use api::{ApiMsg, BuiltDisplayList, ClearCache, DebugCommand};
use api::{BuiltDisplayListIter, SpecificDisplayItem};
use api::{DeviceIntPoint, DevicePixelScale, DeviceUintPoint, DeviceUintRect, DeviceUintSize};
use api::{DocumentId, DocumentLayer, DocumentMsg, HitTestResult, IdNamespace, PipelineId};
use api::{Epoch, TransactionMsg, ResourceUpdates};
use api::TransactionMsg;
use api::RenderNotifier;
use api::channel::{MsgReceiver, PayloadReceiver, PayloadReceiverHelperMethods};
use api::channel::{PayloadSender, PayloadSenderHelperMethods};
use api::channel::MsgSender;
#[cfg(feature = "capture")]
use api::CaptureBits;
#[cfg(feature = "replay")]
@@ -31,6 +30,7 @@ use resource_cache::PlainCacheOwn;
#[cfg(any(feature = "capture", feature = "replay"))]
use resource_cache::PlainResources;
use scene::{Scene, SceneProperties};
use scene_builder::*;
#[cfg(feature = "serialize")]
use serde::{Serialize, Deserialize};
#[cfg(feature = "debugger")]
@@ -39,11 +39,9 @@ use serde_json;
use std::path::PathBuf;
use std::sync::atomic::{ATOMIC_USIZE_INIT, AtomicUsize, Ordering};
use std::mem::replace;
use std::sync::mpsc::{Sender, Receiver, channel};
use std::sync::mpsc::{Sender, Receiver};
use std::u32;
use time::precise_time_ns;
use resource_cache::{FontInstanceMap, TiledImageMap};
use clip_scroll_tree::ClipScrollTree;

// WIP: I realize we don't really want to send the entire struct to the scene

This comment has been minimized.

@mrobinson

mrobinson Feb 15, 2018

Member

Might be good to leave your name here just to make it a bit easier to know who is speaking (ie "WIP(nical)" or something like that).

// building thread, this will be most likely a private struct again by the time
@@ -1182,120 +1180,3 @@ impl RenderBackend {
}
}

// Message from render backend to scene builder.
pub enum SceneBuilderRequest {
Transaction {
document_id: DocumentId,
scene: Option<SceneRequest>,
resource_updates: ResourceUpdates,
frame_ops: Vec<DocumentMsg>,
render: bool,
},
Stop
}

// Message from scene builder to render backend.
pub enum SceneBuilderMsg {
Transaction {
document_id: DocumentId,
built_scene: Option<BuiltScene>,
resource_updates: ResourceUpdates,
frame_ops: Vec<DocumentMsg>,
render: bool,
},
}

/// Contains the the render backend data needed to build a scene.
pub struct SceneRequest {
pub scene: Scene,
pub view: DocumentView,
pub font_instances: FontInstanceMap,
pub tiled_image_map: TiledImageMap,
pub output_pipelines: FastHashSet<PipelineId>,
pub removed_pipelines: Vec<PipelineId>,
}

pub struct BuiltScene {
pub scene: Scene,
pub frame_builder: FrameBuilder,
pub clip_scroll_tree: ClipScrollTree,
pub pipeline_epoch_map: FastHashMap<PipelineId, Epoch>,
pub removed_pipelines: Vec<PipelineId>,
}

pub struct SceneBuilder {
rx: Receiver<SceneBuilderRequest>,
tx: Sender<SceneBuilderMsg>,
api_tx: MsgSender<ApiMsg>,
config: FrameBuilderConfig,
}

impl SceneBuilder {
pub fn new(
config: FrameBuilderConfig,
api_tx: MsgSender<ApiMsg>
) -> (Self, Sender<SceneBuilderRequest>, Receiver<SceneBuilderMsg>) {
let (in_tx, in_rx) = channel();
let (out_tx, out_rx) = channel();
(
SceneBuilder {
rx: in_rx,
tx: out_tx,
api_tx,
config,
},
in_tx,
out_rx,
)
}

pub fn run(&mut self) {
loop {
match self.rx.recv() {
Ok(msg) => {
if !self.process_message(msg) {
return;
}
}
Err(_) => {
return;
}
}
}
}

pub fn process_message(&mut self, msg: SceneBuilderRequest) -> bool {
match msg {
SceneBuilderRequest::Transaction {
document_id,
scene,
resource_updates,
frame_ops,
render,
} => {
let built_scene = scene.map(|request|{
self.build_scene(request)
});

// TODO: pre-rasterization.

self.tx.send(SceneBuilderMsg::Transaction {
document_id,
built_scene,
resource_updates,
frame_ops,
render,
}).unwrap();

let _ = self.api_tx.send(ApiMsg::WakeUp);
}
SceneBuilderRequest::Stop => { return false; }
}

true
}

pub fn build_scene(&mut self, request: SceneRequest) -> BuiltScene {
FrameContext::create_frame_builder_async(&self.config, request)
}
}
@@ -50,7 +50,8 @@ use profiler::{GpuProfileTag, RendererProfileCounters, RendererProfileTimers};
use query::{GpuProfiler, GpuTimer};
use rayon::{ThreadPool, ThreadPoolBuilder};
use record::ApiRecordingReceiver;
use render_backend::{RenderBackend, SceneBuilder};
use render_backend::RenderBackend;
use scene_builder::SceneBuilder;
use render_task::{RenderTaskKind, RenderTaskTree};
use resource_cache::ResourceCache;
#[cfg(feature = "debugger")]
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.