Skip to content

Commit

Permalink
Share gradient GPU cache entries for repeated gradient primitives.
Browse files Browse the repository at this point in the history
This is a potential fix for the intermittent failures here:
#2441 (comment)

I still can't reproduce them locally. However, I could see that the
GPU cache size in that test was getting dangerously close to the
maximum size of the texture supported by the GL implementation.

That would fit with the issues we're seeing on CI, where there
seems to be items not being drawn, and they are affected even
though the test in question doesn't draw any gradients.

This is not a very elegant fix - however it will hopefully fix
the issues we are seeing on CI for now. We can revisit this
later to consider a better fix.
  • Loading branch information
gw3583 committed Feb 22, 2018
1 parent d203776 commit 58a1de7
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 13 deletions.
10 changes: 7 additions & 3 deletions webrender/src/batch.rs
Expand Up @@ -18,7 +18,7 @@ use gpu_types::{CompositePrimitiveInstance, PrimitiveInstance, SimplePrimitiveIn
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive, PictureSurface};
use plane_split::{BspSplitter, Polygon, Splitter};
use prim_store::{ImageSource, PrimitiveIndex, PrimitiveKind, PrimitiveMetadata, PrimitiveStore};
use prim_store::{CachedGradient, ImageSource, PrimitiveIndex, PrimitiveKind, PrimitiveMetadata, PrimitiveStore};
use prim_store::{BrushPrimitive, BrushKind, DeferredResolve, EdgeAaSegmentMask, PrimitiveRun};
use render_task::{RenderTaskAddress, RenderTaskId, RenderTaskKind, RenderTaskTree};
use renderer::{BlendMode, ImageBufferKind};
Expand Down Expand Up @@ -681,6 +681,7 @@ impl AlphaBatchBuilder {
ctx.resource_cache,
gpu_cache,
deferred_resolves,
&ctx.cached_gradients,
) {
self.add_brush_to_batch(
brush,
Expand Down Expand Up @@ -1312,6 +1313,7 @@ impl BrushPrimitive {
resource_cache: &ResourceCache,
gpu_cache: &mut GpuCache,
deferred_resolves: &mut Vec<DeferredResolve>,
cached_gradients: &[CachedGradient],
) -> Option<(BrushBatchKind, BatchTextures, [i32; 3])> {
match self.kind {
BrushKind::Line { .. } => {
Expand Down Expand Up @@ -1358,7 +1360,8 @@ impl BrushPrimitive {
[0; 3],
))
}
BrushKind::RadialGradient { ref stops_handle, .. } => {
BrushKind::RadialGradient { gradient_index, .. } => {
let stops_handle = &cached_gradients[gradient_index.0].handle;
Some((
BrushBatchKind::RadialGradient,
BatchTextures::no_texture(),
Expand All @@ -1369,7 +1372,8 @@ impl BrushPrimitive {
],
))
}
BrushKind::LinearGradient { ref stops_handle, .. } => {
BrushKind::LinearGradient { gradient_index, .. } => {
let stops_handle = &cached_gradients[gradient_index.0].handle;
Some((
BrushBatchKind::LinearGradient,
BatchTextures::no_texture(),
Expand Down
28 changes: 23 additions & 5 deletions webrender/src/frame_builder.rs
Expand Up @@ -18,12 +18,12 @@ use clip_scroll_tree::{ClipScrollTree, ClipChainIndex};
use euclid::{SideOffsets2D, vec2};
use frame::{FrameId, ClipIdToIndexMapper};
use glyph_rasterizer::FontInstance;
use gpu_cache::{GpuCache, GpuCacheHandle};
use gpu_cache::GpuCache;
use gpu_types::{ClipChainRectIndex, ClipScrollNodeData, PictureType};
use hit_test::{HitTester, HitTestingItem, HitTestingRun};
use internal_types::{FastHashMap, FastHashSet};
use picture::{ContentOrigin, PictureCompositeMode, PictureKind, PicturePrimitive, PictureSurface};
use prim_store::{BrushKind, BrushPrimitive, BrushSegmentDescriptor};
use prim_store::{BrushKind, BrushPrimitive, BrushSegmentDescriptor, CachedGradient, CachedGradientIndex};
use prim_store::{ImageCacheKey, ImagePrimitiveCpu, ImageSource, PrimitiveContainer};
use prim_store::{PrimitiveIndex, PrimitiveKind, PrimitiveRun, PrimitiveStore};
use prim_store::{ScrollNodeAndClipChain, TextRunPrimitiveCpu};
Expand Down Expand Up @@ -85,6 +85,7 @@ pub struct FrameBuilder {
pub clip_store: ClipStore,
hit_testing_runs: Vec<HitTestingRun>,
pub config: FrameBuilderConfig,
pub cached_gradients: Vec<CachedGradient>,

// A stack of the current shadow primitives.
// The sub-Vec stores a buffer of fast-path primitives to be appended on pop.
Expand Down Expand Up @@ -123,6 +124,7 @@ pub struct FrameState<'a> {
pub local_clip_rects: &'a mut Vec<LayerRect>,
pub resource_cache: &'a mut ResourceCache,
pub gpu_cache: &'a mut GpuCache,
pub cached_gradients: &'a mut [CachedGradient],
}

pub struct PictureContext<'a> {
Expand Down Expand Up @@ -172,6 +174,7 @@ impl FrameBuilder {
FrameBuilder {
hit_testing_runs: Vec::new(),
shadow_prim_stack: Vec::new(),
cached_gradients: Vec::new(),
pending_shadow_contents: Vec::new(),
scrollbar_prims: Vec::new(),
reference_frame_stack: Vec::new(),
Expand Down Expand Up @@ -200,6 +203,7 @@ impl FrameBuilder {
FrameBuilder {
hit_testing_runs: recycle_vec(self.hit_testing_runs),
shadow_prim_stack: recycle_vec(self.shadow_prim_stack),
cached_gradients: recycle_vec(self.cached_gradients),
pending_shadow_contents: recycle_vec(self.pending_shadow_contents),
scrollbar_prims: recycle_vec(self.scrollbar_prims),
reference_frame_stack: recycle_vec(self.reference_frame_stack),
Expand Down Expand Up @@ -1232,7 +1236,7 @@ impl FrameBuilder {
}
}

pub fn add_gradient_impl(
fn add_gradient_impl(
&mut self,
clip_and_scroll: ScrollNodeAndClipChain,
info: &LayerPrimitiveInfo,
Expand All @@ -1241,6 +1245,7 @@ impl FrameBuilder {
stops: ItemRange<GradientStop>,
stops_count: usize,
extend_mode: ExtendMode,
gradient_index: CachedGradientIndex,
) {
// Try to ensure that if the gradient is specified in reverse, then so long as the stops
// are also supplied in reverse that the rendered result will be equivalent. To do this,
Expand All @@ -1262,13 +1267,13 @@ impl FrameBuilder {

let prim = BrushPrimitive::new(
BrushKind::LinearGradient {
stops_handle: GpuCacheHandle::new(),
stops_range: stops,
stops_count,
extend_mode,
reverse_stops,
start_point: sp,
end_point: ep,
gradient_index,
},
None,
);
Expand All @@ -1290,6 +1295,9 @@ impl FrameBuilder {
tile_size: LayerSize,
tile_spacing: LayerSize,
) {
let gradient_index = CachedGradientIndex(self.cached_gradients.len());
self.cached_gradients.push(CachedGradient::new());

let prim_infos = info.decompose(
tile_size,
tile_spacing,
Expand All @@ -1305,6 +1313,7 @@ impl FrameBuilder {
stops,
stops_count,
extend_mode,
gradient_index,
);
} else {
for prim_info in prim_infos {
Expand All @@ -1316,6 +1325,7 @@ impl FrameBuilder {
stops,
stops_count,
extend_mode,
gradient_index,
);
}
}
Expand All @@ -1332,17 +1342,18 @@ impl FrameBuilder {
ratio_xy: f32,
stops: ItemRange<GradientStop>,
extend_mode: ExtendMode,
gradient_index: CachedGradientIndex,
) {
let prim = BrushPrimitive::new(
BrushKind::RadialGradient {
stops_range: stops,
extend_mode,
stops_handle: GpuCacheHandle::new(),
start_center,
end_center,
start_radius,
end_radius,
ratio_xy,
gradient_index,
},
None,
);
Expand All @@ -1369,6 +1380,9 @@ impl FrameBuilder {
tile_size: LayerSize,
tile_spacing: LayerSize,
) {
let gradient_index = CachedGradientIndex(self.cached_gradients.len());
self.cached_gradients.push(CachedGradient::new());

let prim_infos = info.decompose(
tile_size,
tile_spacing,
Expand All @@ -1386,6 +1400,7 @@ impl FrameBuilder {
ratio_xy,
stops,
extend_mode,
gradient_index,
);
} else {
for prim_info in prim_infos {
Expand All @@ -1399,6 +1414,7 @@ impl FrameBuilder {
ratio_xy,
stops,
extend_mode,
gradient_index,
);
}
}
Expand Down Expand Up @@ -1718,6 +1734,7 @@ impl FrameBuilder {
local_clip_rects,
resource_cache,
gpu_cache,
cached_gradients: &mut self.cached_gradients,
};

let pic_context = PictureContext {
Expand Down Expand Up @@ -1886,6 +1903,7 @@ impl FrameBuilder {
clip_scroll_tree,
use_dual_source_blending,
node_data: &node_data,
cached_gradients: &self.cached_gradients,
};

pass.build(
Expand Down
25 changes: 21 additions & 4 deletions webrender/src/prim_store.rs
Expand Up @@ -71,6 +71,21 @@ impl PrimitiveOpacity {
}
}

#[derive(Debug, Copy, Clone)]
pub struct CachedGradientIndex(pub usize);

pub struct CachedGradient {
pub handle: GpuCacheHandle,
}

impl CachedGradient {
pub fn new() -> CachedGradient {
CachedGradient {
handle: GpuCacheHandle::new(),
}
}
}

// Represents the local space rect of a list of
// primitive runs. For most primitive runs, the
// primitive runs are attached to the parent they
Expand Down Expand Up @@ -205,19 +220,19 @@ pub enum BrushKind {
image_rendering: ImageRendering,
},
RadialGradient {
gradient_index: CachedGradientIndex,
stops_range: ItemRange<GradientStop>,
extend_mode: ExtendMode,
stops_handle: GpuCacheHandle,
start_center: LayerPoint,
end_center: LayerPoint,
start_radius: f32,
end_radius: f32,
ratio_xy: f32,
},
LinearGradient {
gradient_index: CachedGradientIndex,
stops_range: ItemRange<GradientStop>,
stops_count: usize,
stops_handle: GpuCacheHandle,
extend_mode: ExtendMode,
reverse_stops: bool,
start_point: LayerPoint,
Expand Down Expand Up @@ -1255,7 +1270,8 @@ impl PrimitiveStore {
);
}
}
BrushKind::RadialGradient { ref mut stops_handle, stops_range, .. } => {
BrushKind::RadialGradient { gradient_index, stops_range, .. } => {
let stops_handle = &mut frame_state.cached_gradients[gradient_index.0].handle;
if let Some(mut request) = frame_state.gpu_cache.request(stops_handle) {
let gradient_builder = GradientGpuBlockBuilder::new(
stops_range,
Expand All @@ -1267,7 +1283,8 @@ impl PrimitiveStore {
);
}
}
BrushKind::LinearGradient { ref mut stops_handle, stops_range, reverse_stops, .. } => {
BrushKind::LinearGradient { gradient_index, stops_range, reverse_stops, .. } => {
let stops_handle = &mut frame_state.cached_gradients[gradient_index.0].handle;
if let Some(mut request) = frame_state.gpu_cache.request(stops_handle) {
let gradient_builder = GradientGpuBlockBuilder::new(
stops_range,
Expand Down
3 changes: 2 additions & 1 deletion webrender/src/tiling.rs
Expand Up @@ -16,7 +16,7 @@ use gpu_types::{ClipScrollNodeData, ClipScrollNodeIndex};
use gpu_types::{PrimitiveInstance};
use internal_types::{FastHashMap, SavedTargetIndex, SourceTexture};
use picture::{PictureKind};
use prim_store::{PrimitiveIndex, PrimitiveKind, PrimitiveStore};
use prim_store::{CachedGradient, PrimitiveIndex, PrimitiveKind, PrimitiveStore};
use prim_store::{BrushMaskKind, BrushKind, DeferredResolve, EdgeAaSegmentMask};
use profiler::FrameProfileCounters;
use render_task::{BlitSource, RenderTaskAddress, RenderTaskId, RenderTaskKind};
Expand Down Expand Up @@ -46,6 +46,7 @@ pub struct RenderTargetContext<'a> {
pub clip_scroll_tree: &'a ClipScrollTree,
pub use_dual_source_blending: bool,
pub node_data: &'a [ClipScrollNodeData],
pub cached_gradients: &'a [CachedGradient],
}

#[cfg_attr(feature = "capture", derive(Serialize))]
Expand Down

0 comments on commit 58a1de7

Please sign in to comment.