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

Sync changes from mozilla-central gfx/wr #3843

Merged
merged 3 commits into from Jan 24, 2020
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Prev

Bug 1605283 - Improve support for invalidation debugging and testing …

…r=gw

Second part: trace the updates that are sent to the DataStore, and save
at least the Insert/Remove and ItemUID as part of the wr-capture.
(We could expand this with more info, eg. the actual Keys, later).

TileView then reads them back and generates a color coded report to
overlay with the page view.  This helps to see the types and amounts of
interned primitives that lead to cache invalidations.

Differential Revision: https://phabricator.services.mozilla.com/D60619

[ghsync] From https://hg.mozilla.org/mozilla-central/rev/39db0be47ff65dec15b39d70fe465818b090d3b0
  • Loading branch information
bpeersmoz authored and moz-gfx committed Jan 24, 2020
commit 8102f8b98581c1e7e5d650cf505383841680d255
@@ -3,13 +3,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use webrender::{TileNode, TileNodeKind, InvalidationReason, TileOffset};
use webrender::{TileSerializer, TileCacheInstanceSerializer};
use webrender::{TileSerializer, TileCacheInstanceSerializer, TileCacheLoggerUpdateLists};
use serde::Deserialize;
//use ron::de::from_reader;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use std::ffi::OsString;
use webrender::api::enumerate_interners;
use webrender::UpdateKind;

#[derive(Deserialize)]
pub struct Slice {
@@ -234,7 +236,7 @@ fn slices_to_svg(slices: &[Slice], prev_slices: Option<Vec<Slice>>,
+ "\n</svg>\n"
}

fn write_html(output_dir: &Path, svg_files: &[String]) {
fn write_html(output_dir: &Path, svg_files: &[String], intern_files: &[String]) {
let html_head = "<!DOCTYPE html>\n\
<html>\n\
<head>\n\
@@ -253,7 +255,14 @@ fn write_html(output_dir: &Path, svg_files: &[String]) {
for svg_file in svg_files {
script = format!("{} \"{}\",\n", script, svg_file);
}
script = format!("{}];\n\n", script);

script = format!("{}var intern_files = [\n", script);
for intern_file in intern_files {
script = format!("{} \"{}\",\n", script, intern_file);
}
script = format!("{}];\n</script>\n\n", script);

//TODO this requires copying the js file from somewhere?
script = format!("{}<script src=\"tilecache.js\" type=\"text/javascript\"></script>\n\n", script);

@@ -264,8 +273,17 @@ fn write_html(output_dir: &Path, svg_files: &[String]) {

let html_body = format!(
"{}\n\
<object id=\"svg_container0\" type=\"image/svg+xml\" data=\"{}\" class=\"tile_svg\" ></object>\n\
<object id=\"svg_container1\" type=\"image/svg+xml\" data=\"{}\" class=\"tile_svg\" ></object>\n\
<div class=\"split left\">\n\
<div>\n\
<object id=\"svg_container0\" type=\"image/svg+xml\" data=\"{}\" class=\"tile_svg\" ></object>\n\
<object id=\"svg_container1\" type=\"image/svg+xml\" data=\"{}\" class=\"tile_svg\" ></object>\n\
</div>\n\
</div>\n\
\n\
<div class=\"split right\">\n\
<iframe width=\"100%\" id=\"intern\" src=\"{}\"></iframe>\n\
</div>\n\
\n\
<div id=\"svg_ui_overlay\">\n\
<div id=\"text_frame_counter\">{}</div>\n\
<div id=\"text_spacebar\">Spacebar to Play</div>\n\
@@ -275,6 +293,7 @@ fn write_html(output_dir: &Path, svg_files: &[String]) {
html_body,
svg_files[0],
svg_files[0],
intern_files[0],
svg_files[0],
svg_files.len() );

@@ -287,32 +306,59 @@ fn write_html(output_dir: &Path, svg_files: &[String]) {

fn write_css(output_dir: &Path, max_slice_index: usize) {
let mut css = ".tile_svg {\n\
position: fixed;\n\
}\n\n\n\
float: left;\n\
}\n\
\n\
.split {\n\
position: fixed;\n\
z-index: 1;\n\
top: 0;\n\
padding-top: 20px;\n\
}\n\
\n\
.left {\n\
left: 0;\n\
}\n\
\n\
.right {\n\
right: 0;\n\
width: 20%;\n\
height: 100%;\n\
opacity: 90%;\n\
}\n\
\n\
#intern {\n\
position:relative;\n\
top:60px;\n\
width: 100%;\n\
height: 100%;\n\
color: orange;\n\
background-color:white;\n\
}\n\
.svg_invalidated {\n\
fill: white;\n\
font-family:monospace;\n\
fill: white;\n\
font-family:monospace;\n\
}\n\n\n\
#svg_ui_overlay {\n\
position:absolute;\n\
right:0; \n\
top:0; \n\
z-index:70; \n\
color: rgb(255,255,100);\n\
font-family:monospace;\n\
background-color: #404040a0;\n\
position:absolute;\n\
right:0; \n\
top:0; \n\
z-index:70; \n\
color: rgb(255,255,100);\n\
font-family:monospace;\n\
background-color: #404040a0;\n\
}\n\n\n\
.svg_quadtree {\n\
fill: none;\n\
stroke-width: 1;\n\
stroke: orange;\n\
fill: none;\n\
stroke-width: 1;\n\
stroke: orange;\n\
}\n\n\n\
.svg_changed_prim {\n\
stroke: red;\n\
stroke-width: 2.0;\n\
stroke: red;\n\
stroke-width: 2.0;\n\
}\n\n\n\
#svg_ui_slider {\n\
width:90%;\n\
width:90%;\n\
}\n\n".to_string();

for ix in 0..max_slice_index + 1 {
@@ -343,6 +389,64 @@ fn write_css(output_dir: &Path, max_slice_index: usize) {
css_output.write_all(css.as_bytes()).unwrap();
}

macro_rules! updatelist_to_html_macro {
( $( $name:ident: $ty:ty, )+ ) => {
fn updatelist_to_html(update_lists: &TileCacheLoggerUpdateLists) -> String {
let mut html = String::new();
$(
html += &format!("<h4 style=\"margin:5px;\">{}</h4>\n<font color=\"green\">\n", stringify!($name));
let mut was_insert = true;
for update in &update_lists.$name.1 {
let is_insert = match update.kind {
UpdateKind::Insert => true,
_ => false
};
if was_insert != is_insert {
html += &format!("</font><font color=\"{}\">", if is_insert { "green" } else { "red" });
}
html += &format!("{}, \n", update.index);
was_insert = is_insert;
}
html += &"</font><hr/>\n";
)+
html
}
}
}
enumerate_interners!(updatelist_to_html_macro);

fn write_tile_cache_visualizer_svg(entry: &std::fs::DirEntry, output_dir: &Path,
slices: &[Slice], prev_slices: Option<Vec<Slice>>,
svg_width: &mut i32, svg_height: &mut i32,
max_slice_index: &mut usize,
svg_files: &mut Vec::<String>)
{
let svg = slices_to_svg(&slices, prev_slices, svg_width, svg_height, max_slice_index);

let mut output_filename = OsString::from(entry.path().file_name().unwrap());
output_filename.push(".svg");
svg_files.push(output_filename.to_string_lossy().to_string());

output_filename = output_dir.join(output_filename).into_os_string();
let mut svg_output = File::create(output_filename).unwrap();
svg_output.write_all(svg.as_bytes()).unwrap();
}

fn write_update_list_html(entry: &std::fs::DirEntry, output_dir: &Path,
update_lists: &TileCacheLoggerUpdateLists,
html_files: &mut Vec::<String>)
{
let html = updatelist_to_html(update_lists);

let mut output_filename = OsString::from(entry.path().file_name().unwrap());
output_filename.push(".html");
html_files.push(output_filename.to_string_lossy().to_string());

output_filename = output_dir.join(output_filename).into_os_string();
let mut html_output = File::create(output_filename).unwrap();
html_output.write_all(html.as_bytes()).unwrap();
}

fn main() {
let args: Vec<String> = std::env::args().collect();

@@ -368,38 +472,41 @@ fn main() {
entries.sort_by_key(|dir| dir.path());

let mut svg_files: Vec::<String> = Vec::new();
let mut intern_files: Vec::<String> = Vec::new();
let mut prev_slices = None;

for entry in &entries {
if entry.path().is_dir() {
continue;
}
print!("processing {:?}\t", entry.path());
let f = File::open(entry.path()).unwrap();
let slices: Vec<Slice> = match ron::de::from_reader(f) {
let file_data = std::fs::read_to_string(entry.path()).unwrap();
let chunks: Vec<_> = file_data.split("// @@@ chunk @@@").collect();
let slices: Vec<Slice> = match ron::de::from_str(&chunks[0]) {
Ok(data) => { data }
Err(e) => {
println!("ERROR: failed to deserialize {:?}\n{:?}", entry.path(), e);
println!("ERROR: failed to deserialize slicesg {:?}\n{:?}", entry.path(), e);
prev_slices = None;
continue;
}
};
let mut update_lists = TileCacheLoggerUpdateLists::new();
update_lists.from_ron(&chunks[1]);

let svg = slices_to_svg(&slices, prev_slices, &mut svg_width, &mut svg_height, &mut max_slice_index);

let mut output_filename = OsString::from(entry.path().file_name().unwrap());
output_filename.push(".svg");
svg_files.push(output_filename.to_string_lossy().to_string());
write_tile_cache_visualizer_svg(&entry, &output_dir,
&slices, prev_slices,
&mut svg_width, &mut svg_height,
&mut max_slice_index,
&mut svg_files);

output_filename = output_dir.join(output_filename).into_os_string();
let mut svg_output = File::create(output_filename).unwrap();
svg_output.write_all(svg.as_bytes()).unwrap();
write_update_list_html(&entry, &output_dir, &update_lists,
&mut intern_files);

print!("\r");
prev_slices = Some(slices);
}

write_html(output_dir, &svg_files);
write_html(output_dir, &svg_files, &intern_files);
write_css(output_dir, max_slice_index);

println!("OK. For now, manually copy tilecache.js to the output folder please. ");
@@ -75,6 +75,7 @@ function go_to_svg(index) {
is_loading = false;
}
backbuffer.setAttribute('data', svg_files[svg_index]);
document.getElementById('intern').src = intern_files[svg_index];

// also see https://stackoverflow.com/a/29915275
}
@@ -52,7 +52,7 @@ struct Epoch(u64);
/// provided by the interning structure.
pub struct UpdateList<S> {
/// The additions and removals to apply.
updates: Vec<Update>,
pub updates: Vec<Update>,
/// Actual new data to insert.
data: Vec<S>,
}
@@ -122,8 +122,8 @@ pub enum UpdateKind {
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(MallocSizeOf)]
pub struct Update {
index: usize,
kind: UpdateKind,
pub index: usize,
pub kind: UpdateKind,
}

pub trait InternDebug {
@@ -222,4 +222,5 @@ pub use crate::shade::{Shaders, WrShaders};
pub use api as webrender_api;
pub use webrender_build::shader::ProgramSourceDigest;
pub use crate::picture::{TileDescriptor, TileId, InvalidationReason, PrimitiveCompareResult};
pub use crate::picture::{TileNode, TileNodeKind, TileSerializer, TileCacheInstanceSerializer, TileOffset};
pub use crate::picture::{TileNode, TileNodeKind, TileSerializer, TileCacheInstanceSerializer, TileOffset, TileCacheLoggerUpdateLists};
pub use crate::intern::{Update,UpdateKind};
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.