commit 2887eb088c9932216b5b457e1c23de3bef2c97fa parent 10e3952871af896f674c925a0904077d011b6b78 Author: Nicolas Silva <nical@fastmail.com> Date: Thu, 13 Nov 2025 20:41:24 +0000 Bug 1996818 - Switch the TextureCache from GpuCache to GpuBufferF. r=gw Differential Revision: https://phabricator.services.mozilla.com/D270504 Diffstat:
41 files changed, 445 insertions(+), 440 deletions(-)
diff --git a/gfx/wr/webrender/res/blend.glsl b/gfx/wr/webrender/res/blend.glsl @@ -2,6 +2,8 @@ * 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/. */ +#include gpu_buffer + #define COMPONENT_TRANSFER_IDENTITY 0 #define COMPONENT_TRANSFER_TABLE 1 #define COMPONENT_TRANSFER_DISCRETE 2 @@ -154,7 +156,7 @@ vec4 ComponentTransfer(vec4 colora, vec4 vfuncs, highp int table_address) { case COMPONENT_TRANSFER_DISCRETE: { // fetch value from lookup table k = int(floor(colora[i]*255.0 + 0.5)); - texel = fetch_from_gpu_cache_1(table_address + offset + k/4); + texel = fetch_from_gpu_buffer_1f(table_address + offset + k/4); colora[i] = clamp(texel[k % 4], 0.0, 1.0); // offset plus 256/4 blocks offset = offset + 64; @@ -162,7 +164,7 @@ vec4 ComponentTransfer(vec4 colora, vec4 vfuncs, highp int table_address) { } case COMPONENT_TRANSFER_LINEAR: { // fetch the two values for use in the linear equation - texel = fetch_from_gpu_cache_1(table_address + offset); + texel = fetch_from_gpu_buffer_1f(table_address + offset); colora[i] = clamp(texel[0] * colora[i] + texel[1], 0.0, 1.0); // offset plus 1 block offset = offset + 1; @@ -170,7 +172,7 @@ vec4 ComponentTransfer(vec4 colora, vec4 vfuncs, highp int table_address) { } case COMPONENT_TRANSFER_GAMMA: { // fetch the three values for use in the gamma equation - texel = fetch_from_gpu_cache_1(table_address + offset); + texel = fetch_from_gpu_buffer_1f(table_address + offset); colora[i] = clamp(texel[0] * pow(colora[i], texel[1]) + texel[2], 0.0, 1.0); // offset plus 1 block offset = offset + 1; diff --git a/gfx/wr/webrender/res/brush_blend.glsl b/gfx/wr/webrender/res/brush_blend.glsl @@ -5,7 +5,7 @@ #define VECS_PER_SPECIFIC_BRUSH 3 #define WR_FEATURE_TEXTURE_2D -#include shared,prim_shared,brush,blend +#include shared,prim_shared,brush,blend,image_source // Interpolated UV coordinates to sample. varying highp vec2 v_uv; diff --git a/gfx/wr/webrender/res/brush_image.glsl b/gfx/wr/webrender/res/brush_image.glsl @@ -4,7 +4,7 @@ #define VECS_PER_SPECIFIC_BRUSH 3 -#include shared,prim_shared,brush +#include shared,prim_shared,brush,image_source // Interpolated UV coordinates to sample. varying highp vec2 v_uv; diff --git a/gfx/wr/webrender/res/brush_mix_blend.glsl b/gfx/wr/webrender/res/brush_mix_blend.glsl @@ -5,7 +5,7 @@ #define VECS_PER_SPECIFIC_BRUSH 3 #define WR_FEATURE_TEXTURE_2D -#include shared,prim_shared,brush +#include shared,prim_shared,brush,image_source // UV and bounds for the source image varying highp vec2 v_src_uv; diff --git a/gfx/wr/webrender/res/brush_yuv_image.glsl b/gfx/wr/webrender/res/brush_yuv_image.glsl @@ -4,7 +4,7 @@ #define VECS_PER_SPECIFIC_BRUSH 1 -#include shared,prim_shared,brush,yuv +#include shared,prim_shared,brush,yuv,image_source varying highp vec2 vUv_Y; flat varying highp vec4 vUvBounds_Y; diff --git a/gfx/wr/webrender/res/cs_clip_box_shadow.glsl b/gfx/wr/webrender/res/cs_clip_box_shadow.glsl @@ -2,7 +2,7 @@ * 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/. */ -#include shared,clip_shared +#include shared,clip_shared,image_source varying highp vec4 vLocalPos; varying highp vec2 vUv; diff --git a/gfx/wr/webrender/res/cs_svg_filter.glsl b/gfx/wr/webrender/res/cs_svg_filter.glsl @@ -4,7 +4,7 @@ #define WR_FEATURE_TEXTURE_2D -#include shared,prim_shared +#include shared,prim_shared,gpu_buffer varying highp vec2 vInput1Uv; varying highp vec2 vInput2Uv; @@ -126,18 +126,18 @@ void main(void) { vData = ivec4(aFilterGenericInt, 0, 0, 0); break; case FILTER_FLOOD: - vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress); + vFilterData0 = fetch_from_gpu_buffer_1f_direct(aFilterExtraDataAddress); break; case FILTER_OPACITY: vFloat0.x = filter_task.user_data.x; break; case FILTER_COLOR_MATRIX: - vec4 mat_data[4] = fetch_from_gpu_cache_4_direct(aFilterExtraDataAddress); + vec4 mat_data[4] = fetch_from_gpu_buffer_4f_direct(aFilterExtraDataAddress); vColorMat = mat4(mat_data[0], mat_data[1], mat_data[2], mat_data[3]); - vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress + ivec2(4, 0)); + vFilterData0 = fetch_from_gpu_buffer_1f_direct(aFilterExtraDataAddress + ivec2(4, 0)); break; case FILTER_DROP_SHADOW: - vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress); + vFilterData0 = fetch_from_gpu_buffer_1f_direct(aFilterExtraDataAddress); break; case FILTER_OFFSET: vec2 texture_size = vec2(TEX_SIZE(sColor0).xy); @@ -154,7 +154,7 @@ void main(void) { case FILTER_COMPOSITE: vData = ivec4(aFilterGenericInt, 0, 0, 0); if (aFilterGenericInt == COMPOSITE_ARITHMETIC) { - vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress); + vFilterData0 = fetch_from_gpu_buffer_1f_direct(aFilterExtraDataAddress); } break; default: @@ -443,21 +443,21 @@ vec4 ComponentTransfer(vec4 colora) { case COMPONENT_TRANSFER_DISCRETE: // fetch value from lookup table k = int(floor(colora[i]*255.0 + 0.5)); - texel = fetch_from_gpu_cache_1_direct(vData.xy + ivec2(offset + k/4, 0)); + texel = fetch_from_gpu_buffer_1f_direct(vData.xy + ivec2(offset + k/4, 0)); colora[i] = clamp(texel[k % 4], 0.0, 1.0); // offset plus 256/4 blocks offset = offset + 64; break; case COMPONENT_TRANSFER_LINEAR: // fetch the two values for use in the linear equation - texel = fetch_from_gpu_cache_1_direct(vData.xy + ivec2(offset, 0)); + texel = fetch_from_gpu_buffer_1f_direct(vData.xy + ivec2(offset, 0)); colora[i] = clamp(texel[0] * colora[i] + texel[1], 0.0, 1.0); // offset plus 1 block offset = offset + 1; break; case COMPONENT_TRANSFER_GAMMA: // fetch the three values for use in the gamma equation - texel = fetch_from_gpu_cache_1_direct(vData.xy + ivec2(offset, 0)); + texel = fetch_from_gpu_buffer_1f_direct(vData.xy + ivec2(offset, 0)); colora[i] = clamp(texel[0] * pow(colora[i], texel[1]) + texel[2], 0.0, 1.0); // offset plus 1 block offset = offset + 1; diff --git a/gfx/wr/webrender/res/cs_svg_filter_node.glsl b/gfx/wr/webrender/res/cs_svg_filter_node.glsl @@ -38,7 +38,7 @@ Notes about specific filter kinds: #define WR_FEATURE_TEXTURE_2D -#include shared,prim_shared +#include shared,prim_shared,gpu_buffer varying highp vec2 vInput1Uv; varying highp vec2 vInput2Uv; @@ -271,9 +271,9 @@ void main(void) { break; case FILTER_COLOR_MATRIX: case FILTER_COLOR_MATRIX_CONVERTSRGB: - vec4 mat_data[4] = fetch_from_gpu_cache_4_direct(aFilterExtraDataAddress); + vec4 mat_data[4] = fetch_from_gpu_buffer_4f_direct(aFilterExtraDataAddress); vColorMat = mat4(mat_data[0], mat_data[1], mat_data[2], mat_data[3]); - vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress + ivec2(4, 0)); + vFilterData0 = fetch_from_gpu_buffer_1f_direct(aFilterExtraDataAddress + ivec2(4, 0)); break; case FILTER_COMPONENT_TRANSFER: case FILTER_COMPONENT_TRANSFER_CONVERTSRGB: @@ -282,7 +282,7 @@ void main(void) { case FILTER_COMPOSITE_ARITHMETIC: case FILTER_COMPOSITE_ARITHMETIC_CONVERTSRGB: // arithmetic parameters - vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress); + vFilterData0 = fetch_from_gpu_buffer_1f_direct(aFilterExtraDataAddress); break; case FILTER_COMPOSITE_ATOP: case FILTER_COMPOSITE_ATOP_CONVERTSRGB: @@ -326,12 +326,12 @@ void main(void) { // TODO break; case FILTER_DROP_SHADOW: - vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress); + vFilterData0 = fetch_from_gpu_buffer_1f_direct(aFilterExtraDataAddress); // premultiply the color vFilterData0.rgb = vFilterData0.rgb * vFilterData0.a; break; case FILTER_DROP_SHADOW_CONVERTSRGB: - vFilterData0 = fetch_from_gpu_cache_1_direct(aFilterExtraDataAddress); + vFilterData0 = fetch_from_gpu_buffer_1f_direct(aFilterExtraDataAddress); // convert from sRGB to linearRGB and premultiply by alpha vFilterData0.rgb = vertexSrgbToLinear(vFilterData0.rgb); vFilterData0.rgb = vFilterData0.rgb * vFilterData0.a; @@ -601,7 +601,7 @@ void main(void) { vec4 result = vec4(1.0, 0.0, 0.0, 1.0); // This would produce more efficient code for swgl if we used a switch statement. - // However, the glsl-optimizer pass produces awful code for switch statements, + // However, the glsl-optimizer pass produces awful code for switch statements, // resulting in the optimized fragment shader taking half a minute to compile on // some Adreno devices. See bug 1929209. // We should fix the optimizer to produce more sensible output for switch diff --git a/gfx/wr/webrender/res/gpu_buffer.glsl b/gfx/wr/webrender/res/gpu_buffer.glsl @@ -10,21 +10,14 @@ ivec2 get_gpu_buffer_uv(HIGHP_FS_ADDRESS int address) { uint(address) / WR_MAX_VERTEX_TEXTURE_WIDTH); } -vec4 fetch_from_gpu_buffer_1f(HIGHP_FS_ADDRESS int address) { - ivec2 uv = get_gpu_buffer_uv(address); - return texelFetch(sGpuBufferF, uv, 0); -} - -vec4[2] fetch_from_gpu_buffer_2f(HIGHP_FS_ADDRESS int address) { - ivec2 uv = get_gpu_buffer_uv(address); +vec4[2] fetch_from_gpu_buffer_2f_direct(ivec2 uv) { return vec4[2]( TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(0, 0)), TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(1, 0)) ); } -vec4[3] fetch_from_gpu_buffer_3f(HIGHP_FS_ADDRESS int address) { - ivec2 uv = get_gpu_buffer_uv(address); +vec4[3] fetch_from_gpu_buffer_3f_direct(ivec2 uv) { return vec4[3]( TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(0, 0)), TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(1, 0)), @@ -32,8 +25,7 @@ vec4[3] fetch_from_gpu_buffer_3f(HIGHP_FS_ADDRESS int address) { ); } -vec4[4] fetch_from_gpu_buffer_4f(HIGHP_FS_ADDRESS int address) { - ivec2 uv = get_gpu_buffer_uv(address); +vec4[4] fetch_from_gpu_buffer_4f_direct(ivec2 uv) { return vec4[4]( TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(0, 0)), TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(1, 0)), @@ -42,8 +34,7 @@ vec4[4] fetch_from_gpu_buffer_4f(HIGHP_FS_ADDRESS int address) { ); } -vec4[5] fetch_from_gpu_buffer_5f(HIGHP_FS_ADDRESS int address) { - ivec2 uv = get_gpu_buffer_uv(address); +vec4[5] fetch_from_gpu_buffer_5f_direct(ivec2 uv) { return vec4[5]( TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(0, 0)), TEXEL_FETCH(sGpuBufferF, uv, 0, ivec2(1, 0)), @@ -53,6 +44,35 @@ vec4[5] fetch_from_gpu_buffer_5f(HIGHP_FS_ADDRESS int address) { ); } +vec4 fetch_from_gpu_buffer_1f(HIGHP_FS_ADDRESS int address) { + ivec2 uv = get_gpu_buffer_uv(address); + return texelFetch(sGpuBufferF, uv, 0); +} + +vec4[2] fetch_from_gpu_buffer_2f(HIGHP_FS_ADDRESS int address) { + ivec2 uv = get_gpu_buffer_uv(address); + return fetch_from_gpu_buffer_2f_direct(uv); +} + +vec4[3] fetch_from_gpu_buffer_3f(HIGHP_FS_ADDRESS int address) { + ivec2 uv = get_gpu_buffer_uv(address); + return fetch_from_gpu_buffer_3f_direct(uv); +} + +vec4[4] fetch_from_gpu_buffer_4f(HIGHP_FS_ADDRESS int address) { + ivec2 uv = get_gpu_buffer_uv(address); + return fetch_from_gpu_buffer_4f_direct(uv); +} + +vec4[5] fetch_from_gpu_buffer_5f(HIGHP_FS_ADDRESS int address) { + ivec2 uv = get_gpu_buffer_uv(address); + return fetch_from_gpu_buffer_5f_direct(uv); +} + +vec4 fetch_from_gpu_buffer_1f_direct(ivec2 uv) { + return texelFetch(sGpuBufferF, uv, 0); +} + ivec4 fetch_from_gpu_buffer_1i(HIGHP_FS_ADDRESS int address) { ivec2 uv = get_gpu_buffer_uv(address); return texelFetch(sGpuBufferI, uv, 0); diff --git a/gfx/wr/webrender/res/gpu_cache.glsl b/gfx/wr/webrender/res/gpu_cache.glsl @@ -94,44 +94,4 @@ vec4[4] fetch_from_gpu_cache_4(int address) { ); } -//TODO: image resource is too specific for this module - -struct ImageSource { - RectWithEndpoint uv_rect; - vec4 user_data; -}; - -ImageSource fetch_image_source(int address) { - //Note: number of blocks has to match `renderer::BLOCKS_PER_UV_RECT` - vec4 data[2] = fetch_from_gpu_cache_2(address); - RectWithEndpoint uv_rect = RectWithEndpoint(data[0].xy, data[0].zw); - return ImageSource(uv_rect, data[1]); -} - -ImageSource fetch_image_source_direct(ivec2 address) { - vec4 data[2] = fetch_from_gpu_cache_2_direct(address); - RectWithEndpoint uv_rect = RectWithEndpoint(data[0].xy, data[0].zw); - return ImageSource(uv_rect, data[1]); -} - -// Fetch optional extra data for a texture cache resource. This can contain -// a polygon defining a UV rect within the texture cache resource. -// Note: the polygon coordinates are in homogeneous space. -struct ImageSourceExtra { - vec4 st_tl; - vec4 st_tr; - vec4 st_bl; - vec4 st_br; -}; - -ImageSourceExtra fetch_image_source_extra(int address) { - vec4 data[4] = fetch_from_gpu_cache_4(address + VECS_PER_IMAGE_RESOURCE); - return ImageSourceExtra( - data[0], - data[1], - data[2], - data[3] - ); -} - #endif //WR_VERTEX_SHADER diff --git a/gfx/wr/webrender/res/gradient.glsl b/gfx/wr/webrender/res/gradient.glsl @@ -2,7 +2,7 @@ * 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/. */ -#include dithering +#include dithering,gpu_buffer // Gradient GPU cache address. // Packed in to a vector to work around bug 1630356. diff --git a/gfx/wr/webrender/res/image_source.glsl b/gfx/wr/webrender/res/image_source.glsl @@ -0,0 +1,49 @@ +/* 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/. */ + +#include gpu_buffer + +#ifdef WR_VERTEX_SHADER + +#include rect + +struct ImageSource { + RectWithEndpoint uv_rect; + vec4 user_data; +}; + +ImageSource fetch_image_source(int address) { + //Note: number of blocks has to match `renderer::BLOCKS_PER_UV_RECT` + vec4 data[2] = fetch_from_gpu_buffer_2f(address); + RectWithEndpoint uv_rect = RectWithEndpoint(data[0].xy, data[0].zw); + return ImageSource(uv_rect, data[1]); +} + +ImageSource fetch_image_source_direct(ivec2 address) { + vec4 data[2] = fetch_from_gpu_buffer_2f_direct(address); + RectWithEndpoint uv_rect = RectWithEndpoint(data[0].xy, data[0].zw); + return ImageSource(uv_rect, data[1]); +} + +// Fetch optional extra data for a texture cache resource. This can contain +// a polygon defining a UV rect within the texture cache resource. +// Note: the polygon coordinates are in homogeneous space. +struct ImageSourceExtra { + vec4 st_tl; + vec4 st_tr; + vec4 st_bl; + vec4 st_br; +}; + +ImageSourceExtra fetch_image_source_extra(int address) { + vec4 data[4] = fetch_from_gpu_buffer_4f(address + VECS_PER_IMAGE_RESOURCE); + return ImageSourceExtra( + data[0], + data[1], + data[2], + data[3] + ); +} + +#endif // WR_VERTEX_SHADER diff --git a/gfx/wr/webrender/res/prim_shared.glsl b/gfx/wr/webrender/res/prim_shared.glsl @@ -2,7 +2,7 @@ * 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/. */ -#include rect,render_task,gpu_cache,transform +#include rect,render_task,gpu_cache,transform,image_source #define EXTEND_MODE_CLAMP 0 #define EXTEND_MODE_REPEAT 1 diff --git a/gfx/wr/webrender/res/ps_split_composite.glsl b/gfx/wr/webrender/res/ps_split_composite.glsl @@ -4,7 +4,7 @@ #define WR_FEATURE_TEXTURE_2D -#include shared,prim_shared +#include shared,prim_shared,image_source // interpolated UV coordinates to sample. varying highp vec2 vUv; diff --git a/gfx/wr/webrender/res/ps_text_run.glsl b/gfx/wr/webrender/res/ps_text_run.glsl @@ -2,7 +2,7 @@ * 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/. */ -#include shared,prim_shared +#include shared,prim_shared,gpu_buffer flat varying mediump vec4 v_color; flat varying mediump vec3 v_mask_swizzle; @@ -60,7 +60,7 @@ struct GlyphResource { }; GlyphResource fetch_glyph_resource(int address) { - vec4 data[2] = fetch_from_gpu_cache_2(address); + vec4 data[2] = fetch_from_gpu_buffer_2f(address); return GlyphResource(data[0], data[1].xy, data[1].z); } diff --git a/gfx/wr/webrender/src/batch.rs b/gfx/wr/webrender/src/batch.rs @@ -12,7 +12,7 @@ use crate::pattern::PatternKind; use crate::spatial_tree::{SpatialTree, SpatialNodeIndex, CoordinateSystemId}; use glyph_rasterizer::{GlyphFormat, SubpixelDirection}; use crate::gpu_cache::{GpuBlockData, GpuCache, GpuCacheAddress}; -use crate::gpu_types::{BrushFlags, BrushInstance, PrimitiveHeaders, ZBufferId, ZBufferIdGenerator}; +use crate::gpu_types::{BrushFlags, BrushInstance, ImageSource, PrimitiveHeaders, UvRectKind, ZBufferId, ZBufferIdGenerator}; use crate::gpu_types::SplitCompositeInstance; use crate::gpu_types::{PrimitiveInstanceData, RasterizationSpace, GlyphInstance}; use crate::gpu_types::{PrimitiveHeader, PrimitiveHeaderIndex, TransformPaletteId, TransformPalette}; @@ -1085,7 +1085,7 @@ impl BatchBuilder { let (uv_rect_address, texture) = render_tasks.resolve_location( pic_task_id, - gpu_cache, + ).unwrap(); // The set of input textures that most composite modes use, @@ -1147,7 +1147,7 @@ impl BatchBuilder { let shadow_textures = textures; let content_uv_rect_address = render_tasks[secondary_id] - .get_texture_address(gpu_cache) + .get_texture_address() .as_int(); // Build BatchTextures for shadow/content @@ -1297,7 +1297,7 @@ impl BatchBuilder { filter_data.data.b_func.to_int() << 20 | filter_data.data.a_func.to_int() << 16) as i32); - let user_data = filter_data.gpu_cache_handle.as_int(gpu_cache); + let user_data = filter_data.gpu_buffer_address.as_int(); let key = BatchKey::new( BatchKind::Brush(BrushBatchKind::Blend), @@ -1384,8 +1384,8 @@ impl BatchBuilder { clip_mask: clip_mask_texture_id, }, ); - let src_uv_address = render_tasks[pic_task_id].get_texture_address(gpu_cache); - let readback_uv_address = render_tasks[backdrop_id].get_texture_address(gpu_cache); + let src_uv_address = render_tasks[pic_task_id].get_texture_address(); + let readback_uv_address = render_tasks[backdrop_id].get_texture_address(); let prim_header = PrimitiveHeader { user_data: [ mode as u32 as i32, @@ -1653,7 +1653,7 @@ impl BatchBuilder { }; if let Some((src_color, visible_tiles_range, brush_segments)) = img_brush_data { - let src_color = render_tasks.resolve_location(src_color, gpu_cache); + let src_color = render_tasks.resolve_location(src_color); let (uv_rect_address, texture_source) = match src_color { Some(src) => src, @@ -1809,7 +1809,7 @@ impl BatchBuilder { // task for each valid edge / corner of the border. for task_id in task_ids { - if let Some((uv_rect_address, texture)) = render_tasks.resolve_location(*task_id, gpu_cache) { + if let Some((uv_rect_address, texture)) = render_tasks.resolve_location(*task_id) { segment_data.push( SegmentInstanceData { textures: TextureSet::prim_textured(texture), @@ -1910,7 +1910,6 @@ impl BatchBuilder { font, &glyph_keys, &mut self.glyph_fetch_buffer, - gpu_cache, |texture_id, glyph_format, glyphs| { debug_assert_ne!(texture_id, TextureSource::Invalid); @@ -2088,7 +2087,7 @@ impl BatchBuilder { let (batch_kind, textures, prim_user_data, specific_resource_address) = match render_task { Some(task_id) => { - let (uv_rect_address, texture) = render_tasks.resolve_location(*task_id, gpu_cache).unwrap(); + let (uv_rect_address, texture) = render_tasks.resolve_location(*task_id).unwrap(); let textures = BatchTextures::prim_textured( texture, clip_mask_texture_id, @@ -2201,7 +2200,7 @@ impl BatchBuilder { debug_assert!(channel_count <= 3); for channel in 0 .. channel_count { - let src_channel = render_tasks.resolve_location(yuv_image_data.src_yuv[channel], gpu_cache); + let src_channel = render_tasks.resolve_location(yuv_image_data.src_yuv[channel]); let (uv_rect_address, texture_source) = match src_channel { Some(src) => src, @@ -2313,7 +2312,7 @@ impl BatchBuilder { } } - let src_color = render_tasks.resolve_location(image_instance.src_color, gpu_cache); + let src_color = render_tasks.resolve_location(image_instance.src_color); let (uv_rect_address, texture_source) = match src_color { Some(src) => src, @@ -2406,7 +2405,7 @@ impl BatchBuilder { let prim_header_index = prim_headers.push(&prim_header); for (i, tile) in chunk.iter().enumerate() { - let (uv_rect_address, texture) = match render_tasks.resolve_location(tile.src_color, gpu_cache) { + let (uv_rect_address, texture) = match render_tasks.resolve_location(tile.src_color) { Some(result) => result, None => { return; @@ -2533,10 +2532,7 @@ impl BatchBuilder { let kind = BatchKind::Brush( BrushBatchKind::Image(ImageBufferKind::Texture2D) ); - let (_, texture) = render_tasks.resolve_location( - pic_task_id, - gpu_cache, - ).unwrap(); + let (_, texture) = render_tasks.resolve_location(pic_task_id).unwrap(); let textures = BatchTextures::prim_textured( texture, clip_mask_texture_id, @@ -2596,23 +2592,19 @@ impl BatchBuilder { calculate_screen_uv(points[3].unwrap() * pic_info.device_pixel_scale, backdrop_rect), ]; - // TODO (gw): This is a hack that provides the GPU cache blocks for an - // ImageSource. We should update the GPU cache interfaces to - // allow pushing per-frame blocks via a request interface. - let gpu_blocks = &[ - GpuBlockData::from([ - target_rect.min.x as f32, - target_rect.min.y as f32, - target_rect.max.x as f32, - target_rect.max.y as f32, - ]), - GpuBlockData::from([0.0; 4]), - GpuBlockData::from(uvs[0]), - GpuBlockData::from(uvs[1]), - GpuBlockData::from(uvs[2]), - GpuBlockData::from(uvs[3]), - ]; - let uv_rect_handle = gpu_cache.push_per_frame_blocks(gpu_blocks); + let source = ImageSource { + p0: target_rect.min.to_f32(), + p1: target_rect.max.to_f32(), + user_data: [0.0; 4], + uv_rect_kind: UvRectKind::Quad { + top_left: uvs[0], + top_right: uvs[1], + bottom_left: uvs[2], + bottom_right: uvs[3], + }, + }; + + let uv_rect_address = source.write_gpu_blocks(&mut gpu_buffer_builder.f32); self.add_brush_instance_to_batches( key, @@ -2624,7 +2616,7 @@ impl BatchBuilder { clip_task_address, brush_flags, prim_header_index, - uv_rect_handle.as_int(gpu_cache), + uv_rect_address.as_int(), ); } } @@ -3157,7 +3149,6 @@ impl ClipBatcher { clip_node_range: ClipNodeRange, root_spatial_node_index: SpatialNodeIndex, render_tasks: &RenderTaskGraph, - gpu_cache: &GpuCache, clip_store: &ClipStore, transforms: &mut TransformPalette, actual_rect: DeviceRect, @@ -3202,7 +3193,7 @@ impl ClipBatcher { let task_id = source .render_task .expect("bug: render task handle not allocated"); - let (uv_rect_address, texture) = render_tasks.resolve_location(task_id, gpu_cache).unwrap(); + let (uv_rect_address, texture) = render_tasks.resolve_location(task_id).unwrap(); self.get_batch_list(is_first_clip) .box_shadows diff --git a/gfx/wr/webrender/src/clip.rs b/gfx/wr/webrender/src/clip.rs @@ -98,9 +98,9 @@ use api::units::*; use crate::image_tiling::{self, Repetition}; use crate::border::{ensure_no_corner_overlap, BorderRadiusAu}; use crate::box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowClipSource, BoxShadowCacheKey}; +use crate::renderer::GpuBufferBuilderF; use crate::spatial_tree::{SpatialTree, SpatialNodeIndex}; use crate::ellipse::Ellipse; -use crate::gpu_cache::GpuCache; use crate::gpu_types::{BoxShadowStretchMode}; use crate::intern; use crate::internal_types::{FastHashMap, FastHashSet, LayoutPrimitiveInfo}; @@ -1092,7 +1092,7 @@ impl ClipNodeInfo { &self, node: &ClipNode, clipped_rect: &LayoutRect, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, resource_cache: &mut ResourceCache, mask_tiles: &mut Vec<VisibleMaskImageTile>, spatial_tree: &SpatialTree, @@ -1158,7 +1158,7 @@ impl ClipNodeInfo { if request_resources { resource_cache.request_image( req, - gpu_cache, + gpu_buffer, ); } @@ -1176,7 +1176,7 @@ impl ClipNodeInfo { visible_tiles = Some(tile_range_start..mask_tiles.len()); } else { if request_resources { - resource_cache.request_image(request, gpu_cache); + resource_cache.request_image(request, gpu_buffer); } let tile_range_start = mask_tiles.len(); @@ -1499,7 +1499,7 @@ impl ClipStore { prim_to_pic_mapper: &SpaceMapper<LayoutPixel, PicturePixel>, pic_to_vis_mapper: &SpaceMapper<PicturePixel, VisPixel>, spatial_tree: &SpatialTree, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, resource_cache: &mut ResourceCache, device_pixel_scale: DevicePixelScale, culling_rect: &VisRect, @@ -1567,7 +1567,7 @@ impl ClipStore { if let Some(instance) = node_info.create_instance( node, &local_bounding_rect, - gpu_cache, + gpu_buffer, resource_cache, &mut self.mask_tiles, spatial_tree, diff --git a/gfx/wr/webrender/src/composite.rs b/gfx/wr/webrender/src/composite.rs @@ -6,8 +6,8 @@ use api::{BorderRadius, ColorF, ExternalImageId, ImageBufferKind, ImageKey, Imag use api::units::*; use api::ColorDepth; use crate::image_source::resolve_image; +use crate::renderer::GpuBufferBuilderF; use euclid::Box2D; -use crate::gpu_cache::GpuCache; use crate::gpu_types::{ZBufferId, ZBufferIdGenerator}; use crate::internal_types::{FrameAllocator, FrameMemory, FrameVec, TextureSource}; use crate::picture::{ImageDependency, ResolvedSurfaceTexture, TileCacheInstance, TileId, TileSurface}; @@ -854,7 +854,7 @@ impl CompositeState { is_opaque: bool, device_clip_rect: DeviceRect, resource_cache: &ResourceCache, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, deferred_resolves: &mut FrameVec<DeferredResolve>, clip_index: Option<CompositorClipIndex>, ) { @@ -905,7 +905,7 @@ impl CompositeState { &image_dependencies, required_plane_count, resource_cache, - gpu_cache, + gpu_buffer, deferred_resolves, ); if external_surface_index == ResolvedExternalSurfaceIndex::INVALID { @@ -967,7 +967,7 @@ impl CompositeState { tile_cache: &TileCacheInstance, device_clip_rect: DeviceRect, resource_cache: &ResourceCache, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, deferred_resolves: &mut FrameVec<DeferredResolve>, ) { let slice_transform = self.get_compositor_transform(tile_cache.transform_index); @@ -983,7 +983,7 @@ impl CompositeState { tile_cache.compositor_clip, backdrop_surface.device_rect, ); - + // Use the backdrop native surface we created and add that to the composite state. self.descriptor.surfaces.push( CompositeSurfaceDescriptor { @@ -1006,7 +1006,7 @@ impl CompositeState { true, device_clip_rect, resource_cache, - gpu_cache, + gpu_buffer, deferred_resolves, tile_cache.compositor_clip, ); @@ -1092,7 +1092,7 @@ impl CompositeState { compositor_surface.is_opaque, device_clip_rect, resource_cache, - gpu_cache, + gpu_buffer, deferred_resolves, tile_cache.compositor_clip, ); @@ -1136,7 +1136,7 @@ impl CompositeState { image_dependencies: &[ImageDependency; 3], required_plane_count: usize, resource_cache: &ResourceCache, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, deferred_resolves: &mut FrameVec<DeferredResolve>, ) -> ResolvedExternalSurfaceIndex { let mut planes = [ @@ -1156,7 +1156,7 @@ impl CompositeState { let cache_item = resolve_image( request, resource_cache, - gpu_cache, + gpu_buffer, deferred_resolves, true, ); @@ -1801,7 +1801,7 @@ impl Occluders { occluders: memory.new_vec(), scratch: OccludersScratchBuffers { events: memory.new_vec(), - active: memory.new_vec(), + active: memory.new_vec(), } } } diff --git a/gfx/wr/webrender/src/filterdata.rs b/gfx/wr/webrender/src/filterdata.rs @@ -3,9 +3,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use std::hash; -use crate::gpu_cache::{GpuCache, GpuCacheHandle}; -use crate::gpu_cache::GpuDataRequest; use crate::intern; +use crate::renderer::{GpuBufferAddress, GpuBufferBuilderF, GpuBufferWriterF}; use api::ComponentTransferFuncType; @@ -109,14 +108,14 @@ impl intern::InternDebug for SFilterDataKey {} #[derive(MallocSizeOf)] pub struct SFilterDataTemplate { pub data: SFilterData, - pub gpu_cache_handle: GpuCacheHandle, + pub gpu_buffer_address: GpuBufferAddress, } impl From<SFilterDataKey> for SFilterDataTemplate { fn from(item: SFilterDataKey) -> Self { SFilterDataTemplate { data: item.data, - gpu_cache_handle: GpuCacheHandle::new(), + gpu_buffer_address: GpuBufferAddress::INVALID, } } } @@ -129,12 +128,14 @@ impl SFilterData { && self.a_func == SFilterDataComponent::Identity } - pub fn update(&self, mut request: GpuDataRequest) { - push_component_transfer_data(&self.r_func, &mut request); - push_component_transfer_data(&self.g_func, &mut request); - push_component_transfer_data(&self.b_func, &mut request); - push_component_transfer_data(&self.a_func, &mut request); + pub fn write_gpu_blocks(&self, gpu_buffer: &mut GpuBufferBuilderF) -> GpuBufferAddress { assert!(!self.is_identity()); + let mut writer = gpu_buffer.write_blocks(1024); + push_component_transfer_data(&self.r_func, &mut writer); + push_component_transfer_data(&self.g_func, &mut writer); + push_component_transfer_data(&self.b_func, &mut writer); + push_component_transfer_data(&self.a_func, &mut writer); + writer.finish() } } @@ -143,13 +144,11 @@ impl SFilterDataTemplate { /// times per frame, by each primitive reference that refers to this interned /// template. The initial request call to the GPU cache ensures that work is only /// done if the cache entry is invalid (due to first use or eviction). - pub fn update( + pub fn write_gpu_blocks( &mut self, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, ) { - if let Some(request) = gpu_cache.request(&mut self.gpu_cache_handle) { - self.data.update(request); - } + self.gpu_buffer_address = self.data.write_gpu_blocks(gpu_buffer); } } @@ -166,7 +165,7 @@ impl intern::Internable for FilterDataIntern { fn push_component_transfer_data( func_comp: &SFilterDataComponent, - request: &mut GpuDataRequest, + writer: &mut GpuBufferWriterF, ) { match func_comp { SFilterDataComponent::Identity => {} @@ -205,14 +204,14 @@ fn push_component_transfer_data( } } - request.push(arr); + writer.push_one(arr); } } SFilterDataComponent::Linear(a, b) => { - request.push([*a, *b, 0.0, 0.0]); + writer.push_one([*a, *b, 0.0, 0.0]); } SFilterDataComponent::Gamma(a, b, c) => { - request.push([*a, *b, *c, 0.0]); + writer.push_one([*a, *b, *c, 0.0]); } } } diff --git a/gfx/wr/webrender/src/frame_builder.rs b/gfx/wr/webrender/src/frame_builder.rs @@ -396,6 +396,7 @@ impl FrameBuilder { clip_store: &mut scene.clip_store, resource_cache, gpu_cache, + frame_gpu_data, data_stores, clip_tree: &mut scene.clip_tree, composite_state, @@ -456,6 +457,7 @@ impl FrameBuilder { clip_store: &mut scene.clip_store, resource_cache, gpu_cache, + frame_gpu_data, data_stores, clip_tree: &mut scene.clip_tree, composite_state, @@ -631,7 +633,7 @@ impl FrameBuilder { profile_marker!("BlockOnResources"); resource_cache.block_until_all_resources_added( - gpu_cache, + frame_gpu_data, profile, ); } @@ -666,7 +668,7 @@ impl FrameBuilder { profile.set(profiler::PICTURE_CACHE_SLICES, scene.tile_cache_config.picture_cache_slice_count); scratch.begin_frame(); gpu_cache.begin_frame(stamp); - resource_cache.begin_frame(stamp, gpu_cache, profile); + resource_cache.begin_frame(stamp, profile); // TODO(gw): Follow up patches won't clear this, as they'll be assigned // statically during scene building. @@ -735,7 +737,7 @@ impl FrameBuilder { // Finish creating the frame graph and build it. let render_tasks = rg_builder.end_frame( resource_cache, - gpu_cache, + &mut gpu_buffer_builder, &mut deferred_resolves, scene.config.max_shared_surface_size, &frame_memory, @@ -821,7 +823,7 @@ impl FrameBuilder { self.build_composite_pass( scene, &mut ctx, - gpu_cache, + &mut gpu_buffer_builder, &mut deferred_resolves, &mut composite_state, ); @@ -1006,7 +1008,7 @@ impl FrameBuilder { &self, scene: &BuiltScene, ctx: &RenderTargetContext, - gpu_cache: &mut GpuCache, + gpu_buffers: &mut GpuBufferBuilder, deferred_resolves: &mut FrameVec<DeferredResolve>, composite_state: &mut CompositeState, ) { @@ -1034,7 +1036,7 @@ impl FrameBuilder { tile_cache, device_clip_rect, ctx.resource_cache, - gpu_cache, + &mut gpu_buffers.f32, deferred_resolves, ); } @@ -1093,7 +1095,6 @@ pub fn build_render_pass( target.add_task( *task_id, ctx, - gpu_cache, gpu_buffer_builder, render_tasks, clip_store, @@ -1118,7 +1119,6 @@ pub fn build_render_pass( target.add_task( *task_id, ctx, - gpu_cache, gpu_buffer_builder, render_tasks, clip_store, @@ -1256,7 +1256,6 @@ pub fn build_render_pass( texture.add_task( *task_id, ctx, - gpu_cache, gpu_buffer_builder, render_tasks, clip_store, diff --git a/gfx/wr/webrender/src/gpu_cache.rs b/gfx/wr/webrender/src/gpu_cache.rs @@ -854,16 +854,6 @@ impl GpuCache { } } - // Reserve space in the cache for per-frame blocks that - // will be resolved by the render thread via the - // external image callback. - pub fn push_deferred_per_frame_blocks(&mut self, block_count: usize) -> GpuCacheHandle { - let location = self.texture.push_data(None, block_count, self.now); - GpuCacheHandle { - location: Some(location), - } - } - /// End the frame. Return the list of updates to apply to the /// device specific cache texture. pub fn end_frame( diff --git a/gfx/wr/webrender/src/gpu_types.rs b/gfx/wr/webrender/src/gpu_types.rs @@ -4,15 +4,16 @@ use api::{AlphaType, PremultipliedColorF, YuvFormat, YuvRangedColorSpace}; use api::units::*; +use euclid::HomogeneousVector; use crate::composite::{CompositeFeatures, CompositorClip}; use crate::segment::EdgeAaSegmentMask; use crate::spatial_tree::{SpatialTree, SpatialNodeIndex}; -use crate::gpu_cache::{GpuCacheAddress, GpuDataRequest}; +use crate::gpu_cache::GpuCacheAddress; use crate::internal_types::{FastHashMap, FrameVec, FrameMemory}; use crate::prim_store::ClipData; use crate::render_task::RenderTaskAddress; use crate::render_task_graph::RenderTaskId; -use crate::renderer::{ShaderColorMode, GpuBufferAddress}; +use crate::renderer::{GpuBufferAddress, GpuBufferBuilderF, GpuBufferWriterF, ShaderColorMode}; use std::i32; use crate::util::{MatrixHelpers, TransformedRectKind}; use glyph_rasterizer::SubpixelDirection; @@ -172,7 +173,7 @@ pub struct SvgFilterInstance { pub input_count: u16, pub generic_int: u16, pub padding: u16, - pub extra_data_address: GpuCacheAddress, + pub extra_data_address: GpuBufferAddress, } #[derive(Clone, Debug)] @@ -187,7 +188,7 @@ pub struct SVGFEFilterInstance { pub input_2_task_address: RenderTaskAddress, pub kind: u16, pub input_count: u16, - pub extra_data_address: GpuCacheAddress, + pub extra_data_address: GpuBufferAddress, } #[derive(Copy, Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)] @@ -261,7 +262,7 @@ pub struct BoxShadowData { #[repr(C)] pub struct ClipMaskInstanceBoxShadow { pub common: ClipMaskInstanceCommon, - pub resource_address: GpuCacheAddress, + pub resource_address: GpuBufferAddress, pub shadow_data: BoxShadowData, } @@ -571,7 +572,7 @@ impl GlyphInstance { clip_task: RenderTaskAddress, subpx_dir: SubpixelDirection, glyph_index_in_text_run: i32, - glyph_uv_rect: GpuCacheAddress, + glyph_uv_rect: GpuBufferAddress, color_mode: ShaderColorMode, ) -> PrimitiveInstanceData { PrimitiveInstanceData { @@ -1006,25 +1007,34 @@ pub struct ImageSource { } impl ImageSource { - pub fn write_gpu_blocks(&self, request: &mut GpuDataRequest) { + pub fn write_gpu_blocks(&self, gpu_buffer: &mut GpuBufferBuilderF) -> GpuBufferAddress { + let mut writer = gpu_buffer.write_blocks(6); + self.push_gpu_blocks(&mut writer); + writer.finish() + } + + pub fn push_gpu_blocks(&self, writer: &mut GpuBufferWriterF) { // see fetch_image_resource in GLSL // has to be VECS_PER_IMAGE_RESOURCE vectors - request.push([ + writer.push_one([ self.p0.x, self.p0.y, self.p1.x, self.p1.y, ]); - request.push(self.user_data); + writer.push_one(self.user_data); // If this is a polygon uv kind, then upload the four vertices. if let UvRectKind::Quad { top_left, top_right, bottom_left, bottom_right } = self.uv_rect_kind { // see fetch_image_resource_extra in GLSL //Note: we really need only 3 components per point here: X, Y, and W - request.push(top_left); - request.push(top_right); - request.push(bottom_left); - request.push(bottom_right); + fn to_array(v: HomogeneousVector<f32, DevicePixel>) -> [f32; 4] { + [v.x, v.y, v.z, v.w] + } + writer.push_one(to_array(top_left)); + writer.push_one(to_array(top_right)); + writer.push_one(to_array(bottom_left)); + writer.push_one(to_array(bottom_right)); } } } diff --git a/gfx/wr/webrender/src/image_source.rs b/gfx/wr/webrender/src/image_source.rs @@ -11,10 +11,10 @@ use crate::api::ExternalImageType; use crate::api::units::*; -use crate::gpu_cache::GpuCache; use crate::prim_store::DeferredResolve; use crate::renderer::BLOCKS_PER_UV_RECT; use crate::render_task_cache::RenderTaskCacheEntryHandle; +use crate::renderer::GpuBufferBuilderF; use crate::resource_cache::{ResourceCache, ImageRequest, CacheItem}; use crate::internal_types::{TextureSource, TextureSourceExternal, DeferredResolveIndex, FrameVec}; @@ -22,7 +22,7 @@ use crate::internal_types::{TextureSource, TextureSourceExternal, DeferredResolv pub fn resolve_image( request: ImageRequest, resource_cache: &ResourceCache, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, deferred_resolves: &mut FrameVec<DeferredResolve>, is_composited: bool, ) -> CacheItem { @@ -35,7 +35,7 @@ pub fn resolve_image( // This is an external texture - we will add it to // the deferred resolves list to be patched by // the render thread... - let cache_handle = gpu_cache.push_deferred_per_frame_blocks(BLOCKS_PER_UV_RECT); + let uv_rect_address = gpu_buffer.reserve_renderer_deferred_blocks(BLOCKS_PER_UV_RECT); let deferred_resolve_index = DeferredResolveIndex(deferred_resolves.len() as u32); @@ -56,7 +56,7 @@ pub fn resolve_image( kind: image_buffer_kind, normalized_uvs: external_image.normalized_uvs, }), - uv_rect_handle: cache_handle, + uv_rect_handle: uv_rect_address, uv_rect: DeviceIntRect::from_size( image_properties.descriptor.size, ), @@ -65,7 +65,7 @@ pub fn resolve_image( deferred_resolves.push(DeferredResolve { image_properties, - address: gpu_cache.get_address(&cache_handle), + address: uv_rect_address, rendering: request.rendering, is_composited, }); diff --git a/gfx/wr/webrender/src/picture.rs b/gfx/wr/webrender/src/picture.rs @@ -2194,7 +2194,7 @@ impl TileCacheInstance { &map_local_to_picture, &pic_to_vis_mapper, frame_context.spatial_tree, - frame_state.gpu_cache, + &mut frame_state.frame_gpu_data.f32, frame_state.resource_cache, frame_context.global_device_pixel_scale, &surface.culling_rect, @@ -2726,7 +2726,7 @@ impl TileCacheInstance { api_keys: &[ImageKey; 3], resource_cache: &mut ResourceCache, composite_state: &mut CompositeState, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, image_rendering: ImageRendering, color_depth: ColorDepth, color_space: YuvRangedColorSpace, @@ -2741,7 +2741,7 @@ impl TileCacheInstance { rendering: image_rendering, tile: None, }, - gpu_cache, + gpu_buffer, ); } } @@ -2782,7 +2782,7 @@ impl TileCacheInstance { api_key: ImageKey, resource_cache: &mut ResourceCache, composite_state: &mut CompositeState, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, image_rendering: ImageRendering, is_opaque: bool, surface_kind: CompositorSurfaceKind, @@ -2801,7 +2801,7 @@ impl TileCacheInstance { rendering: image_rendering, tile: None, }, - gpu_cache, + gpu_buffer, ); self.setup_compositor_surfaces_impl( @@ -3147,7 +3147,7 @@ impl TileCacheInstance { color_bindings: &ColorBindingStorage, surface_stack: &[(PictureIndex, SurfaceIndex)], composite_state: &mut CompositeState, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, scratch: &mut PrimitiveScratchBuffer, is_root_tile_cache: bool, surfaces: &mut [SurfaceInfo], @@ -3391,7 +3391,7 @@ impl TileCacheInstance { image_data.key, resource_cache, composite_state, - gpu_cache, + gpu_buffer, image_data.image_rendering, is_opaque, kind, @@ -3509,7 +3509,7 @@ impl TileCacheInstance { &prim_data.kind.yuv_key, resource_cache, composite_state, - gpu_cache, + gpu_buffer, prim_data.kind.image_rendering, prim_data.kind.color_depth, prim_data.kind.color_space.with_range(prim_data.kind.color_range), @@ -5510,7 +5510,7 @@ impl PicturePrimitive { if let Some(TileSurface::Texture { descriptor, .. }) = tile.surface.as_ref() { if let SurfaceTextureDescriptor::TextureCache { handle: Some(handle), .. } = descriptor { frame_state.resource_cache - .picture_textures.request(handle, frame_state.gpu_cache); + .picture_textures.request(handle, &mut frame_state.frame_gpu_data.f32); } } @@ -5546,7 +5546,7 @@ impl PicturePrimitive { // TODO(gw): Consider switching to manual eviction policy? frame_state.resource_cache .picture_textures - .request(handle.as_ref().unwrap(), frame_state.gpu_cache); + .request(handle.as_ref().unwrap(), &mut frame_state.frame_gpu_data.f32); } else { // If the texture was evicted on a previous frame, we need to assume // that the entire tile rect is dirty. @@ -5603,7 +5603,7 @@ impl PicturePrimitive { frame_state.resource_cache.picture_textures.update( tile_cache.current_tile_size, handle, - frame_state.gpu_cache, + &mut frame_state.frame_gpu_data.f32, &mut frame_state.resource_cache.texture_cache.next_id, &mut frame_state.resource_cache.texture_cache.pending_updates, ); @@ -6613,11 +6613,11 @@ impl PicturePrimitive { &self.snapshot, &surface_rects, false, - &mut|rg_builder, _, gpu_cache| { + &mut|rg_builder, gpu_buffer, _| { RenderTask::new_svg_filter_graph( filters, rg_builder, - gpu_cache, + gpu_buffer, data_stores, surface_rects.uv_rect_kind, picture_task_id, @@ -7323,7 +7323,7 @@ impl PicturePrimitive { } PictureCompositeMode::ComponentTransferFilter(handle) => { let filter_data = &mut data_stores.filter_data[handle]; - filter_data.update(&mut frame_state.gpu_cache); + filter_data.write_gpu_blocks(&mut frame_state.frame_gpu_data.f32); } PictureCompositeMode::MixBlend(..) | PictureCompositeMode::Blit(_) | @@ -7335,7 +7335,7 @@ impl PicturePrimitive { match op { FilterGraphOp::SVGFEComponentTransferInterned { handle, creates_pixels: _ } => { let filter_data = &mut data_stores.filter_data[*handle]; - filter_data.update(&mut frame_state.gpu_cache); + filter_data.write_gpu_blocks(&mut frame_state.frame_gpu_data.f32); } _ => {} } diff --git a/gfx/wr/webrender/src/picture_textures.rs b/gfx/wr/webrender/src/picture_textures.rs @@ -13,8 +13,8 @@ use crate::internal_types::{ }; use crate::profiler::{self, TransactionProfile}; use crate::gpu_types::{ImageSource, UvRectKind}; -use crate::gpu_cache::{GpuCache, GpuCacheHandle}; use crate::freelist::{FreeList, FreeListHandle, WeakFreeListHandle}; +use crate::renderer::{GpuBufferAddress, GpuBufferBuilderF}; #[derive(Debug, PartialEq)] @@ -42,24 +42,23 @@ pub struct PictureCacheEntry { // in the glyph cache eviction code. We could probably remove it // entirely in future (or move to EntryDetails::Picture). pub last_access: FrameStamp, - /// Handle to the resource rect in the GPU cache. - pub uv_rect_handle: GpuCacheHandle, + /// Handle to the resource rect in the float GPU buffer. + pub uv_rect_handle: GpuBufferAddress, /// The actual device texture ID this is part of. pub texture_id: CacheTextureId, } impl PictureCacheEntry { - fn update_gpu_cache(&mut self, gpu_cache: &mut GpuCache) { - if let Some(mut request) = gpu_cache.request(&mut self.uv_rect_handle) { - let origin = DeviceIntPoint::zero(); - let image_source = ImageSource { - p0: origin.to_f32(), - p1: (origin + self.size).to_f32(), - uv_rect_kind: UvRectKind::Rect, - user_data: [0.0; 4], - }; - image_source.write_gpu_blocks(&mut request); - } + fn write_gpu_blocks(&mut self, gpu_buffer: &mut GpuBufferBuilderF) { + let origin = DeviceIntPoint::zero(); + let image_source = ImageSource { + p0: origin.to_f32(), + p1: (origin + self.size).to_f32(), + uv_rect_kind: UvRectKind::Rect, + user_data: [0.0; 4], + }; + + self.uv_rect_handle = image_source.write_gpu_blocks(gpu_buffer); } } @@ -130,7 +129,7 @@ impl PictureTextures { &mut self, tile_size: DeviceIntSize, handle: &mut Option<PictureCacheTextureHandle>, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, next_texture_id: &mut CacheTextureId, pending_updates: &mut TextureUpdateList, ) { @@ -160,7 +159,7 @@ impl PictureTextures { self.cache_entries .get_opt_mut(handle) .expect("BUG: handle must be valid now") - .update_gpu_cache(gpu_cache); + .write_gpu_blocks(gpu_buffer); } else { panic!("The handle should be valid picture cache handle now") } @@ -219,7 +218,7 @@ impl PictureTextures { let cache_entry = PictureCacheEntry { size: tile_size, last_access: self.now, - uv_rect_handle: GpuCacheHandle::new(), + uv_rect_handle: GpuBufferAddress::INVALID, texture_id, }; @@ -264,14 +263,14 @@ impl PictureTextures { } } - pub fn request(&mut self, handle: &PictureCacheTextureHandle, gpu_cache: &mut GpuCache) -> bool { + pub fn request(&mut self, handle: &PictureCacheTextureHandle, gpu_buffer: &mut GpuBufferBuilderF) -> bool { let entry = self.cache_entries.get_opt_mut(handle); let now = self.now; entry.map_or(true, |entry| { // If an image is requested that is already in the cache, // refresh the GPU cache data associated with this item. entry.last_access = now; - entry.update_gpu_cache(gpu_cache); + entry.write_gpu_blocks(gpu_buffer); false }) } diff --git a/gfx/wr/webrender/src/prepare.rs b/gfx/wr/webrender/src/prepare.rs @@ -514,7 +514,7 @@ fn prepare_interned_prim_for_render( allow_subpixel, frame_context.fb_config.low_quality_pinch_zoom, frame_state.resource_cache, - frame_state.gpu_cache, + &mut frame_state.frame_gpu_data.f32, frame_context.spatial_tree, scratch, ); @@ -1476,7 +1476,7 @@ fn update_clip_task_for_brush( &pic_state.map_local_to_pic, &pic_state.map_pic_to_vis, &frame_context.spatial_tree, - frame_state.gpu_cache, + &mut frame_state.frame_gpu_data.f32, frame_state.resource_cache, device_pixel_scale, &dirty_rect, diff --git a/gfx/wr/webrender/src/prim_store/borders.rs b/gfx/wr/webrender/src/prim_store/borders.rs @@ -256,7 +256,7 @@ impl ImageBorderData { let size = frame_state.resource_cache.request_image( self.request, - frame_state.gpu_cache, + &mut frame_state.frame_gpu_data.f32, ); let task_id = frame_state.rg_builder.add().init( diff --git a/gfx/wr/webrender/src/prim_store/image.rs b/gfx/wr/webrender/src/prim_store/image.rs @@ -10,9 +10,10 @@ use api::{ use api::units::*; use euclid::point2; use crate::composite::CompositorSurfaceKind; +use crate::renderer::GpuBufferBuilderF; use crate::scene_building::{CreateShadow, IsVisible}; use crate::frame_builder::{FrameBuildingContext, FrameBuildingState}; -use crate::gpu_cache::{GpuCache, GpuDataRequest}; +use crate::gpu_cache::{GpuDataRequest}; use crate::intern::{Internable, InternDebug, Handle as InternHandle}; use crate::internal_types::LayoutPrimitiveInfo; use crate::prim_store::{ @@ -192,7 +193,7 @@ impl ImageData { let mut size = frame_state.resource_cache.request_image( request, - frame_state.gpu_cache, + &mut frame_state.frame_gpu_data.f32, ); let mut task_id = frame_state.rg_builder.add().init( @@ -357,7 +358,7 @@ impl ImageData { let request = request.with_tile(tile.offset); let size = frame_state.resource_cache.request_image( request, - frame_state.gpu_cache, + &mut frame_state.frame_gpu_data.f32, ); let task_id = frame_state.rg_builder.add().init( @@ -673,7 +674,7 @@ impl YuvImageData { let size = frame_state.resource_cache.request_image( request, - frame_state.gpu_cache, + &mut frame_state.frame_gpu_data.f32, ); let task_id = frame_state.rg_builder.add().init( @@ -698,7 +699,7 @@ impl YuvImageData { pub fn request_resources( &mut self, resource_cache: &mut ResourceCache, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, ) { let channel_num = self.format.get_plane_num(); debug_assert!(channel_num <= 3); @@ -709,7 +710,7 @@ impl YuvImageData { rendering: self.image_rendering, tile: None, }, - gpu_cache, + gpu_buffer, ); } } diff --git a/gfx/wr/webrender/src/prim_store/mod.rs b/gfx/wr/webrender/src/prim_store/mod.rs @@ -13,6 +13,7 @@ use crate::composite::CompositorSurfaceKind; use crate::clip::ClipLeafId; use crate::pattern::{Pattern, PatternBuilder, PatternBuilderContext, PatternBuilderState}; use crate::quad::QuadTileClassifier; +use crate::renderer::GpuBufferAddress; use crate::segment::EdgeAaSegmentMask; use crate::border::BorderSegmentCacheKey; use crate::debug_item::{DebugItem, DebugMessage}; @@ -20,7 +21,7 @@ use crate::debug_colors; use crate::scene_building::{CreateShadow, IsVisible}; use crate::frame_builder::FrameBuildingState; use glyph_rasterizer::GlyphKey; -use crate::gpu_cache::{GpuCacheAddress, GpuCacheHandle, GpuDataRequest}; +use crate::gpu_cache::{GpuCacheHandle, GpuDataRequest}; use crate::gpu_types::{BrushFlags, QuadSegment}; use crate::intern; use crate::picture::PicturePrimitive; @@ -90,7 +91,7 @@ impl PrimitiveOpacity { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct DeferredResolve { - pub address: GpuCacheAddress, + pub address: GpuBufferAddress, pub image_properties: ImageProperties, pub rendering: ImageRendering, pub is_composited: bool, diff --git a/gfx/wr/webrender/src/prim_store/text_run.rs b/gfx/wr/webrender/src/prim_store/text_run.rs @@ -8,13 +8,12 @@ use api::units::*; use crate::scene_building::{CreateShadow, IsVisible}; use crate::frame_builder::FrameBuildingState; use glyph_rasterizer::{FontInstance, FontTransform, GlyphKey, FONT_SIZE_LIMIT}; -use crate::gpu_cache::GpuCache; use crate::intern; use crate::internal_types::LayoutPrimitiveInfo; use crate::picture::SurfaceInfo; use crate::prim_store::{PrimitiveOpacity, PrimitiveScratchBuffer}; use crate::prim_store::{PrimitiveStore, PrimKeyCommonData, PrimTemplateCommonData}; -use crate::renderer::MAX_VERTEX_TEXTURE_WIDTH; +use crate::renderer::{GpuBufferBuilderF, MAX_VERTEX_TEXTURE_WIDTH}; use crate::resource_cache::ResourceCache; use crate::util::MatrixHelpers; use crate::prim_store::{InternablePrimitive, PrimitiveInstanceKind, LayoutPointAu}; @@ -466,7 +465,7 @@ impl TextRunPrimitive { allow_subpixel: bool, low_quality_pinch_zoom: bool, resource_cache: &mut ResourceCache, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, spatial_tree: &SpatialTree, scratch: &mut PrimitiveScratchBuffer, ) { @@ -507,7 +506,7 @@ impl TextRunPrimitive { resource_cache.request_glyphs( self.used_font.clone(), &scratch.glyph_keys[self.glyph_keys_range], - gpu_cache, + gpu_buffer, ); } } diff --git a/gfx/wr/webrender/src/render_target.rs b/gfx/wr/webrender/src/render_target.rs @@ -13,7 +13,7 @@ use crate::segment::EdgeAaSegmentMask; use crate::spatial_tree::SpatialTree; use crate::clip::{ClipStore, ClipItemKind}; use crate::frame_builder::FrameGlobalResources; -use crate::gpu_cache::{GpuCache, GpuCacheAddress}; +use crate::gpu_cache::GpuCache; use crate::gpu_types::{BorderInstance, SvgFilterInstance, SVGFEFilterInstance, BlurDirection, BlurInstance, PrimitiveHeaders, ScalingInstance}; use crate::gpu_types::{TransformPalette, ZBufferIdGenerator, MaskInstance, ClipSpace, BlurEdgeMode}; use crate::gpu_types::{ZBufferId, QuadSegment, PrimitiveInstanceData, TransformPaletteId}; @@ -354,7 +354,6 @@ impl RenderTarget { &mut self, task_id: RenderTaskId, ctx: &RenderTargetContext, - gpu_cache: &mut GpuCache, gpu_buffer_builder: &mut GpuBufferBuilder, render_tasks: &RenderTaskGraph, clip_store: &ClipStore, @@ -444,7 +443,7 @@ impl RenderTarget { task_id, task.children.get(0).cloned(), task.children.get(1).cloned(), - task_info.extra_gpu_cache_handle.map(|handle| gpu_cache.get_address(&handle)), + task_info.extra_gpu_data, &ctx.frame_memory, ) } @@ -456,7 +455,7 @@ impl RenderTarget { task, task.children.get(0).cloned(), task.children.get(1).cloned(), - task_info.extra_gpu_cache_handle.map(|handle| gpu_cache.get_address(&handle)), + task_info.extra_gpu_data, &ctx.frame_memory, ) } @@ -471,7 +470,6 @@ impl RenderTarget { task_info.clip_node_range, task_info.root_spatial_node_index, render_tasks, - gpu_cache, clip_store, transforms, task_info.actual_rect, @@ -682,7 +680,7 @@ fn add_svg_filter_instances( task_id: RenderTaskId, input_1_task: Option<RenderTaskId>, input_2_task: Option<RenderTaskId>, - extra_data_address: Option<GpuCacheAddress>, + extra_data_address: Option<GpuBufferAddress>, memory: &FrameMemory, ) { let mut textures = BatchTextures::empty(); @@ -753,7 +751,7 @@ fn add_svg_filter_instances( input_count, generic_int, padding: 0, - extra_data_address: extra_data_address.unwrap_or(GpuCacheAddress::INVALID), + extra_data_address: extra_data_address.unwrap_or(GpuBufferAddress::INVALID), }; for (ref mut batch_textures, ref mut batch) in instances.iter_mut() { @@ -786,7 +784,7 @@ fn add_svg_filter_node_instances( target_task: &RenderTask, input_1_task: Option<RenderTaskId>, input_2_task: Option<RenderTaskId>, - extra_data_address: Option<GpuCacheAddress>, + extra_data_address: Option<GpuBufferAddress>, memory: &FrameMemory, ) { let node = &task_info.node; @@ -808,7 +806,7 @@ fn add_svg_filter_node_instances( input_2_task_address: RenderTaskId::INVALID.into(), kind: 0, input_count: node.inputs.len() as u16, - extra_data_address: extra_data_address.unwrap_or(GpuCacheAddress::INVALID), + extra_data_address: extra_data_address.unwrap_or(GpuBufferAddress::INVALID), }; // Must match FILTER_* in cs_svg_filter_node.glsl diff --git a/gfx/wr/webrender/src/render_task.rs b/gfx/wr/webrender/src/render_task.rs @@ -15,7 +15,7 @@ use crate::profiler::{add_text_marker}; use crate::spatial_tree::SpatialNodeIndex; use crate::filterdata::SFilterData; use crate::frame_builder::FrameBuilderConfig; -use crate::gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle}; +use crate::gpu_cache::GpuCache; use crate::gpu_types::{BorderInstance, ImageSource, UvRectKind, TransformPaletteId, BlurEdgeMode}; use crate::internal_types::{CacheTextureId, FastHashMap, FilterGraphNode, FilterGraphOp, FilterGraphPictureReference, SVGFE_CONVOLVE_VALUES_LIMIT, TextureSource, Swizzle}; use crate::picture::{ResolvedSurfaceTexture, MAX_SURFACE_SIZE}; @@ -26,7 +26,7 @@ use crate::prim_store::gradient::{ }; use crate::resource_cache::{ResourceCache, ImageRequest}; use std::{usize, f32, i32, u32}; -use crate::renderer::{GpuBufferAddress, GpuBufferBuilderF}; +use crate::renderer::{GpuBufferAddress, GpuBufferBuilder, GpuBufferBuilderF}; use crate::render_backend::DataStores; use crate::render_target::{ResolveOp, RenderTargetKind}; use crate::render_task_graph::{PassId, RenderTaskId, RenderTaskGraphBuilder}; @@ -346,7 +346,7 @@ pub enum SvgFilterInfo { #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct SvgFilterTask { pub info: SvgFilterInfo, - pub extra_gpu_cache_handle: Option<GpuCacheHandle>, + pub extra_gpu_data: Option<GpuBufferAddress>, } #[derive(Debug)] @@ -356,7 +356,7 @@ pub struct SVGFEFilterTask { pub node: FilterGraphNode, pub op: FilterGraphOp, pub content_origin: DevicePoint, - pub extra_gpu_cache_handle: Option<GpuCacheHandle>, + pub extra_gpu_data: Option<GpuBufferAddress>, } #[cfg_attr(feature = "capture", derive(Serialize))] @@ -850,38 +850,32 @@ impl RenderTaskKind { pub fn write_gpu_blocks( &mut self, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilder, ) { match self { RenderTaskKind::SvgFilter(ref mut filter_task) => { match filter_task.info { SvgFilterInfo::ColorMatrix(ref matrix) => { - let handle = filter_task.extra_gpu_cache_handle.get_or_insert_with(GpuCacheHandle::new); - if let Some(mut request) = gpu_cache.request(handle) { - for i in 0..5 { - request.push([matrix[i*4], matrix[i*4+1], matrix[i*4+2], matrix[i*4+3]]); - } + let mut writer = gpu_buffer.f32.write_blocks(5); + for i in 0..5 { + writer.push_one([matrix[i*4], matrix[i*4+1], matrix[i*4+2], matrix[i*4+3]]); } + filter_task.extra_gpu_data = Some(writer.finish()); } SvgFilterInfo::DropShadow(color) | SvgFilterInfo::Flood(color) => { - let handle = filter_task.extra_gpu_cache_handle.get_or_insert_with(GpuCacheHandle::new); - if let Some(mut request) = gpu_cache.request(handle) { - request.push(color.to_array()); - } + let mut writer = gpu_buffer.f32.write_blocks(1); + writer.push_one(color.to_array()); + filter_task.extra_gpu_data = Some(writer.finish()); } SvgFilterInfo::ComponentTransfer(ref data) => { - let handle = filter_task.extra_gpu_cache_handle.get_or_insert_with(GpuCacheHandle::new); - if let Some(request) = gpu_cache.request(handle) { - data.update(request); - } + filter_task.extra_gpu_data = Some(data.write_gpu_blocks(&mut gpu_buffer.f32)); } SvgFilterInfo::Composite(ref operator) => { if let CompositeOperator::Arithmetic(k_vals) = operator { - let handle = filter_task.extra_gpu_cache_handle.get_or_insert_with(GpuCacheHandle::new); - if let Some(mut request) = gpu_cache.request(handle) { - request.push(*k_vals); - } + let mut writer = gpu_buffer.f32.write_blocks(1); + writer.push_one(*k_vals); + filter_task.extra_gpu_data = Some(writer.finish()); } } _ => {}, @@ -905,21 +899,19 @@ impl RenderTaskKind { FilterGraphOp::SVGFEBlendSaturation => {} FilterGraphOp::SVGFEBlendColor => {} FilterGraphOp::SVGFEBlendLuminosity => {} - FilterGraphOp::SVGFEColorMatrix{values: matrix} => { - let handle = filter_task.extra_gpu_cache_handle.get_or_insert_with(GpuCacheHandle::new); - if let Some(mut request) = gpu_cache.request(handle) { - for i in 0..5 { - request.push([matrix[i*4], matrix[i*4+1], matrix[i*4+2], matrix[i*4+3]]); - } + FilterGraphOp::SVGFEColorMatrix { values: matrix } => { + let mut writer = gpu_buffer.f32.write_blocks(5); + for i in 0..5 { + writer.push_one([matrix[i*4], matrix[i*4+1], matrix[i*4+2], matrix[i*4+3]]); } + filter_task.extra_gpu_data = Some(writer.finish()); } FilterGraphOp::SVGFEComponentTransfer => unreachable!(), FilterGraphOp::SVGFEComponentTransferInterned{..} => {} FilterGraphOp::SVGFECompositeArithmetic{k1, k2, k3, k4} => { - let handle = filter_task.extra_gpu_cache_handle.get_or_insert_with(GpuCacheHandle::new); - if let Some(mut request) = gpu_cache.request(handle) { - request.push([k1, k2, k3, k4]); - } + let mut writer = gpu_buffer.f32.write_blocks(1); + writer.push_one([k1, k2, k3, k4]); + filter_task.extra_gpu_data = Some(writer.finish()); } FilterGraphOp::SVGFECompositeATop => {} FilterGraphOp::SVGFECompositeIn => {} @@ -930,44 +922,40 @@ impl RenderTaskKind { FilterGraphOp::SVGFEConvolveMatrixEdgeModeDuplicate{order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha} | FilterGraphOp::SVGFEConvolveMatrixEdgeModeNone{order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha} | FilterGraphOp::SVGFEConvolveMatrixEdgeModeWrap{order_x, order_y, kernel, divisor, bias, target_x, target_y, kernel_unit_length_x, kernel_unit_length_y, preserve_alpha} => { - let handle = filter_task.extra_gpu_cache_handle.get_or_insert_with(GpuCacheHandle::new); - if let Some(mut request) = gpu_cache.request(handle) { - request.push([-target_x as f32, -target_y as f32, order_x as f32, order_y as f32]); - request.push([kernel_unit_length_x as f32, kernel_unit_length_y as f32, 1.0 / divisor, bias]); - assert!(SVGFE_CONVOLVE_VALUES_LIMIT == 25); - request.push([kernel[0], kernel[1], kernel[2], kernel[3]]); - request.push([kernel[4], kernel[5], kernel[6], kernel[7]]); - request.push([kernel[8], kernel[9], kernel[10], kernel[11]]); - request.push([kernel[12], kernel[13], kernel[14], kernel[15]]); - request.push([kernel[16], kernel[17], kernel[18], kernel[19]]); - request.push([kernel[20], 0.0, 0.0, preserve_alpha as f32]); - } + let mut writer = gpu_buffer.f32.write_blocks(8); + assert!(SVGFE_CONVOLVE_VALUES_LIMIT == 25); + writer.push_one([-target_x as f32, -target_y as f32, order_x as f32, order_y as f32]); + writer.push_one([kernel_unit_length_x as f32, kernel_unit_length_y as f32, 1.0 / divisor, bias]); + writer.push_one([kernel[0], kernel[1], kernel[2], kernel[3]]); + writer.push_one([kernel[4], kernel[5], kernel[6], kernel[7]]); + writer.push_one([kernel[8], kernel[9], kernel[10], kernel[11]]); + writer.push_one([kernel[12], kernel[13], kernel[14], kernel[15]]); + writer.push_one([kernel[16], kernel[17], kernel[18], kernel[19]]); + writer.push_one([kernel[20], 0.0, 0.0, preserve_alpha as f32]); + filter_task.extra_gpu_data = Some(writer.finish()); } FilterGraphOp::SVGFEDiffuseLightingDistant{..} => {} FilterGraphOp::SVGFEDiffuseLightingPoint{..} => {} FilterGraphOp::SVGFEDiffuseLightingSpot{..} => {} FilterGraphOp::SVGFEDisplacementMap{scale, x_channel_selector, y_channel_selector} => { - let handle = filter_task.extra_gpu_cache_handle.get_or_insert_with(GpuCacheHandle::new); - if let Some(mut request) = gpu_cache.request(handle) { - request.push([x_channel_selector as f32, y_channel_selector as f32, scale, 0.0]); - } - } - FilterGraphOp::SVGFEDropShadow{color, ..} | - FilterGraphOp::SVGFEFlood{color} => { - let handle = filter_task.extra_gpu_cache_handle.get_or_insert_with(GpuCacheHandle::new); - if let Some(mut request) = gpu_cache.request(handle) { - request.push(color.to_array()); - } + let mut writer = gpu_buffer.f32.write_blocks(1); + writer.push_one([x_channel_selector as f32, y_channel_selector as f32, scale, 0.0]); + filter_task.extra_gpu_data = Some(writer.finish()); } + FilterGraphOp::SVGFEDropShadow { color, .. } | + FilterGraphOp::SVGFEFlood { color } => { + let mut writer = gpu_buffer.f32.write_blocks(1); + writer.push_one(color.to_array()); + filter_task.extra_gpu_data = Some(writer.finish()); + } FilterGraphOp::SVGFEGaussianBlur{..} => {} FilterGraphOp::SVGFEIdentity => {} - FilterGraphOp::SVGFEImage{..} => {} - FilterGraphOp::SVGFEMorphologyDilate{radius_x, radius_y} | - FilterGraphOp::SVGFEMorphologyErode{radius_x, radius_y} => { - let handle = filter_task.extra_gpu_cache_handle.get_or_insert_with(GpuCacheHandle::new); - if let Some(mut request) = gpu_cache.request(handle) { - request.push([radius_x, radius_y, 0.0, 0.0]); - } + FilterGraphOp::SVGFEImage {..} => {} + FilterGraphOp::SVGFEMorphologyDilate { radius_x, radius_y } | + FilterGraphOp::SVGFEMorphologyErode { radius_x, radius_y } => { + let mut writer = gpu_buffer.f32.write_blocks(1); + writer.push_one([radius_x, radius_y, 0.0, 0.0]); + filter_task.extra_gpu_data = Some(writer.finish()); } FilterGraphOp::SVGFEOpacity{..} => {} FilterGraphOp::SVGFESourceAlpha => {} @@ -1053,7 +1041,7 @@ pub struct RenderTask { /// /// Will be set to None if the render task is cached, in which case the texture cache /// manages the handle. - pub uv_rect_handle: GpuCacheHandle, + pub uv_rect_handle: GpuBufferAddress, pub cache_handle: Option<RenderTaskCacheEntryHandle>, uv_rect_kind: UvRectKind, } @@ -1071,7 +1059,7 @@ impl RenderTask { kind, free_after: PassId::MAX, render_on: PassId::MIN, - uv_rect_handle: GpuCacheHandle::new(), + uv_rect_handle: GpuBufferAddress::INVALID, uv_rect_kind: UvRectKind::Rect, cache_handle: None, sub_pass: None, @@ -1116,7 +1104,7 @@ impl RenderTask { }), free_after: PassId::MAX, render_on: PassId::MIN, - uv_rect_handle: GpuCacheHandle::new(), + uv_rect_handle: GpuBufferAddress::INVALID, uv_rect_kind: UvRectKind::Rect, cache_handle: None, sub_pass: None, @@ -1135,7 +1123,7 @@ impl RenderTask { kind: RenderTaskKind::Test(target), free_after: PassId::MAX, render_on: PassId::MIN, - uv_rect_handle: GpuCacheHandle::new(), + uv_rect_handle: GpuBufferAddress::INVALID, uv_rect_kind: UvRectKind::Rect, cache_handle: None, sub_pass: None, @@ -1635,7 +1623,7 @@ impl RenderTask { let task_id = rg_builder.add().init(RenderTask::new_dynamic( target_size, RenderTaskKind::SvgFilter(SvgFilterTask { - extra_gpu_cache_handle: None, + extra_gpu_data: None, info, }), ).with_uv_rect_kind(uv_rect_kind)); @@ -1665,7 +1653,7 @@ impl RenderTask { pub fn new_svg_filter_graph( filter_nodes: &[(FilterGraphNode, FilterGraphOp)], rg_builder: &mut RenderTaskGraphBuilder, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, data_stores: &mut DataStores, _uv_rect_kind: UvRectKind, original_task_id: RenderTaskId, @@ -2367,7 +2355,7 @@ impl RenderTask { }, op: FilterGraphOp::SVGFEIdentity, content_origin: DevicePoint::zero(), - extra_gpu_cache_handle: None, + extra_gpu_data: None, } ), ).with_uv_rect_kind(UvRectKind::Rect)); @@ -2411,7 +2399,7 @@ impl RenderTask { }, op: FilterGraphOp::SVGFEIdentity, content_origin: node_task_rect.min, - extra_gpu_cache_handle: None, + extra_gpu_data: None, } ), ).with_uv_rect_kind(node_uv_rect_kind)); @@ -2497,7 +2485,7 @@ impl RenderTask { }, op: FilterGraphOp::SVGFEIdentity, content_origin: node_task_rect.min, - extra_gpu_cache_handle: None, + extra_gpu_data: None, } ), ).with_uv_rect_kind(UvRectKind::Rect)); @@ -2552,7 +2540,7 @@ impl RenderTask { std_deviation_x: 0.0, std_deviation_y: 0.0, }, content_origin: node_task_rect.min, - extra_gpu_cache_handle: None, + extra_gpu_data: None, } ), ).with_uv_rect_kind(node_uv_rect_kind)); @@ -2590,7 +2578,7 @@ impl RenderTask { }, op: op.clone(), content_origin: source_subregion.min.cast_unit(), - extra_gpu_cache_handle: None, + extra_gpu_data: None, } ), ).with_uv_rect_kind(node_uv_rect_kind)); @@ -2601,13 +2589,13 @@ impl RenderTask { // FIXME: Doing this in prepare_interned_prim_for_render // doesn't seem to be enough, where should it be done? let filter_data = &mut data_stores.filter_data[handle]; - filter_data.update(gpu_cache); - // ComponentTransfer has a gpu_cache_handle that we need to + filter_data.write_gpu_blocks(gpu_buffer); + // ComponentTransfer has a gpu buffer address that we need to // pass along task_id = rg_builder.add().init(RenderTask::new_dynamic( node_task_size, RenderTaskKind::SVGFENode( - SVGFEFilterTask{ + SVGFEFilterTask { node: FilterGraphNode{ kept_by_optimizer: true, linear: node.linear, @@ -2617,7 +2605,7 @@ impl RenderTask { }, op: op.clone(), content_origin: node_task_rect.min, - extra_gpu_cache_handle: Some(filter_data.gpu_cache_handle), + extra_gpu_data: Some(filter_data.gpu_buffer_address), } ), ).with_uv_rect_kind(node_uv_rect_kind)); @@ -2649,7 +2637,7 @@ impl RenderTask { }, op: op.clone(), content_origin: node_task_rect.min, - extra_gpu_cache_handle: None, + extra_gpu_data: None, } ), ).with_uv_rect_kind(node_uv_rect_kind)); @@ -2690,8 +2678,8 @@ impl RenderTask { self.uv_rect_kind } - pub fn get_texture_address(&self, gpu_cache: &GpuCache) -> GpuCacheAddress { - gpu_cache.get_address(&self.uv_rect_handle) + pub fn get_texture_address(&self) -> GpuBufferAddress { + self.uv_rect_handle } pub fn get_target_texture(&self) -> CacheTextureId { @@ -2773,11 +2761,11 @@ impl RenderTask { pub fn write_gpu_blocks( &mut self, target_rect: DeviceIntRect, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilder, ) { profile_scope!("write_gpu_blocks"); - self.kind.write_gpu_blocks(gpu_cache); + self.kind.write_gpu_blocks(gpu_buffer); if self.cache_handle.is_some() { // The uv rect handle of cached render tasks is requested and set by the @@ -2785,17 +2773,16 @@ impl RenderTask { return; } - if let Some(mut request) = gpu_cache.request(&mut self.uv_rect_handle) { - let p0 = target_rect.min.to_f32(); - let p1 = target_rect.max.to_f32(); - let image_source = ImageSource { - p0, - p1, - user_data: [0.0; 4], - uv_rect_kind: self.uv_rect_kind, - }; - image_source.write_gpu_blocks(&mut request); - } + let p0 = target_rect.min.to_f32(); + let p1 = target_rect.max.to_f32(); + let image_source = ImageSource { + p0, + p1, + user_data: [0.0; 4], + uv_rect_kind: self.uv_rect_kind, + }; + + self.uv_rect_handle = image_source.write_gpu_blocks(&mut gpu_buffer.f32); } /// Called by the render task cache. diff --git a/gfx/wr/webrender/src/render_task_cache.rs b/gfx/wr/webrender/src/render_task_cache.rs @@ -165,7 +165,7 @@ impl RenderTaskCache { size: DeviceIntSize, render_task: &mut RenderTask, entry: &mut RenderTaskCacheEntry, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, texture_cache: &mut TextureCache, ) { // Find out what size to alloc in the texture cache. @@ -199,7 +199,7 @@ impl RenderTaskCache { None, entry.user_data.unwrap_or([0.0; 4]), DirtyRect::All, - gpu_cache, + gpu_buffer, None, render_task.uv_rect_kind(), Eviction::Auto, @@ -309,7 +309,7 @@ impl RenderTaskCache { cache_entry.frame_id = self.frame_id; // Check if this texture cache handle is valid. - if texture_cache.request(&cache_entry.handle, gpu_cache) { + if texture_cache.request(&cache_entry.handle, gpu_buffer_builder) { // Invoke user closure to get render task chain // to draw this into the texture cache. let render_task_id = f(rg_builder, gpu_buffer_builder, gpu_cache); @@ -328,7 +328,7 @@ impl RenderTaskCache { task_size, render_task, cache_entry, - gpu_cache, + gpu_buffer_builder, texture_cache, ); } diff --git a/gfx/wr/webrender/src/render_task_graph.rs b/gfx/wr/webrender/src/render_task_graph.rs @@ -9,12 +9,13 @@ use api::units::*; use api::ImageFormat; -use crate::gpu_cache::{GpuCache, GpuCacheAddress}; use crate::internal_types::{TextureSource, CacheTextureId, FastHashMap, FastHashSet, FrameId}; use crate::internal_types::size_of_frame_vec; use crate::render_task::{StaticRenderTaskSurface, RenderTaskLocation, RenderTask}; use crate::render_target::RenderTargetKind; use crate::render_task::{RenderTaskData, RenderTaskKind}; +use crate::renderer::GpuBufferAddress; +use crate::renderer::GpuBufferBuilder; use crate::resource_cache::ResourceCache; use crate::texture_pack::GuillotineAllocator; use crate::prim_store::DeferredResolve; @@ -280,7 +281,7 @@ impl RenderTaskGraphBuilder { pub fn end_frame( &mut self, resource_cache: &mut ResourceCache, - gpu_cache: &mut GpuCache, + gpu_buffers: &mut GpuBufferBuilder, deferred_resolves: &mut FrameVec<DeferredResolve>, max_shared_surface_size: i32, memory: &FrameMemory, @@ -630,7 +631,7 @@ impl RenderTaskGraphBuilder { Some(resolve_image( info.request, resource_cache, - gpu_cache, + &mut gpu_buffers.f32, deferred_resolves, info.is_composited, )) @@ -660,7 +661,7 @@ impl RenderTaskGraphBuilder { task.write_gpu_blocks( target_rect, - gpu_cache, + gpu_buffers, ); graph.task_data.push( @@ -723,16 +724,14 @@ impl RenderTaskGraph { pub fn resolve_location( &self, task_id: impl Into<Option<RenderTaskId>>, - gpu_cache: &GpuCache, - ) -> Option<(GpuCacheAddress, TextureSource)> { - self.resolve_impl(task_id.into()?, gpu_cache) + ) -> Option<(GpuBufferAddress, TextureSource)> { + self.resolve_impl(task_id.into()?) } fn resolve_impl( &self, task_id: RenderTaskId, - gpu_cache: &GpuCache, - ) -> Option<(GpuCacheAddress, TextureSource)> { + ) -> Option<(GpuBufferAddress, TextureSource)> { let task = &self[task_id]; let texture_source = task.get_texture_source(); @@ -740,7 +739,7 @@ impl RenderTaskGraph { return None; } - let uv_address = task.get_texture_address(gpu_cache); + let uv_address = task.get_texture_address(); Some((uv_address, texture_source)) } diff --git a/gfx/wr/webrender/src/renderer/gpu_buffer.rs b/gfx/wr/webrender/src/renderer/gpu_buffer.rs @@ -336,6 +336,22 @@ impl<T> GpuBufferBuilderImpl<T> where T: Texel + std::convert::From<DeviceIntRec ) } + // Reserve space in the gpu buffer for data that will be written by the + // renderer. + pub fn reserve_renderer_deferred_blocks(&mut self, block_count: usize) -> GpuBufferAddress { + let index = self.data.len(); + + self.data.reserve(block_count); + for _ in 0 ..block_count { + self.data.push(Default::default()); + } + + GpuBufferAddress { + u: (index % MAX_VERTEX_TEXTURE_WIDTH) as u16, + v: (index / MAX_VERTEX_TEXTURE_WIDTH) as u16, + } + } + pub fn finalize( mut self, render_tasks: &RenderTaskGraph, diff --git a/gfx/wr/webrender/src/renderer/gpu_cache.rs b/gfx/wr/webrender/src/renderer/gpu_cache.rs @@ -9,7 +9,6 @@ use crate::{ device::{CustomVAO, Device, DrawTarget, Program, ReadTarget, Texture, TextureFilter, UploadPBOPool, VBO}, gpu_cache::{GpuBlockData, GpuCacheUpdate, GpuCacheUpdateList}, internal_types::{FrameId, RenderTargetInfo, Swizzle}, - prim_store::DeferredResolve, profiler, render_api::MemoryReport, }; @@ -484,10 +483,7 @@ impl super::Renderer { self.profile.set(profiler::GPU_CACHE_BLOCKS_UPDATED, updated_blocks); } - pub fn prepare_gpu_cache( - &mut self, - deferred_resolves: &[DeferredResolve], - ) -> Result<(), super::RendererError> { + pub fn prepare_gpu_cache(&mut self) -> Result<(), super::RendererError> { self.profile.start_time(profiler::GPU_CACHE_PREPARE_TIME); if self.pending_gpu_cache_clear { @@ -505,9 +501,6 @@ impl super::Renderer { self.pending_gpu_cache_clear = false; } - let deferred_update_list = self.update_deferred_resolves(deferred_resolves); - self.pending_gpu_cache_updates.extend(deferred_update_list); - self.update_gpu_cache(); // Note: the texture might have changed during the `update`, diff --git a/gfx/wr/webrender/src/renderer/mod.rs b/gfx/wr/webrender/src/renderer/mod.rs @@ -70,7 +70,7 @@ use crate::device::FBOId; use crate::debug_item::DebugItem; use crate::frame_builder::Frame; use glyph_rasterizer::GlyphFormat; -use crate::gpu_cache::{GpuCacheUpdate, GpuCacheUpdateList}; +use crate::gpu_cache::GpuCacheUpdateList; use crate::gpu_cache::{GpuCacheDebugChunk, GpuCacheDebugCmd}; use crate::gpu_types::{ScalingInstance, SvgFilterInstance, SVGFEFilterInstance, CopyInstance, PrimitiveInstanceData}; use crate::gpu_types::{BlurInstance, ClearInstance, CompositeInstance, ZBufferId}; @@ -1748,7 +1748,9 @@ impl Renderer { "Cleared texture cache without sending new document frame."); } - match self.prepare_gpu_cache(&frame.deferred_resolves) { + self.update_deferred_resolves(&frame.deferred_resolves, &mut frame.gpu_buffer_f); + + match self.prepare_gpu_cache() { Ok(..) => { assert!(frame.gpu_cache_frame_id <= self.gpu_cache_frame_id, "Received frame depends on a later GPU cache epoch ({:?}) than one we received last via `UpdateGpuCache` ({:?})", @@ -4945,28 +4947,23 @@ impl Renderer { } } - fn update_deferred_resolves(&mut self, deferred_resolves: &[DeferredResolve]) -> Option<GpuCacheUpdateList> { + fn update_deferred_resolves( + &mut self, + deferred_resolves: &[DeferredResolve], + gpu_buffer: &mut GpuBufferF, + ) { // The first thing we do is run through any pending deferred // resolves, and use a callback to get the UV rect for this // custom item. Then we patch the resource_rects structure // here before it's uploaded to the GPU. if deferred_resolves.is_empty() { - return None; + return; } let handler = self.external_image_handler .as_mut() .expect("Found external image, but no handler set!"); - let mut list = GpuCacheUpdateList { - frame_id: FrameId::INVALID, - clear: false, - height: self.gpu_cache_texture.get_height(), - blocks: Vec::new(), - updates: Vec::new(), - debug_commands: Vec::new(), - }; - for (i, deferred_resolve) in deferred_resolves.iter().enumerate() { self.gpu_profiler.place_marker("deferred resolve"); let props = &deferred_resolve.image_properties; @@ -5019,16 +5016,11 @@ impl Renderer { .external_images .insert(DeferredResolveIndex(i as u32), texture); - list.updates.push(GpuCacheUpdate::Copy { - block_index: list.blocks.len(), - block_count: BLOCKS_PER_UV_RECT, - address: deferred_resolve.address, - }); - list.blocks.push(image.uv.into()); - list.blocks.push([0f32; 4].into()); + let addr = deferred_resolve.address; + let index = addr.u as usize + addr.v as usize * MAX_VERTEX_TEXTURE_WIDTH; + gpu_buffer.data[index] = image.uv.to_array().into(); + gpu_buffer.data[index + 1] = [0f32; 4].into(); } - - Some(list) } fn unlock_external_images( diff --git a/gfx/wr/webrender/src/resource_cache.rs b/gfx/wr/webrender/src/resource_cache.rs @@ -27,7 +27,7 @@ use crate::glyph_cache::{GlyphCache, CachedGlyphInfo}; use crate::glyph_cache::GlyphCacheEntry; use glyph_rasterizer::{GLYPH_FLASHING, FontInstance, GlyphFormat, GlyphKey, GlyphRasterizer, GlyphRasterJob}; use glyph_rasterizer::{SharedFontResources, BaseFontInstance}; -use crate::gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle}; +use crate::gpu_cache::GpuCache; use crate::gpu_types::UvRectKind; use crate::internal_types::{ CacheTextureId, FastHashMap, FastHashSet, TextureSource, ResourceUpdateList, @@ -37,7 +37,7 @@ use crate::profiler::{self, TransactionProfile, bytes_to_mb}; use crate::render_task_graph::{RenderTaskId, RenderTaskGraphBuilder}; use crate::render_task_cache::{RenderTaskCache, RenderTaskCacheKey, RenderTaskParent}; use crate::render_task_cache::{RenderTaskCacheEntry, RenderTaskCacheEntryHandle}; -use crate::renderer::GpuBufferBuilderF; +use crate::renderer::{GpuBufferAddress, GpuBufferBuilder, GpuBufferBuilderF}; use crate::surface::SurfaceBuilder; use euclid::point2; use smallvec::SmallVec; @@ -64,7 +64,7 @@ static NEXT_NATIVE_SURFACE_ID: AtomicUsize = AtomicUsize::new(0); #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct GlyphFetchResult { pub index_in_text_run: i32, - pub uv_rect_address: GpuCacheAddress, + pub uv_rect_address: GpuBufferAddress, pub offset: DevicePoint, pub size: DeviceIntSize, pub scale: f32, @@ -84,7 +84,7 @@ pub struct GlyphFetchResult { #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct CacheItem { pub texture_id: TextureSource, - pub uv_rect_handle: GpuCacheHandle, + pub uv_rect_handle: GpuBufferAddress, pub uv_rect: DeviceIntRect, pub user_data: [f32; 4], } @@ -93,7 +93,7 @@ impl CacheItem { pub fn invalid() -> Self { CacheItem { texture_id: TextureSource::Invalid, - uv_rect_handle: GpuCacheHandle::new(), + uv_rect_handle: GpuBufferAddress::INVALID, uv_rect: DeviceIntRect::zero(), user_data: [0.0; 4], } @@ -727,7 +727,7 @@ impl ResourceCache { None, user_data, DirtyRect::All, - gpu_cache, + gpu_buffer_builder, None, render_task.uv_rect_kind(), Eviction::Manual, @@ -1101,7 +1101,7 @@ impl ResourceCache { pub fn request_image( &mut self, mut request: ImageRequest, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, ) -> DeviceIntSize { debug_assert_eq!(self.state, State::AddResources); @@ -1202,7 +1202,7 @@ impl ResourceCache { ImageResult::Err(_) => panic!("Errors should already have been handled"), }; - let needs_upload = self.texture_cache.request(&entry.texture_cache_handle, gpu_cache); + let needs_upload = self.texture_cache.request(&entry.texture_cache_handle, gpu_buffer); if !needs_upload && entry.dirty_rect.is_empty() { return size; @@ -1276,7 +1276,7 @@ impl ResourceCache { &mut self, mut font: FontInstance, glyph_keys: &[GlyphKey], - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, ) { debug_assert_eq!(self.state, State::AddResources); @@ -1291,7 +1291,7 @@ impl ResourceCache { match entry { GlyphCacheEntry::Cached(ref glyph) => { // Skip the glyph if it is already has a valid texture cache handle. - if !texture_cache.request(&glyph.texture_cache_handle, gpu_cache) { + if !texture_cache.request(&glyph.texture_cache_handle, gpu_buffer) { return false; } // This case gets hit when we already rasterized the glyph, but the @@ -1322,7 +1322,6 @@ impl ResourceCache { mut font: FontInstance, glyph_keys: &[GlyphKey], fetch_buffer: &mut Vec<GlyphFetchResult>, - gpu_cache: &mut GpuCache, mut f: F, ) where F: FnMut(TextureSource, GlyphFormat, &[GlyphFetchResult]), @@ -1354,7 +1353,7 @@ impl ResourceCache { } fetch_buffer.push(GlyphFetchResult { index_in_text_run: loop_index as i32, - uv_rect_address: gpu_cache.get_address(&cache_item.uv_rect_handle), + uv_rect_address: cache_item.uv_rect_handle, offset: DevicePoint::new(cache_item.user_data[0], cache_item.user_data[1]), size: cache_item.uv_rect.size(), scale: cache_item.user_data[2], @@ -1469,7 +1468,7 @@ impl ResourceCache { }) } - pub fn begin_frame(&mut self, stamp: FrameStamp, gpu_cache: &mut GpuCache, profile: &mut TransactionProfile) { + pub fn begin_frame(&mut self, stamp: FrameStamp, profile: &mut TransactionProfile) { profile_scope!("begin_frame"); debug_assert_eq!(self.state, State::Idle); self.state = State::AddResources; @@ -1490,12 +1489,12 @@ impl ResourceCache { v.clear(); self.deleted_blob_keys.push_back(v); - self.texture_cache.run_compaction(gpu_cache); + self.texture_cache.run_compaction(); } pub fn block_until_all_resources_added( &mut self, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilder, profile: &mut TransactionProfile, ) { profile_scope!("block_until_all_resources_added"); @@ -1517,7 +1516,7 @@ impl ResourceCache { } Ok(glyph) => { let mut texture_cache_handle = TextureCacheHandle::invalid(); - texture_cache.request(&texture_cache_handle, gpu_cache); + texture_cache.request(&texture_cache_handle, &mut gpu_buffer.f32); texture_cache.update( &mut texture_cache_handle, ImageDescriptor { @@ -1531,7 +1530,7 @@ impl ResourceCache { Some(CachedImageData::Raw(Arc::new(glyph.bytes))), [glyph.left, -glyph.top, glyph.scale, 0.0], DirtyRect::All, - gpu_cache, + &mut gpu_buffer.f32, Some(glyph_key_cache.eviction_notice()), UvRectKind::Rect, Eviction::Auto, @@ -1550,10 +1549,10 @@ impl ResourceCache { ); // Apply any updates of new / updated images (incl. blobs) to the texture cache. - self.update_texture_cache(gpu_cache); + self.update_texture_cache(gpu_buffer); } - fn update_texture_cache(&mut self, gpu_cache: &mut GpuCache) { + fn update_texture_cache(&mut self, gpu_buffer: &mut GpuBufferBuilder) { profile_scope!("update_texture_cache"); if self.fallback_handle == TextureCacheHandle::invalid() { @@ -1575,7 +1574,7 @@ impl ResourceCache { Some(CachedImageData::Raw(Arc::new(fallback_color))), [0.0; 4], DirtyRect::All, - gpu_cache, + &mut gpu_buffer.f32, None, UvRectKind::Rect, Eviction::Manual, @@ -1693,7 +1692,7 @@ impl ResourceCache { Some(image_data), [0.0; 4], dirty_rect, - gpu_cache, + &mut gpu_buffer.f32, None, UvRectKind::Rect, eviction, diff --git a/gfx/wr/webrender/src/texture_cache.rs b/gfx/wr/webrender/src/texture_cache.rs @@ -9,7 +9,6 @@ use api::units::*; use api::{DocumentId, IdNamespace}; use crate::device::{TextureFilter, TextureFormatPair}; use crate::freelist::{FreeList, FreeListHandle, WeakFreeListHandle}; -use crate::gpu_cache::{GpuCache, GpuCacheHandle}; use crate::gpu_types::{ImageSource, UvRectKind}; use crate::internal_types::{ CacheTextureId, Swizzle, SwizzleSettings, FrameStamp, FrameId, @@ -18,6 +17,7 @@ use crate::internal_types::{ }; use crate::lru_cache::LRUCache; use crate::profiler::{self, TransactionProfile}; +use crate::renderer::{GpuBufferAddress, GpuBufferBuilderF}; use crate::resource_cache::{CacheItem, CachedImageData}; use crate::texture_pack::{ AllocatorList, AllocId, AtlasAllocatorList, ShelfAllocator, ShelfAllocatorOptions, @@ -102,8 +102,8 @@ pub struct CacheEntry { // in the glyph cache eviction code. We could probably remove it // entirely in future (or move to PictureCacheEntry). pub last_access: FrameStamp, - /// Handle to the resource rect in the GPU cache. - pub uv_rect_handle: GpuCacheHandle, + /// Address of the resource rect in the GPU cache. + pub uv_rect_handle: GpuBufferAddress, /// Image format of the data that the entry expects. pub input_format: ImageFormat, pub filter: TextureFilter, @@ -143,7 +143,7 @@ impl CacheEntry { input_format: params.descriptor.format, filter: params.filter, swizzle, - uv_rect_handle: GpuCacheHandle::new(), + uv_rect_handle: GpuBufferAddress::INVALID, eviction_notice: None, uv_rect_kind: params.uv_rect_kind, shader: TargetShader::Default, @@ -154,17 +154,15 @@ impl CacheEntry { // 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 origin = self.details.describe(); - let image_source = ImageSource { - p0: origin.to_f32(), - p1: (origin + self.size).to_f32(), - user_data: self.user_data, - uv_rect_kind: self.uv_rect_kind, - }; - image_source.write_gpu_blocks(&mut request); - } + fn write_gpu_blocks(&mut self, gpu_buffer: &mut GpuBufferBuilderF) { + let origin = self.details.describe(); + let image_source = ImageSource { + p0: origin.to_f32(), + p1: (origin + self.size).to_f32(), + user_data: self.user_data, + uv_rect_kind: self.uv_rect_kind, + }; + self.uv_rect_handle = image_source.write_gpu_blocks(gpu_buffer); } fn evict(&self) { @@ -756,7 +754,7 @@ impl TextureCache { self.now = FrameStamp::INVALID; } - pub fn run_compaction(&mut self, gpu_cache: &mut GpuCache) { + pub fn run_compaction(&mut self) { // Use the same order as BudgetType::VALUES so that we can index self.bytes_allocated // with the same index. let allocator_lists = [ @@ -807,8 +805,7 @@ impl TextureCache { allocated_size_in_bytes: new_bytes, }; - gpu_cache.invalidate(&entry.uv_rect_handle); - entry.uv_rect_handle = GpuCacheHandle::new(); + entry.uv_rect_handle = GpuBufferAddress::INVALID; let src_rect = DeviceIntRect::from_origin_and_size(change.old_rect.min, entry.size); let dst_rect = DeviceIntRect::from_origin_and_size(change.new_rect.min, entry.size); @@ -837,7 +834,7 @@ impl TextureCache { // Returns true if the image needs to be uploaded to the // texture cache (either never uploaded, or has been // evicted on a previous frame). - pub fn request(&mut self, handle: &TextureCacheHandle, gpu_cache: &mut GpuCache) -> bool { + pub fn request(&mut self, handle: &TextureCacheHandle, gpu_buffer: &mut GpuBufferBuilderF) -> bool { let now = self.now; let entry = match handle { TextureCacheHandle::Empty => None, @@ -854,7 +851,7 @@ impl TextureCache { // If an image is requested that is already in the cache, // refresh the GPU cache data associated with this item. entry.last_access = now; - entry.update_gpu_cache(gpu_cache); + entry.write_gpu_blocks(gpu_buffer); false }) } @@ -913,7 +910,7 @@ impl TextureCache { data: Option<CachedImageData>, user_data: [f32; 4], mut dirty_rect: ImageDirtyRect, - gpu_cache: &mut GpuCache, + gpu_buffer: &mut GpuBufferBuilderF, eviction_notice: Option<&EvictionNotice>, uv_rect_kind: UvRectKind, eviction: Eviction, @@ -953,14 +950,8 @@ impl TextureCache { entry.eviction_notice = eviction_notice.cloned(); entry.uv_rect_kind = uv_rect_kind; - // Invalidate the contents of the resource rect in the GPU cache. - // This ensures that the update_gpu_cache below will add - // the new information to the GPU cache. - //TODO: only invalidate if the parameters change? - gpu_cache.invalidate(&entry.uv_rect_handle); - // Upload the resource rect and texture array layer. - entry.update_gpu_cache(gpu_cache); + entry.write_gpu_blocks(gpu_buffer); // Create an update command, which the render thread processes // to upload the new image data into the correct location @@ -1033,7 +1024,7 @@ impl TextureCache { pub fn try_get_cache_location( &self, handle: &TextureCacheHandle, - ) -> Option<(CacheTextureId, DeviceIntRect, Swizzle, GpuCacheHandle, [f32; 4])> { + ) -> Option<(CacheTextureId, DeviceIntRect, Swizzle, GpuBufferAddress, [f32; 4])> { let entry = self.get_entry_opt(handle)?; let origin = entry.details.describe(); Some(( @@ -1053,7 +1044,7 @@ impl TextureCache { pub fn get_cache_location( &self, handle: &TextureCacheHandle, - ) -> (CacheTextureId, DeviceIntRect, Swizzle, GpuCacheHandle, [f32; 4]) { + ) -> (CacheTextureId, DeviceIntRect, Swizzle, GpuBufferAddress, [f32; 4]) { self.try_get_cache_location(handle).expect("BUG: was dropped from cache or not updated!") } @@ -1360,7 +1351,7 @@ impl TextureCache { alloc_id, allocated_size_in_bytes, }, - uv_rect_handle: GpuCacheHandle::new(), + uv_rect_handle: GpuBufferAddress::INVALID, input_format: params.descriptor.format, filter: params.filter, swizzle, @@ -1665,7 +1656,6 @@ mod test_texture_cache { // original value. use crate::texture_cache::{TextureCache, TextureCacheHandle, Eviction, TargetShader}; - use crate::gpu_cache::GpuCache; use crate::device::TextureFilter; use crate::gpu_types::UvRectKind; use api::{ImageDescriptor, ImageDescriptorFlags, ImageFormat, DirtyRect}; diff --git a/gfx/wr/webrender/src/visibility.rs b/gfx/wr/webrender/src/visibility.rs @@ -13,6 +13,7 @@ use std::usize; use crate::clip::ClipStore; use crate::composite::CompositeState; use crate::profiler::TransactionProfile; +use crate::renderer::GpuBufferBuilder; use crate::spatial_tree::{SpatialTree, SpatialNodeIndex}; use crate::clip::{ClipChainInstance, ClipTree}; use crate::frame_builder::FrameBuilderConfig; @@ -42,6 +43,7 @@ pub struct FrameVisibilityState<'a> { pub clip_store: &'a mut ClipStore, pub resource_cache: &'a mut ResourceCache, pub gpu_cache: &'a mut GpuCache, + pub frame_gpu_data: &'a mut GpuBufferBuilder, pub data_stores: &'a mut DataStores, pub clip_tree: &'a mut ClipTree, pub composite_state: &'a mut CompositeState, @@ -321,7 +323,7 @@ pub fn update_prim_visibility( &map_local_to_picture, &map_surface_to_vis, &frame_context.spatial_tree, - frame_state.gpu_cache, + &mut frame_state.frame_gpu_data.f32, frame_state.resource_cache, device_pixel_scale, &surface_culling_rect, @@ -363,7 +365,7 @@ pub fn update_prim_visibility( &store.color_bindings, &frame_state.surface_stack, &mut frame_state.composite_state, - &mut frame_state.gpu_cache, + &mut frame_state.frame_gpu_data.f32, &mut frame_state.scratch.primitive, is_root_tile_cache, frame_state.surfaces, diff --git a/gfx/wr/webrender_api/src/units.rs b/gfx/wr/webrender_api/src/units.rs @@ -191,6 +191,15 @@ impl TexelRect { uv1: DevicePoint::new(-1.0, -1.0), } } + + pub fn to_array(&self) -> [f32; 4] { + [ + self.uv0.x, + self.uv0.y, + self.uv1.x, + self.uv1.y, + ] + } } impl Into<TexelRect> for DeviceIntRect {