Bug 1507938 - Update webrender to commit 199ace786ef5d80982a8c811dabfab13593e6ae6 (WR PR #3321). r=kats
authorWR Updater Bot <graphics-team@mozilla.staktrace.com>
Sun, 18 Nov 2018 22:37:30 +0000
changeset 446940 9ca8941c2357
parent 446939 eb04ab1f698a
child 446941 70e906a17ad3
push id35061
push userebalazs@mozilla.com
push dateMon, 19 Nov 2018 09:27:38 +0000
treeherdermozilla-central@88ba9f723934 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1507938
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1507938 - Update webrender to commit 199ace786ef5d80982a8c811dabfab13593e6ae6 (WR PR #3321). r=kats Differential Revision: https://phabricator.services.mozilla.com/D12227
gfx/webrender/src/internal_types.rs
gfx/webrender/src/render_backend.rs
gfx/webrender/src/renderer.rs
gfx/webrender/src/resource_cache.rs
gfx/webrender/src/texture_cache.rs
gfx/webrender_api/src/api.rs
gfx/webrender_bindings/revision.txt
--- a/gfx/webrender/src/internal_types.rs
+++ b/gfx/webrender/src/internal_types.rs
@@ -1,13 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-use api::{DebugCommand, DeviceIntRect, DocumentId, ExternalImageData, ExternalImageId};
+use api::{DebugCommand, DocumentId, ExternalImageData, ExternalImageId};
+use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
 use api::{ImageFormat, WorldPixel, NotificationRequest};
 use device::TextureFilter;
 use renderer::PipelineInfo;
 use gpu_cache::GpuCacheUpdateList;
 use fxhash::FxHasher;
 use plane_split::BspSplitter;
 use profiler::BackendProfileCounters;
 use std::{usize, i32};
@@ -103,16 +104,19 @@ pub struct RenderTargetInfo {
 
 #[derive(Debug)]
 pub enum TextureUpdateSource {
     External {
         id: ExternalImageId,
         channel_index: u8,
     },
     Bytes { data: Arc<Vec<u8>> },
+    /// Clears the target area, rather than uploading any pixels. Used when the
+    /// texture cache debug display is active.
+    DebugClear,
 }
 
 /// Command to allocate, reallocate, or free a texture for the texture cache.
 #[derive(Debug)]
 pub struct TextureCacheAllocation {
     /// The virtual ID (i.e. distinct from device ID) of the texture.
     pub id: CacheTextureId,
     /// Details corresponding to the operation in question.
@@ -178,16 +182,40 @@ impl TextureUpdateList {
     }
 
     /// Pushes an update operation onto the list.
     #[inline]
     pub fn push_update(&mut self, update: TextureCacheUpdate) {
         self.updates.push(update);
     }
 
+    /// Sends a command to the Renderer to clear the portion of the shared region
+    /// we just freed. Used when the texture cache debugger is enabled.
+    #[cold]
+    pub fn push_debug_clear(
+        &mut self,
+        id: CacheTextureId,
+        origin: DeviceIntPoint,
+        width: i32,
+        height: i32,
+        layer_index: usize
+    ) {
+        let size = DeviceIntSize::new(width, height);
+        let rect = DeviceIntRect::new(origin, size);
+        self.push_update(TextureCacheUpdate {
+            id,
+            rect,
+            source: TextureUpdateSource::DebugClear,
+            stride: None,
+            offset: 0,
+            layer_index: layer_index as i32,
+        });
+    }
+
+
     /// Pushes an allocation operation onto the list.
     pub fn push_alloc(&mut self, id: CacheTextureId, info: TextureCacheAllocInfo) {
         debug_assert!(!self.allocations.iter().any(|x| x.id == id));
         self.allocations.push(TextureCacheAllocation {
             id,
             kind: TextureCacheAllocationKind::Alloc(info),
         });
     }
--- a/gfx/webrender/src/render_backend.rs
+++ b/gfx/webrender/src/render_backend.rs
@@ -942,16 +942,20 @@ impl RenderBackend {
                         return true;
                     }
                     DebugCommand::SimulateLongLowPrioritySceneBuild(time_ms) => {
                         self.low_priority_scene_tx.send(
                             SceneBuilderRequest::SimulateLongLowPrioritySceneBuild(time_ms)
                         ).unwrap();
                         return true;
                     }
+                    DebugCommand::SetFlags(flags) => {
+                        self.resource_cache.set_debug_flags(flags);
+                        ResultMsg::DebugCommand(option)
+                    }
                     _ => ResultMsg::DebugCommand(option),
                 };
                 self.result_tx.send(msg).unwrap();
                 self.notifier.wake_up();
             }
             ApiMsg::ShutDown => {
                 return false;
             }
--- a/gfx/webrender/src/renderer.rs
+++ b/gfx/webrender/src/renderer.rs
@@ -25,16 +25,17 @@
 use api::{BlobImageHandler, ColorF, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
 use api::{DocumentId, Epoch, ExternalImageId};
 use api::{ExternalImageType, FontRenderMode, FrameMsg, ImageFormat, PipelineId};
 use api::{ImageRendering, Checkpoint, NotificationRequest};
 use api::{MemoryReport, VoidPtrToSizeFn};
 use api::{RenderApiSender, RenderNotifier, TexelRect, TextureTarget};
 use api::{channel};
 use api::DebugCommand;
+pub use api::DebugFlags;
 use api::channel::PayloadReceiverHelperMethods;
 use batch::{BatchKind, BatchTextures, BrushBatchKind};
 #[cfg(any(feature = "capture", feature = "replay"))]
 use capture::{CaptureConfig, ExternalCaptureImage, PlainExternalImage};
 use debug_colors;
 use device::{DepthFunction, Device, GpuFrameId, Program, UploadMethod, Texture, PBO};
 use device::{DrawTarget, ExternalTexture, FBOId, ReadTarget, TextureSlot};
 use device::{ShaderError, TextureFilter, TextureFlags,
@@ -193,16 +194,21 @@ const GPU_SAMPLER_TAG_OPAQUE: GpuProfile
     label: "Opaque Pass",
     color: debug_colors::BLACK,
 };
 const GPU_SAMPLER_TAG_TRANSPARENT: GpuProfileTag = GpuProfileTag {
     label: "Transparent Pass",
     color: debug_colors::BLACK,
 };
 
+/// The clear color used for the texture cache when the debug display is enabled.
+/// We use a shade of blue so that we can still identify completely blue items in
+/// the texture cache.
+const TEXTURE_CACHE_DBG_CLEAR_COLOR: [f32; 4] = [0.0, 0.0, 0.8, 1.0];
+
 impl BatchKind {
     #[cfg(feature = "debugger")]
     fn debug_name(&self) -> &'static str {
         match *self {
             BatchKind::SplitComposite => "SplitComposite",
             BatchKind::Brush(kind) => {
                 match kind {
                     BrushBatchKind::Solid => "Brush (Solid)",
@@ -232,36 +238,16 @@ impl BatchKind {
                     BrushBatchKind::LinearGradient => GPU_TAG_BRUSH_LINEAR_GRADIENT,
                 }
             }
             BatchKind::TextRun(_) => GPU_TAG_PRIM_TEXT_RUN,
         }
     }
 }
 
-bitflags! {
-    #[derive(Default)]
-    pub struct DebugFlags: u32 {
-        const PROFILER_DBG          = 1 << 0;
-        const RENDER_TARGET_DBG     = 1 << 1;
-        const TEXTURE_CACHE_DBG     = 1 << 2;
-        const GPU_TIME_QUERIES      = 1 << 3;
-        const GPU_SAMPLE_QUERIES    = 1 << 4;
-        const DISABLE_BATCHING      = 1 << 5;
-        const EPOCHS                = 1 << 6;
-        const COMPACT_PROFILER      = 1 << 7;
-        const ECHO_DRIVER_MESSAGES  = 1 << 8;
-        const NEW_FRAME_INDICATOR   = 1 << 9;
-        const NEW_SCENE_INDICATOR   = 1 << 10;
-        const SHOW_OVERDRAW         = 1 << 11;
-        const GPU_CACHE_DBG         = 1 << 12;
-        const SLOW_FRAME_INDICATOR  = 1 << 13;
-    }
-}
-
 fn flag_changed(before: DebugFlags, after: DebugFlags, select: DebugFlags) -> Option<bool> {
     if before & select != after & select {
         Some(after.contains(select))
     } else {
         None
     }
 }
 
@@ -2431,16 +2417,19 @@ impl Renderer {
                             row.is_dirty = true;
                         }
                     }
                     GpuCacheBus::Scatter { .. } => {
                         warn!("Unable to invalidate scattered GPU cache");
                     }
                 }
             }
+            DebugCommand::SetFlags(flags) => {
+                self.set_debug_flags(flags);
+            }
         }
     }
 
     /// Set a callback for handling external images.
     pub fn set_external_image_handler(&mut self, handler: Box<ExternalImageHandler>) {
         self.external_image_handler = Some(handler);
     }
 
@@ -2834,16 +2823,24 @@ impl Renderer {
                                 // tasks get rendered into the texture cache.
                                 Some(RenderTargetInfo { has_depth: false }),
                                 info.layer_count,
                             );
 
                             if info.is_shared_cache {
                                 texture.flags_mut()
                                     .insert(TextureFlags::IS_SHARED_TEXTURE_CACHE);
+
+                                // Textures in the cache generally don't need to be cleared,
+                                // but we do so if the debug display is active to make it
+                                // easier to identify unallocated regions.
+                                if self.debug_flags.contains(DebugFlags::TEXTURE_CACHE_DBG) {
+                                    self.clear_texture(&texture, TEXTURE_CACHE_DBG_CLEAR_COLOR);
+                                }
+
                             }
 
                             let old = self.texture_resolver.texture_cache_map.insert(allocation.id, texture);
                             assert_eq!(old.is_some(), is_realloc, "Renderer and RenderBackend disagree");
                             if let Some(old) = old {
                                 self.device.blit_renderable_texture(
                                     self.texture_resolver.texture_cache_map.get_mut(&allocation.id).unwrap(),
                                     &old
@@ -2856,30 +2853,35 @@ impl Renderer {
                             self.device.delete_texture(texture);
                         },
                     }
                 }
 
                 for update in update_list.updates {
                     let TextureCacheUpdate { id, rect, stride, offset, layer_index, source } = update;
                     let texture = &self.texture_resolver.texture_cache_map[&id];
-                    let mut uploader = self.device.upload_texture(
-                        texture,
-                        &self.texture_cache_upload_pbo,
-                        0,
-                    );
 
                     let bytes_uploaded = match source {
                         TextureUpdateSource::Bytes { data } => {
+                            let mut uploader = self.device.upload_texture(
+                                texture,
+                                &self.texture_cache_upload_pbo,
+                                0,
+                            );
                             uploader.upload(
                                 rect, layer_index, stride,
                                 &data[offset as usize ..],
                             )
                         }
                         TextureUpdateSource::External { id, channel_index } => {
+                            let mut uploader = self.device.upload_texture(
+                                texture,
+                                &self.texture_cache_upload_pbo,
+                                0,
+                            );
                             let handler = self.external_image_handler
                                 .as_mut()
                                 .expect("Found external image, but no handler set!");
                             // The filter is only relevant for NativeTexture external images.
                             let size = match handler.lock(id, channel_index, ImageRendering::Auto).source {
                                 ExternalImageSource::RawData(data) => {
                                     uploader.upload(
                                         rect, layer_index, stride,
@@ -2898,16 +2900,29 @@ impl Renderer {
                                 }
                                 ExternalImageSource::NativeTexture(eid) => {
                                     panic!("Unexpected external texture {:?} for the texture cache update of {:?}", eid, id);
                                 }
                             };
                             handler.unlock(id, channel_index);
                             size
                         }
+                        TextureUpdateSource::DebugClear => {
+                            self.device.bind_draw_target(DrawTarget::Texture {
+                                texture,
+                                layer: layer_index as usize,
+                                with_depth: false,
+                            });
+                            self.device.clear_target(
+                                Some(TEXTURE_CACHE_DBG_CLEAR_COLOR),
+                                None,
+                                Some(rect.to_i32())
+                            );
+                            0
+                        }
                     };
                     self.profile_counters.texture_data_uploaded.add(bytes_uploaded >> 10);
                 }
             }
 
             drain_filter(
                 &mut self.notifications,
                 |n| { n.when() == Checkpoint::FrameTexturesUpdated },
@@ -4545,16 +4560,28 @@ impl Renderer {
     fn set_blend_mode_subpixel_with_bg_color_pass2(&self, framebuffer_kind: FramebufferKind) {
         if framebuffer_kind == FramebufferKind::Main &&
                 self.debug_flags.contains(DebugFlags::SHOW_OVERDRAW) {
             self.device.set_blend_mode_show_overdraw();
         } else {
             self.device.set_blend_mode_subpixel_with_bg_color_pass2();
         }
     }
+
+    /// Clears all the layers of a texture with a given color.
+    fn clear_texture(&mut self, texture: &Texture, color: [f32; 4]) {
+        for i in 0..texture.get_layer_count() {
+            self.device.bind_draw_target(DrawTarget::Texture {
+                texture: &texture,
+                layer: i as usize,
+                with_depth: false,
+            });
+            self.device.clear_target(Some(color), None, None);
+        }
+    }
 }
 
 pub enum ExternalImageSource<'a> {
     RawData(&'a [u8]),  // raw buffers.
     NativeTexture(u32), // It's a gl::GLuint texture handle
     Invalid,
 }
 
--- a/gfx/webrender/src/resource_cache.rs
+++ b/gfx/webrender/src/resource_cache.rs
@@ -1,16 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use api::{AddFont, BlobImageResources, AsyncBlobImageRasterizer, ResourceUpdate};
 use api::{BlobImageDescriptor, BlobImageHandler, BlobImageRequest, RasterizedBlobImage};
 use api::{ClearCache, ColorF, DevicePoint, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
-use api::{FontInstanceKey, FontKey, FontTemplate, GlyphIndex};
+use api::{DebugFlags, FontInstanceKey, FontKey, FontTemplate, GlyphIndex};
 use api::{ExternalImageData, ExternalImageType, BlobImageResult, BlobImageParams};
 use api::{FontInstanceData, FontInstanceOptions, FontInstancePlatformOptions, FontVariation};
 use api::{GlyphDimensions, IdNamespace};
 use api::{ImageData, ImageDescriptor, ImageKey, ImageRendering};
 use api::{MemoryReport, VoidPtrToSizeFn};
 use api::{TileOffset, TileSize, TileRange, BlobImageData};
 use app_units::Au;
 #[cfg(feature = "capture")]
@@ -1618,16 +1618,20 @@ impl ResourceCache {
         }
     }
 
     pub fn end_frame(&mut self) {
         debug_assert_eq!(self.state, State::QueryResources);
         self.state = State::Idle;
     }
 
+    pub fn set_debug_flags(&mut self, flags: DebugFlags) {
+        self.texture_cache.set_debug_flags(flags);
+    }
+
     pub fn clear(&mut self, what: ClearCache) {
         if what.contains(ClearCache::IMAGES) {
             for (_key, mut cached) in self.cached_images.resources.drain() {
                 cached.drop_from_cache(&mut self.texture_cache);
             }
         }
         if what.contains(ClearCache::GLYPHS) {
             self.cached_glyphs.clear();
--- a/gfx/webrender/src/texture_cache.rs
+++ b/gfx/webrender/src/texture_cache.rs
@@ -1,13 +1,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};
+use api::{DebugFlags, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
 use api::{ExternalImageType, ImageData, ImageFormat};
 use api::ImageDescriptor;
 use device::{TextureFilter, total_gpu_bytes_allocated};
 use freelist::{FreeList, FreeListHandle, UpsertResult, WeakFreeListHandle};
 use gpu_cache::{GpuCache, GpuCacheHandle};
 use gpu_types::{ImageSource, UvRectKind};
 use internal_types::{CacheTextureId, LayerIndex, TextureUpdateList, TextureUpdateSource};
 use internal_types::{TextureSource, TextureCacheAllocInfo, TextureCacheUpdate};
@@ -314,16 +314,19 @@ pub struct TextureCache {
     shared_textures: SharedTextures,
 
     /// Maximum texture size supported by hardware.
     max_texture_size: i32,
 
     /// Maximum number of texture layers supported by hardware.
     max_texture_layers: usize,
 
+    /// The current set of debug flags.
+    debug_flags: DebugFlags,
+
     /// The next unused virtual texture ID. Monotonically increasing.
     next_id: CacheTextureId,
 
     /// A list of allocations and updates that need to be applied to the texture
     /// cache in the rendering thread this frame.
     #[cfg_attr(all(feature = "serde", any(feature = "capture", feature = "replay")), serde(skip))]
     pending_updates: TextureUpdateList,
 
@@ -367,25 +370,30 @@ impl TextureCache {
             //     start to introduce performance issues.
             max_texture_layers = max_texture_layers.min(32);
         }
 
         TextureCache {
             shared_textures: SharedTextures::new(),
             max_texture_size,
             max_texture_layers,
+            debug_flags: DebugFlags::empty(),
             next_id: CacheTextureId(1),
             pending_updates: TextureUpdateList::new(),
             frame_id: FrameId::INVALID,
             last_shared_cache_expiration: FrameId::INVALID,
             entries: FreeList::new(),
             handles: EntryHandles::default(),
         }
     }
 
+    pub fn set_debug_flags(&mut self, flags: DebugFlags) {
+        self.debug_flags = flags;
+    }
+
     pub fn clear(&mut self) {
         let standalone_entry_handles = mem::replace(
             &mut self.handles.standalone,
             Vec::new(),
         );
 
         for handle in standalone_entry_handles {
             let entry = self.entries.free(handle);
@@ -542,26 +550,16 @@ impl TextureCache {
                 entry.texture_id,
                 layer_index as i32,
                 dirty_rect,
             );
             self.pending_updates.push_update(op);
         }
     }
 
-    // Get a specific region by index from a shared texture array.
-    fn get_region_mut(&mut self,
-        format: ImageFormat,
-        filter: TextureFilter,
-        layer_index: usize,
-    ) -> &mut TextureRegion {
-        let texture_array = self.shared_textures.select(format, filter);
-        &mut texture_array.regions[layer_index]
-    }
-
     // Check if a given texture handle has a valid allocation
     // in the texture cache.
     pub fn is_allocated(&self, handle: &TextureCacheHandle) -> bool {
         self.entries.get_opt(handle).is_some()
     }
 
     // Retrieve the details of an item in the cache. This is used
     // during batch creation to provide the resource rect address
@@ -710,21 +708,30 @@ impl TextureCache {
                 // This is a standalone texture allocation. Free it directly.
                 self.pending_updates.push_free(entry.texture_id);
             }
             EntryDetails::Cache {
                 origin,
                 layer_index,
             } => {
                 // Free the block in the given region.
-                let region = self.get_region_mut(
-                    entry.format,
-                    entry.filter,
-                    layer_index,
-                );
+                let texture_array = self.shared_textures.select(entry.format, entry.filter);
+                let region = &mut texture_array.regions[layer_index];
+
+                if self.debug_flags.contains(
+                    DebugFlags::TEXTURE_CACHE_DBG |
+                    DebugFlags::TEXTURE_CACHE_DBG_CLEAR_EVICTED) {
+                    self.pending_updates.push_debug_clear(
+                        entry.texture_id,
+                        origin,
+                        region.slab_size.width,
+                        region.slab_size.height,
+                        layer_index
+                    );
+                }
                 region.free(origin);
             }
         }
     }
 
     // Attempt to allocate a block from the shared cache.
     fn allocate_from_shared_cache(
         &mut self,
--- a/gfx/webrender_api/src/api.rs
+++ b/gfx/webrender_api/src/api.rs
@@ -659,16 +659,19 @@ pub enum DebugCommand {
     /// Invalidate GPU cache, forcing the update from the CPU mirror.
     InvalidateGpuCache,
     /// Causes the scene builder to pause for a given amount of miliseconds each time it
     /// processes a transaction.
     SimulateLongSceneBuild(u32),
     /// Causes the low priority scene builder to pause for a given amount of miliseconds
     /// each time it processes a transaction.
     SimulateLongLowPrioritySceneBuild(u32),
+    /// Sets the provided debug flags. This may overlap with some of the functionality
+    /// above.
+    SetFlags(DebugFlags),
 }
 
 #[derive(Clone, Deserialize, Serialize)]
 pub enum ApiMsg {
     /// Add/remove/update images and fonts.
     UpdateResources(Vec<ResourceUpdate>),
     /// Gets the glyph dimensions
     GetGlyphDimensions(
@@ -908,17 +911,37 @@ impl RenderApiSender {
         self.api_sender.send(msg).expect("Failed to send CloneApiByClient message");
         RenderApi {
             api_sender: self.api_sender.clone(),
             payload_sender: self.payload_sender.clone(),
             namespace_id,
             next_id: Cell::new(ResourceId(0)),
         }
     }
+}
 
+bitflags! {
+    #[derive(Default, Deserialize, Serialize)]
+    pub struct DebugFlags: u32 {
+        const PROFILER_DBG          = 1 << 0;
+        const RENDER_TARGET_DBG     = 1 << 1;
+        const TEXTURE_CACHE_DBG     = 1 << 2;
+        const GPU_TIME_QUERIES      = 1 << 3;
+        const GPU_SAMPLE_QUERIES    = 1 << 4;
+        const DISABLE_BATCHING      = 1 << 5;
+        const EPOCHS                = 1 << 6;
+        const COMPACT_PROFILER      = 1 << 7;
+        const ECHO_DRIVER_MESSAGES  = 1 << 8;
+        const NEW_FRAME_INDICATOR   = 1 << 9;
+        const NEW_SCENE_INDICATOR   = 1 << 10;
+        const SHOW_OVERDRAW         = 1 << 11;
+        const GPU_CACHE_DBG         = 1 << 12;
+        const SLOW_FRAME_INDICATOR  = 1 << 13;
+        const TEXTURE_CACHE_DBG_CLEAR_EVICTED = 1 << 14;
+    }
 }
 
 pub struct RenderApi {
     api_sender: MsgSender<ApiMsg>,
     payload_sender: PayloadSender,
     namespace_id: IdNamespace,
     next_id: Cell<ResourceId>,
 }
@@ -1008,16 +1031,21 @@ impl RenderApi {
     }
 
     pub fn report_memory(&self) -> MemoryReport {
         let (tx, rx) = channel::msg_channel().unwrap();
         self.api_sender.send(ApiMsg::ReportMemory(tx)).unwrap();
         rx.recv().unwrap()
     }
 
+    pub fn set_debug_flags(&self, flags: DebugFlags) {
+        let cmd = DebugCommand::SetFlags(flags);
+        self.api_sender.send(ApiMsg::DebugCommand(cmd)).unwrap();
+    }
+
     pub fn shut_down(&self) {
         self.api_sender.send(ApiMsg::ShutDown).unwrap();
     }
 
     /// Create a new unique key that can be used for
     /// animated property bindings.
     pub fn generate_property_binding_key<T: Copy>(&self) -> PropertyBindingKey<T> {
         let new_id = self.next_unique_id();
--- a/gfx/webrender_bindings/revision.txt
+++ b/gfx/webrender_bindings/revision.txt
@@ -1,1 +1,1 @@
-596984d1b49f47af65ccfaedd9684b2a90a564e2
+199ace786ef5d80982a8c811dabfab13593e6ae6