зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1512287
- Expose dirty regions to wrench. r=gw
Depends on D17991 Differential Revision: https://phabricator.services.mozilla.com/D17992 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
c7b68459e9
Коммит
d9c60f139c
|
@ -659,8 +659,8 @@ pub extern "C" fn wr_renderer_render(renderer: &mut Renderer,
|
|||
renderer.notify_slow_frame();
|
||||
}
|
||||
match renderer.render(DeviceIntSize::new(width, height)) {
|
||||
Ok(stats) => {
|
||||
*out_stats = stats;
|
||||
Ok(results) => {
|
||||
*out_stats = results.stats;
|
||||
true
|
||||
}
|
||||
Err(errors) => {
|
||||
|
|
|
@ -596,6 +596,7 @@ impl FrameBuilder {
|
|||
has_been_rendered: false,
|
||||
has_texture_cache_tasks,
|
||||
prim_headers,
|
||||
recorded_dirty_regions: mem::replace(&mut scratch.recorded_dirty_regions, Vec::new()),
|
||||
debug_items: mem::replace(&mut scratch.debug_items, Vec::new()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -209,7 +209,7 @@ pub use frame_builder::ChasePrimitive;
|
|||
pub use renderer::{AsyncPropertySampler, CpuProfile, DebugFlags, OutputImageHandler, RendererKind};
|
||||
pub use renderer::{ExternalImage, ExternalImageHandler, ExternalImageSource, GpuProfile};
|
||||
pub use renderer::{GraphicsApi, GraphicsApiInfo, PipelineInfo, Renderer, RendererOptions};
|
||||
pub use renderer::{RendererStats, SceneBuilderHooks, ThreadListener, ShaderPrecacheFlags};
|
||||
pub use renderer::{RenderResults, RendererStats, SceneBuilderHooks, ThreadListener, ShaderPrecacheFlags};
|
||||
pub use renderer::MAX_VERTEX_TEXTURE_WIDTH;
|
||||
pub use shade::{Shaders, WrShaders};
|
||||
pub use webrender_api as api;
|
||||
|
|
|
@ -420,6 +420,35 @@ impl DirtyRegion {
|
|||
combined,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a record of this dirty region for exporting to test infrastructure.
|
||||
pub fn record(&self) -> RecordedDirtyRegion {
|
||||
let mut rects: Vec<WorldRect> =
|
||||
self.dirty_rects.iter().map(|r| r.world_rect.clone()).collect();
|
||||
rects.sort_unstable_by_key(|r| (r.origin.y as usize, r.origin.x as usize));
|
||||
RecordedDirtyRegion { rects }
|
||||
}
|
||||
}
|
||||
|
||||
/// A recorded copy of the dirty region for exporting to test infrastructure.
|
||||
pub struct RecordedDirtyRegion {
|
||||
pub rects: Vec<WorldRect>,
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for RecordedDirtyRegion {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
for r in self.rects.iter() {
|
||||
let (x, y, w, h) = (r.origin.x, r.origin.y, r.size.width, r.size.height);
|
||||
write!(f, "[({},{}):{}x{}]", x, y, w, h)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Debug for RecordedDirtyRegion {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
|
||||
::std::fmt::Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper struct to build a (roughly) minimal set of dirty rectangles
|
||||
|
@ -1490,6 +1519,12 @@ impl TileCache {
|
|||
|
||||
builder.build(&mut self.dirty_region);
|
||||
|
||||
// When under test, record a copy of the dirty region to support
|
||||
// invalidation testing in wrench.
|
||||
if frame_context.config.testing {
|
||||
scratch.recorded_dirty_regions.push(self.dirty_region.record());
|
||||
}
|
||||
|
||||
// If we end up with too many dirty rects, then it's going to be a lot
|
||||
// of extra draw calls to submit (since we currently just submit every
|
||||
// draw call for every dirty rect). In this case, bail out and work
|
||||
|
|
|
@ -29,7 +29,7 @@ use image::{Repetition};
|
|||
use intern;
|
||||
use malloc_size_of::MallocSizeOf;
|
||||
use picture::{PictureCompositeMode, PicturePrimitive, PictureUpdateState};
|
||||
use picture::{ClusterIndex, PrimitiveList, SurfaceIndex, RetainedTiles, RasterConfig};
|
||||
use picture::{ClusterIndex, PrimitiveList, RecordedDirtyRegion, SurfaceIndex, RetainedTiles, RasterConfig};
|
||||
use prim_store::borders::{ImageBorderDataHandle, NormalBorderDataHandle};
|
||||
use prim_store::gradient::{LinearGradientDataHandle, RadialGradientDataHandle};
|
||||
use prim_store::image::{ImageDataHandle, ImageInstance, VisibleImageTile, YuvImageDataHandle};
|
||||
|
@ -1553,6 +1553,11 @@ pub struct PrimitiveScratchBuffer {
|
|||
/// List of the visibility information for currently visible primitives.
|
||||
pub prim_info: Vec<PrimitiveVisibility>,
|
||||
|
||||
/// List of dirty regions for the cached pictures in this document, used to
|
||||
/// verify invalidation in wrench reftests. Only collected in testing.
|
||||
pub recorded_dirty_regions: Vec<RecordedDirtyRegion>,
|
||||
|
||||
/// List of debug display items for rendering.
|
||||
pub debug_items: Vec<DebugItem>,
|
||||
}
|
||||
|
||||
|
@ -1565,6 +1570,7 @@ impl PrimitiveScratchBuffer {
|
|||
segments: SegmentStorage::new(0),
|
||||
segment_instances: SegmentInstanceStorage::new(0),
|
||||
gradient_tiles: GradientTileStorage::new(0),
|
||||
recorded_dirty_regions: Vec::new(),
|
||||
debug_items: Vec::new(),
|
||||
prim_info: Vec::new(),
|
||||
}
|
||||
|
@ -1599,6 +1605,8 @@ impl PrimitiveScratchBuffer {
|
|||
self.prim_info.clear();
|
||||
|
||||
self.debug_items.clear();
|
||||
|
||||
assert!(self.recorded_dirty_regions.is_empty(), "Should have sent to Renderer");
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
|
@ -58,6 +58,7 @@ use internal_types::{CacheTextureId, DebugOutput, FastHashMap, LayerIndex, Rende
|
|||
use internal_types::{TextureCacheAllocationKind, TextureCacheUpdate, TextureUpdateList, TextureUpdateSource};
|
||||
use internal_types::{RenderTargetInfo, SavedTargetIndex};
|
||||
use malloc_size_of::MallocSizeOfOps;
|
||||
use picture::RecordedDirtyRegion;
|
||||
use prim_store::DeferredResolve;
|
||||
use profiler::{BackendProfileCounters, FrameProfileCounters, TimeProfileCounter,
|
||||
GpuProfileTag, RendererProfileCounters, RendererProfileTimers};
|
||||
|
@ -2455,7 +2456,7 @@ impl Renderer {
|
|||
pub fn render(
|
||||
&mut self,
|
||||
framebuffer_size: DeviceIntSize,
|
||||
) -> Result<RendererStats, Vec<RendererError>> {
|
||||
) -> Result<RenderResults, Vec<RendererError>> {
|
||||
self.framebuffer_size = Some(framebuffer_size);
|
||||
|
||||
let result = self.render_impl(Some(framebuffer_size));
|
||||
|
@ -2481,14 +2482,14 @@ impl Renderer {
|
|||
fn render_impl(
|
||||
&mut self,
|
||||
framebuffer_size: Option<DeviceIntSize>,
|
||||
) -> Result<RendererStats, Vec<RendererError>> {
|
||||
) -> Result<RenderResults, Vec<RendererError>> {
|
||||
profile_scope!("render");
|
||||
let mut results = RenderResults::default();
|
||||
if self.active_documents.is_empty() {
|
||||
self.last_time = precise_time_ns();
|
||||
return Ok(RendererStats::empty());
|
||||
return Ok(results);
|
||||
}
|
||||
|
||||
let mut stats = RendererStats::empty();
|
||||
let mut frame_profiles = Vec::new();
|
||||
let mut profile_timers = RendererProfileTimers::new();
|
||||
|
||||
|
@ -2577,12 +2578,16 @@ impl Renderer {
|
|||
framebuffer_size,
|
||||
clear_depth_value.is_some(),
|
||||
cpu_frame_id,
|
||||
&mut stats
|
||||
&mut results.stats
|
||||
);
|
||||
|
||||
if self.debug_flags.contains(DebugFlags::PROFILER_DBG) {
|
||||
frame_profiles.push(frame.profile_counters.clone());
|
||||
}
|
||||
|
||||
let dirty_regions =
|
||||
mem::replace(&mut frame.recorded_dirty_regions, Vec::new());
|
||||
results.recorded_dirty_regions.extend(dirty_regions);
|
||||
}
|
||||
|
||||
self.unlock_external_images();
|
||||
|
@ -2665,13 +2670,13 @@ impl Renderer {
|
|||
self.device.echo_driver_messages();
|
||||
}
|
||||
|
||||
stats.texture_upload_kb = self.profile_counters.texture_data_uploaded.get();
|
||||
results.stats.texture_upload_kb = self.profile_counters.texture_data_uploaded.get();
|
||||
self.backend_profile_counters.reset();
|
||||
self.profile_counters.reset();
|
||||
self.profile_counters.frame_counter.inc();
|
||||
stats.resource_upload_time = self.resource_upload_time;
|
||||
results.stats.resource_upload_time = self.resource_upload_time;
|
||||
self.resource_upload_time = 0;
|
||||
stats.gpu_cache_upload_time = self.gpu_cache_upload_time;
|
||||
results.stats.gpu_cache_upload_time = self.gpu_cache_upload_time;
|
||||
self.gpu_cache_upload_time = 0;
|
||||
|
||||
profile_timers.cpu_time.profile(|| {
|
||||
|
@ -2687,7 +2692,7 @@ impl Renderer {
|
|||
}
|
||||
|
||||
if self.renderer_errors.is_empty() {
|
||||
Ok(stats)
|
||||
Ok(results)
|
||||
} else {
|
||||
Err(mem::replace(&mut self.renderer_errors, Vec::new()))
|
||||
}
|
||||
|
@ -4845,11 +4850,11 @@ impl DebugServer {
|
|||
pub fn send(&mut self, _: String) {}
|
||||
}
|
||||
|
||||
// Some basic statistics about the rendered scene
|
||||
// that we can use in wrench reftests to ensure that
|
||||
// tests are batching and/or allocating on render
|
||||
// targets as we expect them to.
|
||||
/// Some basic statistics about the rendered scene, used in Gecko, as
|
||||
/// well as in wrench reftests to ensure that tests are batching and/or
|
||||
/// allocating on render targets as we expect them to.
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct RendererStats {
|
||||
pub total_draw_calls: usize,
|
||||
pub alpha_target_count: usize,
|
||||
|
@ -4859,21 +4864,14 @@ pub struct RendererStats {
|
|||
pub gpu_cache_upload_time: u64,
|
||||
}
|
||||
|
||||
impl RendererStats {
|
||||
pub fn empty() -> Self {
|
||||
RendererStats {
|
||||
total_draw_calls: 0,
|
||||
alpha_target_count: 0,
|
||||
color_target_count: 0,
|
||||
texture_upload_kb: 0,
|
||||
resource_upload_time: 0,
|
||||
gpu_cache_upload_time: 0,
|
||||
}
|
||||
}
|
||||
/// Return type from render(), which contains some repr(C) statistics as well as
|
||||
/// some non-repr(C) data.
|
||||
#[derive(Debug, Default)]
|
||||
pub struct RenderResults {
|
||||
pub stats: RendererStats,
|
||||
pub recorded_dirty_regions: Vec<RecordedDirtyRegion>,
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[cfg(any(feature = "capture", feature = "replay"))]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
|
|
|
@ -18,7 +18,7 @@ use gpu_types::{TransformData, TransformPalette, ZBufferIdGenerator};
|
|||
use internal_types::{CacheTextureId, FastHashMap, SavedTargetIndex, TextureSource};
|
||||
#[cfg(feature = "pathfinder")]
|
||||
use pathfinder_partitioner::mesh::Mesh;
|
||||
use picture::SurfaceInfo;
|
||||
use picture::{RecordedDirtyRegion, SurfaceInfo};
|
||||
use prim_store::{PrimitiveStore, DeferredResolve, PrimitiveScratchBuffer};
|
||||
use profiler::FrameProfileCounters;
|
||||
use render_backend::{DataStores, FrameId};
|
||||
|
@ -1119,6 +1119,11 @@ pub struct Frame {
|
|||
/// renderer.
|
||||
pub has_been_rendered: bool,
|
||||
|
||||
/// Dirty regions recorded when generating this frame. Empty when not in
|
||||
/// testing.
|
||||
#[cfg_attr(feature = "serde", serde(skip))]
|
||||
pub recorded_dirty_regions: Vec<RecordedDirtyRegion>,
|
||||
|
||||
/// Debugging information to overlay for this frame.
|
||||
pub debug_items: Vec<DebugItem>,
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ use std::fs::File;
|
|||
use std::io::{BufRead, BufReader};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::mpsc::Receiver;
|
||||
use webrender::RendererStats;
|
||||
use webrender::RenderResults;
|
||||
use webrender::api::*;
|
||||
use wrench::{Wrench, WrenchThing};
|
||||
use yaml_frame_reader::YamlFrameReader;
|
||||
|
@ -376,7 +376,7 @@ impl<'a> ReftestHarness<'a> {
|
|||
|
||||
// the reference can be smaller than the window size,
|
||||
// in which case we only compare the intersection
|
||||
let (test, stats) = self.render_yaml(
|
||||
let (test, results) = self.render_yaml(
|
||||
t.test.as_path(),
|
||||
reference.size,
|
||||
t.font_render_mode,
|
||||
|
@ -394,10 +394,10 @@ impl<'a> ReftestHarness<'a> {
|
|||
let comparison = test.compare(&reference);
|
||||
|
||||
if let Some(expected_draw_calls) = t.expected_draw_calls {
|
||||
if expected_draw_calls != stats.total_draw_calls {
|
||||
if expected_draw_calls != results.stats.total_draw_calls {
|
||||
println!("REFTEST TEST-UNEXPECTED-FAIL | {} | {}/{} | expected_draw_calls",
|
||||
t,
|
||||
stats.total_draw_calls,
|
||||
results.stats.total_draw_calls,
|
||||
expected_draw_calls
|
||||
);
|
||||
println!("REFTEST TEST-END | {}", t);
|
||||
|
@ -405,10 +405,10 @@ impl<'a> ReftestHarness<'a> {
|
|||
}
|
||||
}
|
||||
if let Some(expected_alpha_targets) = t.expected_alpha_targets {
|
||||
if expected_alpha_targets != stats.alpha_target_count {
|
||||
if expected_alpha_targets != results.stats.alpha_target_count {
|
||||
println!("REFTEST TEST-UNEXPECTED-FAIL | {} | {}/{} | alpha_target_count",
|
||||
t,
|
||||
stats.alpha_target_count,
|
||||
results.stats.alpha_target_count,
|
||||
expected_alpha_targets
|
||||
);
|
||||
println!("REFTEST TEST-END | {}", t);
|
||||
|
@ -416,10 +416,10 @@ impl<'a> ReftestHarness<'a> {
|
|||
}
|
||||
}
|
||||
if let Some(expected_color_targets) = t.expected_color_targets {
|
||||
if expected_color_targets != stats.color_target_count {
|
||||
if expected_color_targets != results.stats.color_target_count {
|
||||
println!("REFTEST TEST-UNEXPECTED-FAIL | {} | {}/{} | color_target_count",
|
||||
t,
|
||||
stats.color_target_count,
|
||||
results.stats.color_target_count,
|
||||
expected_color_targets
|
||||
);
|
||||
println!("REFTEST TEST-END | {}", t);
|
||||
|
@ -483,7 +483,7 @@ impl<'a> ReftestHarness<'a> {
|
|||
size: DeviceIntSize,
|
||||
font_render_mode: Option<FontRenderMode>,
|
||||
allow_mipmaps: bool,
|
||||
) -> (ReftestImage, RendererStats) {
|
||||
) -> (ReftestImage, RenderResults) {
|
||||
let mut reader = YamlFrameReader::new(filename);
|
||||
reader.set_font_render_mode(font_render_mode);
|
||||
reader.allow_mipmaps(allow_mipmaps);
|
||||
|
@ -493,7 +493,7 @@ impl<'a> ReftestHarness<'a> {
|
|||
|
||||
// wait for the frame
|
||||
self.rx.recv().unwrap();
|
||||
let stats = self.wrench.render();
|
||||
let results = self.wrench.render();
|
||||
|
||||
let window_size = self.window.get_inner_size();
|
||||
assert!(
|
||||
|
@ -515,6 +515,6 @@ impl<'a> ReftestHarness<'a> {
|
|||
|
||||
reader.deinit(self.wrench);
|
||||
|
||||
(ReftestImage { data: pixels, size }, stats)
|
||||
(ReftestImage { data: pixels, size }, results)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ use std::sync::mpsc::Receiver;
|
|||
use time;
|
||||
use webrender;
|
||||
use webrender::api::*;
|
||||
use webrender::{DebugFlags, RendererStats, ShaderPrecacheFlags};
|
||||
use webrender::{DebugFlags, RenderResults, ShaderPrecacheFlags};
|
||||
use yaml_frame_writer::YamlFrameWriterReceiver;
|
||||
use {WindowWrapper, NotifierEvent};
|
||||
|
||||
|
@ -555,7 +555,7 @@ impl Wrench {
|
|||
self.renderer.get_frame_profiles()
|
||||
}
|
||||
|
||||
pub fn render(&mut self) -> RendererStats {
|
||||
pub fn render(&mut self) -> RenderResults {
|
||||
self.renderer.update();
|
||||
let _ = self.renderer.flush_pipeline_info();
|
||||
self.renderer
|
||||
|
|
Загрузка…
Ссылка в новой задаче