In this side, I introduce Webrender 1.0 (it have been updated to 2.0 after 08/03/2016) that is based on Rust language and OpenGL to develop a proof of concept to bring the game engine technology into Web browser. It mentions how Scene Graph, Batching, Composite work in this modern web browser, Servo.
2. Introduction
● The rendering engine of Servo
○ Implementations of essentially all features of CSS that Servo supports.
○ Working on enabled by default.
○ Separately from Servo
● Initial commit: September 22, 2015.
● Two main developers: Glenn Watson (lead) and Patrick Walton.
● OpenGL-based renderer
● This is just version 1.0… Still in progress.
4. GPU API modes
Retained mode Immediate mode Tiled-based mode
In 2000s PC GPUs In 2010s mobile GPUsIn 1990s PC GPUs
5. [In existing APIs] path rendering can result in many state changes per
path…In this case, the API overhead can substantially limit the overall
performance. Our experience…indicates these approaches are often more
GPU-assisted rather than GPU-accelerated…
—Mark Kilgard and Jeff Bolz, NVIDIA
SIGGRAPH Asia 2012
6. Today web browsers respecify paths every time a web page with path content
is re-rendered assuming re-specifying paths is cheap…When path rendering is
fully GPU-accelerated, a retained model of rendering is more appropriate and
efficient. We believe web browsers should behave more like video games in
this respect to exploit the GPU.
—Mark Kilgard and Jeff Bolz, NVIDIA
SIGGRAPH Asia 2012
7. Retained vs. Immediate mode
● Framework example: WPF vs. Direct2D
● Immediate mode gives the control of GPU pipeline to developers.
○ If you are good at this, your application would gain more performance. Otherwise...
● Immediate mode doesn’t help the management of scene, state, and batch.
● Retained mode have display lists for managing drawcalls & states. Ex: OpenGL 2.0
8. --- Advanced Game Programming 3D Mathematics.
Graphics API
“Game engines do scene graph no matter
retained mode or immediate mode API”
“Scene graph == Software retained mode”
Batching
State management
Sorting
etc...
9. --- Advanced Game Programming 3D Mathematics.
Graphics API
How about Web browser?
CSS DOM
simple scene graph
Batching
State management
Sorting
etc...
10. GPU synchronization
● Mode transition
● Command buffer
“glFinish. It will not return, stopping the current CPU thread, until all
rendering commands that have been sent have completed.”
11. What is Webrender?
● A game engine (renderer) for Web browser
● Retained mode, multithreaded
● Focus on CSS
● Takes a post-layout CSS display list and draws it to the screen as quickly as
possible.
● Webrender supports OpenGL ES 2.1 and OpenGL 3.x.
○ Instance rendering / Loop in shaders
● Webrender could be used as a backend for any sort of 2D graphics that CSS can
describe
16. DisplayItem
● The minimum unit of renderable item
● It describes by a visible rect and clip region
● Types:
○ RectangleDisplayItem
○ TextDisplayItem
○ ImageDisplayItem
○ WebGLDisplayItem
○ BorderDisplayItem
○ BoxShadowDisplayItem
○ GradientDisplayItem
DisplayListBuilder
pub enum SpecificDisplayListItem {
DrawList(DrawListInfo),
StackingContext(StackingContextInfo),
Iframe(IframeInfo),
}
○ Store items to a list
○ Finalize
■ Generate a displaylist as Blob
convert_to_webrender
17. StackingContext
● Stacking context is the three-dimensional conceptualization of HTML elements
along an imaginary z-axis relative to the user who is assumed to be facing the
viewport or the webpage
pub struct StackingContext {
pub servo_id: ServoStackingContextId,
pub scroll_layer_id: Option<ScrollLayerId>,
pub scroll_policy: ScrollPolicy,
pub bounds: Rect<f32>,
pub overflow: Rect<f32>,
pub z_index: i32,
pub display_lists: Vec<DisplayListId>,
pub transform: Matrix4,
pub perspective: Matrix4,
pub establishes_3d_context: bool,
pub mix_blend_mode: MixBlendMode,
pub filters: ItemRange,
pub has_stacking_contexts: bool,
}
20. Scene
● Pipeline_map / display_list_map / stacking_context_map
● Set_root_stacking_context()
○ Remove old display list and stacking_context
○ New a scene pipeline
○ Insert to pipeline_map and remove old one
pub struct ScenePipeline {
pub pipeline_id: PipelineId,
pub epoch: Epoch,
pub background_draw_list: Option<DrawListId>,
pub root_stacking_context_id: StackingContextId,
pub viewport_size: Size2D<f32>,
}
25. ● Build_scene -> Do scene graph
● Render -> Generate RenderFrame
Main thread
render_backend
thread
APIMsg::
SetRootPipeline
26. ● Get root stacking_context
● Create render target
● Create layer
Create new Layer
add_items_to_target
Scrollable
stacking
context
Yes
No
Render_backend::
build_scene()
Frame::create() Frame::flatten()
● Add items to render
target
27. Frame::create
● Create a root layer and render target
● Flatten
○ Try to add to the existing layers as an AABB node or create a new one
■ Determine by whether the same scroll_layer_id or not
impl Layer {
pub fn new(world_origin: Point2D<f32>,
layer_size: Size2D<f32>,
viewport_rect: &Rect<f32>,
viewport_transform: &Matrix4D<f32>,
local_transform: &Matrix4D<f32>,
local_perspective: &Matrix4D<f32>,
pipeline_id: PipelineId,
stacking_context_id: ServoStackingContextId)
Layer
● Own an AABB tree to manage scene items
● Cull via view_port rect
28. Frame::build
● Cull layer’s AABB nodes
○ Adjust viewport to layer’s local space
○ Recursively check_node_visibility->
intersect(viewport rect, AABB node rect) and
mark is_visible to true
● Update
○ Resource
○ Texture
○ Glyph
Cull layers
via viewport rect
Update
29. Frame::build
● compile_visible_nodes
○ Thread_pool.scoped
○ Node_compiler uses BatchBuilder to batch draw list
(same texture, color)
(batch.rs:add_rectangle)
● update_batch_cache
○ Because some vertex buffers are modified after
batching, pending them to update
● update_layer_transforms
○ Update child layer’s world transform and viewport
to the world space
compile_visible_nodes
update_batch_cache
update_layer_transform
30. Frame::build
● compile_visible_nodes
○ Thread_pool.scoped
○ Node_compiler uses BatchBuilder to batch draw list
(same texture, color)
(batch.rs:add_rectangle)
● update_batch_cache
○ Because some vertex buffers are modified after
batching, pending them to update
● update_layer_transforms
○ Update child layer’s world transform and viewport
to the world space
compile_visible_nodes
update_batch_cache
update_layer_transform
thread_pool.scoped(|scope| {
for (_, layer) in layers {
let nodes = &mut layer.aabb_tree.nodes;
for node in nodes {
if node.is_visible && node.compiled_node.is_none() {
scope.execute(move || {
node.compile(resource_cache,
frame_id,
device_pixel_ratio,
stacking_context_info,
draw_list_groups,
pipeline_auxiliary_lists);
});
}
}
}
});
31. Frame::build
● collect_and_sort_visible_batches
○ Collect visible batches from layers and
transform them to RenderTarget space.
○ Traverse RenderTarget tree to collect
■ CompositeBatch (clear buffer,
transform, set texture commands)
■ DrawListBatch (collect draw calls)
○ Generate a DrawLayer tree
○ Return a RendererFrame
● expire_old_resources
collect_and_sort_visible_batches
expire_old_resources
37. Webrender teaches us
● Scene graph
○ Using AABB tree to remove invisible display items effectively.
● Batching
○ Reduce draw calls and state changes to save redundant API calls.
● Delay execution draw commands
○ Avoiding unneeded mode-transition to occur CPU / GPU waiting time.