| author | Nicolas Silva <nsilva@mozilla.com> |
| Fri, 13 Dec 2019 04:55:38 +0000 | |
| changeset 506843 | 0112c670bd65f1214aee2764657690b211eabb6f |
| parent 506842 | a96a38c0b28f9db0359ab77e20fdb6147ca12945 |
| child 506844 | 2a87eb08886e30ca7bbbc4438220aa5c97a61630 |
| push id | 36913 |
| push user | opoprus@mozilla.com |
| push date | Fri, 13 Dec 2019 16:53:24 +0000 |
| treeherder | mozilla-central@1ed684598bd0 [default view] [failures only] |
| perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
| reviewers | gw |
| bugs | 1595768 |
| milestone | 73.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
|
--- a/gfx/wr/webrender/src/texture_cache.rs +++ b/gfx/wr/webrender/src/texture_cache.rs @@ -20,16 +20,17 @@ use crate::profiler::{ResourceProfileCou use crate::render_backend::{FrameId, FrameStamp}; use crate::resource_cache::{CacheItem, CachedImageData}; use smallvec::SmallVec; use std::cell::Cell; use std::cmp; use std::mem; use std::time::{Duration, SystemTime}; use std::rc::Rc; +use euclid::size2; /// The size of each region/layer in shared cache texture arrays. pub const TEXTURE_REGION_DIMENSIONS: i32 = 512; const PICTURE_TEXTURE_ADD_SLICES: usize = 4; /// The chosen image format for picture tiles. const PICTURE_TILE_FORMAT: ImageFormat = ImageFormat::RGBA8; @@ -56,45 +57,48 @@ enum EntryDetails { layer_index: usize, }, Cache { /// Origin within the texture layer where this item exists. origin: DeviceIntPoint, /// The layer index of the texture array. layer_index: usize, }, + Empty, } impl EntryDetails { fn describe(&self) -> (LayerIndex, DeviceIntPoint) { match *self { - EntryDetails::Standalone => (0, DeviceIntPoint::zero()), + EntryDetails::Standalone | EntryDetails::Empty => (0, DeviceIntPoint::zero()), EntryDetails::Picture { layer_index, .. } => (layer_index, DeviceIntPoint::zero()), EntryDetails::Cache { origin, layer_index } => (layer_index, origin), } } } impl EntryDetails { /// Returns the kind associated with the details. fn kind(&self) -> EntryKind { match *self { EntryDetails::Standalone => EntryKind::Standalone, EntryDetails::Picture { .. } => EntryKind::Picture, EntryDetails::Cache { .. } => EntryKind::Shared, + EntryDetails::Empty => EntryKind::Empty, } } } /// Tag identifying standalone-versus-shared, without the details. #[derive(Clone, Copy, Debug, Eq, PartialEq)] enum EntryKind { Standalone, Picture, Shared, + Empty, } #[derive(Debug)] pub enum CacheEntryMarker {} // Stores information related to a single entry in the texture // cache. This is stored for each item whether it's in the shared // cache or a standalone texture. @@ -145,16 +149,34 @@ impl CacheEntry { swizzle, uv_rect_handle: GpuCacheHandle::new(), eviction_notice: None, uv_rect_kind: params.uv_rect_kind, eviction: Eviction::Auto, } } + // Create a new entry for a standalone texture. + fn new_empty(last_access: FrameStamp) -> Self { + CacheEntry { + size: size2(0, 0), + user_data: [0.0; 3], + last_access, + details: EntryDetails::Empty, + texture_id: CacheTextureId(std::u64::MAX), + input_format: ImageFormat::BGRA8, + filter: TextureFilter::Linear, + swizzle: Swizzle::default(), + uv_rect_handle: GpuCacheHandle::new(), + eviction_notice: None, + uv_rect_kind: UvRectKind::Rect, + eviction: Eviction::Auto, + } + } + // Update the GPU cache for this texture cache entry. // This ensures that the UV rect, and texture layer index // are up to date in the GPU cache for vertex shaders // to fetch from. fn update_gpu_cache(&mut self, gpu_cache: &mut GpuCache) { if let Some(mut request) = gpu_cache.request(&mut self.uv_rect_handle) { let (layer_index, origin) = self.details.describe(); let image_source = ImageSource { @@ -338,25 +360,28 @@ impl SharedTextures { #[cfg_attr(feature = "replay", derive(Deserialize))] struct EntryHandles { /// Handles for each standalone texture cache entry. standalone: Vec<FreeListHandle<CacheEntryMarker>>, /// Handles for each picture cache entry. picture: Vec<FreeListHandle<CacheEntryMarker>>, /// Handles for each shared texture cache entry. shared: Vec<FreeListHandle<CacheEntryMarker>>, + /// Handles for each shared texture cache entry. + empty: Vec<FreeListHandle<CacheEntryMarker>>, } impl EntryHandles { /// Mutably borrows the requested handle list. fn select(&mut self, kind: EntryKind) -> &mut Vec<FreeListHandle<CacheEntryMarker>> { match kind { EntryKind::Standalone => &mut self.standalone, EntryKind::Picture => &mut self.picture, EntryKind::Shared => &mut self.shared, + EntryKind::Empty => &mut self.empty, } } } /// Container struct for the various parameters used in cache allocation. struct CacheAllocParams { descriptor: ImageDescriptor, filter: TextureFilter, @@ -1162,17 +1187,18 @@ impl TextureCache { origin, region.slab_size.width, region.slab_size.height, layer_index, ); } region.free(origin, &mut unit.empty_regions); } - } + EntryDetails::Empty => {} + } } /// Check if we can allocate this entry without growing any of the texture cache arrays. fn has_space_in_shared_cache( &mut self, params: &CacheAllocParams, ) -> bool { let texture_array = self.shared_textures.select( @@ -1257,17 +1283,18 @@ impl TextureCache { ) -> bool { let mut allowed_in_shared_cache = true; // Anything larger than TEXTURE_REGION_DIMENSIONS goes in a standalone texture. // TODO(gw): If we find pages that suffer from batch breaks in this // case, add support for storing these in a standalone // texture array. if descriptor.size.width > TEXTURE_REGION_DIMENSIONS || - descriptor.size.height > TEXTURE_REGION_DIMENSIONS + descriptor.size.height > TEXTURE_REGION_DIMENSIONS || + descriptor.size.is_empty_or_negative() { allowed_in_shared_cache = false; } // TODO(gw): For now, alpha formats of the texture cache can only be linearly sampled. // Nearest sampling gets a standalone texture. // This is probably rare enough that it can be fixed up later. if filter == TextureFilter::Nearest && @@ -1318,18 +1345,19 @@ impl TextureCache { /// /// This allocates from the shared cache unless the parameters do not meet /// the shared cache requirements, in which case a standalone texture is /// used. fn allocate_cache_entry( &mut self, params: &CacheAllocParams, ) -> CacheEntry { - assert!(!params.descriptor.size.is_empty_or_negative()); - + if params.descriptor.size.is_empty_or_negative() { + return CacheEntry::new_empty(self.now); + } // If this image doesn't qualify to go in the shared (batching) cache, // allocate a standalone entry. if self.is_allowed_in_shared_cache(params.filter, ¶ms.descriptor) { if !self.has_space_in_shared_cache(params) { // If we don't have extra space and haven't GCed this frame, do so. let threshold = self.default_eviction(); self.maybe_expire_old_shared_entries(threshold); } @@ -1358,17 +1386,17 @@ impl TextureCache { UpsertResult::Updated(old_entry) => { if new_kind != old_entry.details.kind() { // Handle the rare case than an update moves an entry from // shared to standalone or vice versa. This involves a linear // search, but should be rare enough not to matter. let (from, to) = match new_kind { EntryKind::Standalone => (&mut self.doc_data.handles.shared, &mut self.doc_data.handles.standalone), - EntryKind::Picture => unreachable!(), + EntryKind::Picture | EntryKind::Empty => unreachable!(), EntryKind::Shared => (&mut self.doc_data.handles.standalone, &mut self.doc_data.handles.shared), }; let idx = from.iter().position(|h| h.weak() == *handle).unwrap(); to.push(from.remove(idx)); } self.free(&old_entry); }