Bug 1682365 - Pt 2 - Remove texture array usage from render task graph. r=nical

With this change, all color/alpha intermediate surfaces are individual
textures, rather than texture arrays.

This can in theory cause more batch breaks in some cases, but this
is likely to be very rare in practice.

Benefits:
 - No more allocating the array at the size of the largest task / slice.
 - Remove a source of many driver bugs on android devices.
 - Simplify integration of future patches with render task graph.

Much of the render target array texture code is still present, since
picture cache tiles in the Draw compositor still make use of texture
arrays. However, once these are switched to normal textures, we can
remove most of the slice layer, blit workaround functionality etc.

Remove the default feature setting for selecting the image sampler
kind. Instead, this must be explicitly specified by the shader or
a dynamic feature define, which makes sampler selection less error prone.

Differential Revision: https://phabricator.services.mozilla.com/D99006
This commit is contained in:
Glenn Watson 2020-12-14 21:48:41 +00:00
Родитель 78271aa3ec
Коммит d38a041500
26 изменённых файлов: 227 добавлений и 294 удалений

Просмотреть файл

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define VECS_PER_SPECIFIC_BRUSH 3
#define WR_FEATURE_TEXTURE_2D
#define COMPONENT_TRANSFER_IDENTITY 0
#define COMPONENT_TRANSFER_TABLE 1
@ -37,9 +38,8 @@ flat varying vec4 v_uv_sample_bounds;
flat varying vec4 v_color_offset;
// x: Layer index to sample.
// y: Flag to allow perspective interpolation of UV.
flat varying vec2 v_layer_and_perspective;
// Flag to allow perspective interpolation of UV.
flat varying float v_perspective;
flat varying float v_amount;
@ -75,8 +75,7 @@ void brush_vs(
float perspective_interpolate = (brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0 ? 1.0 : 0.0;
v_uv = uv * inv_texture_size * mix(vi.world_pos.w, 1.0, perspective_interpolate);
v_layer_and_perspective.x = res.layer;
v_layer_and_perspective.y = perspective_interpolate;
v_perspective = perspective_interpolate;
v_uv_sample_bounds = vec4(uv0 + vec2(0.5), uv1 - vec2(0.5)) * inv_texture_size.xyxy;
@ -245,12 +244,12 @@ vec4 ComponentTransfer(vec4 colora) {
}
Fragment brush_fs() {
float perspective_divisor = mix(gl_FragCoord.w, 1.0, v_layer_and_perspective.y);
float perspective_divisor = mix(gl_FragCoord.w, 1.0, v_perspective);
vec2 uv = v_uv * perspective_divisor;
// Clamp the uvs to avoid sampling artifacts.
uv = clamp(uv, v_uv_sample_bounds.xy, v_uv_sample_bounds.zw);
vec4 Cs = texture(sColor0, vec3(uv, v_layer_and_perspective.x));
vec4 Cs = texture(sColor0, uv);
// Un-premultiply the input.
float alpha = Cs.a;

Просмотреть файл

@ -3,16 +3,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define VECS_PER_SPECIFIC_BRUSH 3
#define WR_FEATURE_TEXTURE_2D
#include shared,prim_shared,brush
// xy: uv coorinates.
// z: layer.
varying vec3 v_src_uv;
varying vec2 v_src_uv;
// xy: uv coorinates.
// z: layer.
varying vec3 v_backdrop_uv;
varying vec2 v_backdrop_uv;
flat varying int v_op;
@ -41,16 +40,14 @@ void brush_vs(
vec2 src_uv = src_device_pos +
src_task.common_data.task_rect.p0 -
src_task.content_origin;
v_src_uv.xy = src_uv / src_texture_size;
v_src_uv.z = src_task.common_data.texture_layer_index;
v_src_uv = src_uv / src_texture_size;
RenderTaskCommonData backdrop_task = fetch_render_task_common_data(prim_user_data.y);
float src_to_backdrop_scale = pic_task.device_pixel_scale / src_task.device_pixel_scale;
vec2 backdrop_uv = device_pos +
backdrop_task.task_rect.p0 -
src_task.content_origin * src_to_backdrop_scale;
v_backdrop_uv.xy = backdrop_uv / backdrop_texture_size;
v_backdrop_uv.z = backdrop_task.texture_layer_index;
v_backdrop_uv = backdrop_uv / backdrop_texture_size;
}
#endif
@ -213,8 +210,8 @@ const int MixBlendMode_Color = 14;
const int MixBlendMode_Luminosity = 15;
Fragment brush_fs() {
vec4 Cb = textureLod(sColor0, vec3(v_backdrop_uv.xy, v_backdrop_uv.z), 0.0);
vec4 Cs = textureLod(sColor1, vec3(v_src_uv.xy, v_src_uv.z), 0.0);
vec4 Cb = texture(sColor0, v_backdrop_uv);
vec4 Cs = texture(sColor1, v_src_uv);
// The mix-blend-mode functions assume no premultiplied alpha
if (Cb.a != 0.0) {

Просмотреть файл

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#define VECS_PER_SPECIFIC_BRUSH 3
#define WR_FEATURE_TEXTURE_2D
#include shared,prim_shared,brush
@ -16,7 +17,7 @@ flat varying vec4 v_uv_sample_bounds;
// Layer index to sample.
// Flag to allow perspective interpolation of UV.
flat varying vec2 v_layer_and_perspective;
flat varying float v_perspective;
flat varying float v_opacity;
@ -44,8 +45,7 @@ void brush_vs(
float perspective_interpolate = (brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0 ? 1.0 : 0.0;
v_uv = uv / texture_size * mix(vi.world_pos.w, 1.0, perspective_interpolate);
v_layer_and_perspective.x = res.layer;
v_layer_and_perspective.y = perspective_interpolate;
v_perspective = perspective_interpolate;
v_uv_sample_bounds = vec4(uv0 + vec2(0.5), uv1 - vec2(0.5)) / texture_size.xyxy;
@ -59,13 +59,13 @@ void brush_vs(
#ifdef WR_FRAGMENT_SHADER
Fragment brush_fs() {
float perspective_divisor = mix(gl_FragCoord.w, 1.0, v_layer_and_perspective.y);
float perspective_divisor = mix(gl_FragCoord.w, 1.0, v_perspective);
vec2 uv = v_uv * perspective_divisor;
// Clamp the uvs to avoid sampling artifacts.
uv = clamp(uv, v_uv_sample_bounds.xy, v_uv_sample_bounds.zw);
// No need to un-premultiply since we'll only apply a factor to the alpha.
vec4 color = texture(sColor0, vec3(uv, v_layer_and_perspective.x));
vec4 color = texture(sColor0, uv);
float alpha = v_opacity;
@ -83,9 +83,7 @@ void swgl_drawSpanRGBA8() {
return;
}
int layer = swgl_textureLayerOffset(sColor0, v_layer_and_perspective.x);
float perspective_divisor = mix(swgl_forceScalar(gl_FragCoord.w), 1.0, v_layer_and_perspective.y);
float perspective_divisor = mix(swgl_forceScalar(gl_FragCoord.w), 1.0, v_perspective);
vec2 uv = swgl_linearQuantize(sColor0, v_uv * perspective_divisor);
vec2 min_uv = swgl_linearQuantize(sColor0, v_uv_sample_bounds.xy);
@ -99,7 +97,7 @@ void swgl_drawSpanRGBA8() {
alpha *= init_transform_fs(v_local_pos);
v_local_pos += swgl_interpStep(v_local_pos);
#endif
swgl_commitTextureLinearColorRGBA8(sColor0, clamp(uv, min_uv, max_uv), alpha, layer);
swgl_commitTextureLinearColorRGBA8(sColor0, clamp(uv, min_uv, max_uv), alpha, 0);
uv += step_uv;
vClipMaskUv += swgl_interpStep(vClipMaskUv);
}
@ -110,7 +108,7 @@ void swgl_drawSpanRGBA8() {
alpha *= init_transform_fs(v_local_pos);
v_local_pos += swgl_interpStep(v_local_pos);
#endif
swgl_commitTextureLinearColorRGBA8(sColor0, clamp(uv, min_uv, max_uv), alpha, layer);
swgl_commitTextureLinearColorRGBA8(sColor0, clamp(uv, min_uv, max_uv), alpha, 0);
uv += step_uv;
}
}

Просмотреть файл

@ -2,10 +2,11 @@
* 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/. */
#define WR_FEATURE_TEXTURE_2D
#include shared,prim_shared
varying vec2 vUv;
flat varying float vUvLayer;
flat varying vec4 vUvRect;
flat varying vec2 vOffsetScale;
// The number of pixels on each end that we apply the blur filter over.
@ -73,7 +74,6 @@ void main(void) {
RectWithSize target_rect = blur_task.common_data.task_rect;
vec2 texture_size = vec2(textureSize(sColor0, 0).xy);
vUvLayer = src_task.texture_layer_index;
// Ensure that the support is an even number of pixels to simplify the
// fragment shader logic.
@ -118,10 +118,10 @@ void main(void) {
#if defined WR_FEATURE_COLOR_TARGET
#define SAMPLE_TYPE vec4
#define SAMPLE_TEXTURE(uv) texture(sColor0, vec3(uv, vUvLayer))
#define SAMPLE_TEXTURE(uv) texture(sColor0, uv)
#else
#define SAMPLE_TYPE float
#define SAMPLE_TEXTURE(uv) texture(sColor0, vec3(uv, vUvLayer)).r
#define SAMPLE_TEXTURE(uv) texture(sColor0, uv).r
#endif
// TODO(gw): Write a fast path blur that handles smaller blur radii
@ -182,9 +182,8 @@ void swgl_drawSpanRGBA8() {
return;
}
int layer = swgl_textureLayerOffset(sColor0, vUvLayer);
swgl_commitGaussianBlurRGBA8(sColor0, vUv, vUvRect, vOffsetScale.x != 0.0,
vSupport, vGaussCoefficients, layer);
vSupport, vGaussCoefficients, 0);
}
#else
void swgl_drawSpanR8() {
@ -192,9 +191,8 @@ void swgl_drawSpanR8() {
return;
}
int layer = swgl_textureLayerOffset(sColor0, vUvLayer);
swgl_commitGaussianBlurR8(sColor0, vUv, vUvRect, vOffsetScale.x != 0.0,
vSupport, vGaussCoefficients, layer);
vSupport, vGaussCoefficients, 0);
}
#endif
#endif

Просмотреть файл

@ -2,10 +2,12 @@
* 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/. */
#define WR_FEATURE_TEXTURE_2D
#include shared,prim_shared
varying vec3 vInput1Uv;
varying vec3 vInput2Uv;
varying vec2 vInput1Uv;
varying vec2 vInput2Uv;
flat varying vec4 vInput1UvRect;
flat varying vec4 vInput2UvRect;
flat varying int vFilterInputCount;
@ -72,15 +74,12 @@ vec4 compute_uv_rect(RenderTaskCommonData task, vec2 texture_size) {
return uvRect;
}
vec3 compute_uv(RenderTaskCommonData task, vec2 texture_size) {
vec2 compute_uv(RenderTaskCommonData task, vec2 texture_size) {
RectWithSize task_rect = task.task_rect;
vec3 uv = vec3(0.0, 0.0, task.texture_layer_index);
vec2 uv0 = task_rect.p0 / texture_size;
vec2 uv1 = floor(task_rect.p0 + task_rect.size) / texture_size;
uv.xy = mix(uv0, uv1, aPosition.xy);
return uv;
return mix(uv0, uv1, aPosition.xy);
}
void main(void) {
@ -507,9 +506,9 @@ vec4 composite(vec4 Cs, vec4 Cb, int mode) {
return Cr;
}
vec4 sampleInUvRect(sampler2DArray sampler, vec3 uv, vec4 uvRect) {
vec4 sampleInUvRect(sampler2D sampler, vec2 uv, vec4 uvRect) {
vec2 clamped = clamp(uv.xy, uvRect.xy, uvRect.zw);
return texture(sampler, vec3(clamped, uv.z));
return texture(sampler, clamped);
}
void main(void) {
@ -564,8 +563,8 @@ void main(void) {
needsPremul = false;
break;
case FILTER_OFFSET:
vec2 offsetUv = vInput1Uv.xy + vFilterData0.xy;
result = sampleInUvRect(sColor0, vec3(offsetUv, vInput1Uv.z), vInput1UvRect);
vec2 offsetUv = vInput1Uv + vFilterData0.xy;
result = sampleInUvRect(sColor0, offsetUv, vInput1UvRect);
result *= point_inside_rect(offsetUv, vFilterData1.xy, vFilterData1.zw);
needsPremul = false;
break;

Просмотреть файл

@ -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/. */
#define WR_FEATURE_TEXTURE_2D
#include shared,shared_other
varying vec2 vColorTexCoord;
@ -22,7 +24,7 @@ void main(void) {
#ifdef WR_FRAGMENT_SHADER
void main(void) {
float alpha = texture(sColor0, vec3(vColorTexCoord.xy, 0.0)).r;
float alpha = texture(sColor0, vColorTexCoord).r;
oFragColor = vColor * alpha;
}
#endif

Просмотреть файл

@ -15,7 +15,7 @@
#define RASTER_LOCAL 0
#define RASTER_SCREEN 1
uniform sampler2DArray sClipMask;
uniform sampler2D sClipMask;
vec2 clamp_rect(vec2 pt, RectWithSize rect) {
return clamp(pt, rect.p0, rect.p0 + rect.size);
@ -266,11 +266,7 @@ float do_clip() {
return 0.0;
}
// finally, the slow path - fetch the mask value from an image
// Note the Z getting rounded to the nearest integer because the variable
// is still interpolated and becomes a subject of precision-caused
// fluctuations, see https://bugzilla.mozilla.org/show_bug.cgi?id=1491911
ivec3 tc = ivec3(mask_uv, vClipMaskUv.z + 0.5);
return texelFetch(sClipMask, tc, 0).r;
return texelFetch(sClipMask, ivec2(mask_uv), 0).r;
}
#ifdef WR_FEATURE_DITHERING

Просмотреть файл

@ -2,12 +2,14 @@
* 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/. */
#define WR_FEATURE_TEXTURE_2D
#include shared,prim_shared
// interpolated UV coordinates to sample.
varying vec2 vUv;
// X = layer index to sample, Y = flag to allow perspective interpolation of UV.
flat varying vec2 vLayerAndPerspective;
// flag to allow perspective interpolation of UV.
flat varying float vPerspective;
flat varying vec4 vUvSampleBounds;
#ifdef WR_VERTEX_SHADER
@ -104,15 +106,15 @@ void main(void) {
float perspective_interpolate = float(ph.user_data.y);
vUv = uv / texture_size * mix(gl_Position.w, 1.0, perspective_interpolate);
vLayerAndPerspective = vec2(res.layer, perspective_interpolate);
vPerspective = perspective_interpolate;
}
#endif
#ifdef WR_FRAGMENT_SHADER
void main(void) {
float alpha = do_clip();
float perspective_divisor = mix(gl_FragCoord.w, 1.0, vLayerAndPerspective.y);
float perspective_divisor = mix(gl_FragCoord.w, 1.0, vPerspective);
vec2 uv = clamp(vUv * perspective_divisor, vUvSampleBounds.xy, vUvSampleBounds.zw);
write_output(alpha * textureLod(sColor0, vec3(uv, vLayerAndPerspective.x), 0.0));
write_output(alpha * texture(sColor0, uv));
}
#endif

Просмотреть файл

@ -163,7 +163,7 @@ uniform sampler2DRect sColor2;
uniform samplerExternalOES sColor0;
uniform samplerExternalOES sColor1;
uniform samplerExternalOES sColor2;
#else
#elif defined WR_FEATURE_TEXTURE_2D_ARRAY
uniform sampler2DArray sColor0;
uniform sampler2DArray sColor1;
uniform sampler2DArray sColor2;

Просмотреть файл

@ -1607,7 +1607,7 @@ impl BatchBuilder {
).unwrap();
let kind = BatchKind::Brush(
BrushBatchKind::Image(ImageBufferKind::Texture2DArray)
BrushBatchKind::Image(ImageBufferKind::Texture2D)
);
let (uv_rect_address, textures) = render_tasks.resolve_surface(
surface_task.expect("bug: surface must be allocated by now"),
@ -1654,7 +1654,7 @@ impl BatchBuilder {
// The shadows and the content get drawn as a brush image.
let kind = BatchKind::Brush(
BrushBatchKind::Image(ImageBufferKind::Texture2DArray),
BrushBatchKind::Image(ImageBufferKind::Texture2D),
);
// Gets the saved render task ID of the content, which is
@ -1665,7 +1665,6 @@ impl BatchBuilder {
let texture_id = secondary_task.get_target_texture();
TextureSource::TextureCache(
texture_id,
ImageBufferKind::Texture2DArray,
Swizzle::default(),
)
};
@ -1944,7 +1943,7 @@ impl BatchBuilder {
);
let key = BatchKey::new(
BatchKind::Brush(
BrushBatchKind::Image(ImageBufferKind::Texture2DArray),
BrushBatchKind::Image(ImageBufferKind::Texture2D),
),
BlendMode::Advanced(mode),
textures,
@ -2004,12 +2003,10 @@ impl BatchBuilder {
colors: [
TextureSource::TextureCache(
color0,
ImageBufferKind::Texture2DArray,
Swizzle::default(),
),
TextureSource::TextureCache(
color1,
ImageBufferKind::Texture2DArray,
Swizzle::default(),
),
TextureSource::Invalid,
@ -2052,7 +2049,6 @@ impl BatchBuilder {
colors: [
TextureSource::TextureCache(
texture_id,
ImageBufferKind::Texture2DArray,
Swizzle::default(),
),
TextureSource::Invalid,
@ -2060,7 +2056,7 @@ impl BatchBuilder {
],
};
let batch_params = BrushBatchParameters::shared(
BrushBatchKind::Image(ImageBufferKind::Texture2DArray),
BrushBatchKind::Image(ImageBufferKind::Texture2D),
textures,
ImageBrushData {
color_mode: ShaderColorMode::Image,
@ -2126,7 +2122,7 @@ impl BatchBuilder {
).unwrap();
let kind = BatchKind::Brush(
BrushBatchKind::Image(ImageBufferKind::Texture2DArray)
BrushBatchKind::Image(ImageBufferKind::Texture2D)
);
let (uv_rect_address, textures) = render_tasks.resolve_surface(
surface_task.expect("bug: surface must be allocated by now"),
@ -2983,7 +2979,7 @@ impl BatchBuilder {
);
let batch_key = BatchKey::new(
BatchKind::Brush(BrushBatchKind::Image(ImageBufferKind::Texture2DArray)),
BatchKind::Brush(BrushBatchKind::Image(ImageBufferKind::Texture2D)),
BlendMode::PremultipliedAlpha,
textures,
);
@ -3345,7 +3341,6 @@ impl RenderTaskGraph {
BatchTextures::prim_textured(
TextureSource::TextureCache(
task.get_target_texture(),
ImageBufferKind::Texture2DArray,
Swizzle::default(),
),
clip_mask,
@ -3828,7 +3823,6 @@ impl<'a, 'rc> RenderTargetContext<'a, 'rc> {
task_id.into(),
TextureSource::TextureCache(
render_tasks[task_id].get_target_texture(),
ImageBufferKind::Texture2DArray,
Swizzle::default(),
)
))

Просмотреть файл

@ -140,7 +140,7 @@ impl DebugRenderer {
let tri_vao = device.create_vao(&DESC_COLOR);
let font_texture = device.create_texture(
ImageBufferKind::Texture2DArray,
ImageBufferKind::Texture2D,
ImageFormat::R8,
debug_font_data::BMP_WIDTH,
debug_font_data::BMP_HEIGHT,

Просмотреть файл

@ -474,6 +474,13 @@ impl Texture {
self.filter
}
pub fn is_array(&self) -> bool {
match self.target {
gl::TEXTURE_2D_ARRAY => true,
_ => false
}
}
pub fn supports_depth(&self) -> bool {
!self.fbos_with_depth.is_empty()
}

Просмотреть файл

@ -12,7 +12,7 @@ use crate::debug_render::DebugItem;
use crate::gpu_cache::{GpuCache, GpuCacheHandle};
use crate::gpu_types::{PrimitiveHeaders, TransformPalette, ZBufferIdGenerator};
use crate::gpu_types::TransformData;
use crate::internal_types::{CacheTextureId, FastHashMap, PlaneSplitter};
use crate::internal_types::{FastHashMap, PlaneSplitter};
use crate::picture::{DirtyRegion, PictureUpdateState, SliceId, TileCacheInstance};
use crate::picture::{SurfaceInfo, SurfaceIndex, ROOT_SURFACE_INDEX};
use crate::picture::{BackdropKind, SubpixelMode, TileCacheLogger, RasterConfig, PictureCompositeMode};
@ -593,23 +593,6 @@ impl FrameBuilder {
has_texture_cache_tasks |= !pass.texture_cache.is_empty();
has_texture_cache_tasks |= !pass.picture_cache.is_empty();
// Check which textures in this pass need to be saved until the end of
// the frame. This will all disappear once render task graph is a full DAG.
let mut save_color = false;
let mut save_alpha = false;
for task_id in &pass.tasks {
let task = &render_tasks[*task_id];
match task.target_kind() {
RenderTargetKind::Color => {
save_color |= task.save_target;
}
RenderTargetKind::Alpha => {
save_alpha |= task.save_target;
}
}
}
// Return previous frame's textures to the target pool, so they are available
// for use on subsequent passes. Also include these in the list for the renderer
// to immediately invalidate once they are no longer used.
@ -618,16 +601,18 @@ impl FrameBuilder {
pass.textures_to_invalidate.push(texture_id);
}
if let Some(texture_id) = pass.color.texture_id {
if save_color {
for target in &pass.color.targets {
let texture_id = target.texture_id();
if target.save_target() {
saved_texture_ids.push(texture_id);
} else {
active_texture_ids.push(texture_id);
}
}
if let Some(texture_id) = pass.alpha.texture_id {
if save_alpha {
for target in &pass.alpha.targets {
let texture_id = target.texture_id();
if target.save_target() {
saved_texture_ids.push(texture_id);
} else {
active_texture_ids.push(texture_id);
@ -807,12 +792,12 @@ pub fn build_render_pass(
(Some(texture), layer)
}
RenderTaskLocation::Dynamic(ref mut origin, size) => {
let (target_index, alloc_origin) = match target_kind {
RenderTargetKind::Color => pass.color.allocate(size),
RenderTargetKind::Alpha => pass.alpha.allocate(size),
let (target_index, texture_id, alloc_origin) = match target_kind {
RenderTargetKind::Color => pass.color.allocate(size, ctx.resource_cache),
RenderTargetKind::Alpha => pass.alpha.allocate(size, ctx.resource_cache),
};
*origin = Some((alloc_origin, CacheTextureId::INVALID, target_index));
(None, target_index.0)
*origin = Some((alloc_origin, texture_id));
(None, target_index)
}
RenderTaskLocation::PictureCache { .. } => {
// For picture cache tiles, just store them in the map
@ -1040,47 +1025,6 @@ pub fn build_render_pass(
z_generator,
composite_state,
);
// Now that the passes have been built, we know what the texture_id is for this surface
// (since we know the layer count and texture size). Step through the tasks on this
// texture and store that in the task location. This is used so that tasks that get added
// on following passes can directly access and reference the texture_id, rather than
// referring to PrevPassAlpha/Color. Again, this will become a lot simpler once we
// have the full DAG in place (and once sub-passes are individual textures rather than
// a single texture array).
for &task_id in &pass.tasks {
let task = &mut render_tasks[task_id];
let target_kind = task.target_kind();
match task.location {
RenderTaskLocation::TextureCache { .. } |
RenderTaskLocation::PictureCache { .. } => {}
RenderTaskLocation::Dynamic(None, _) => {
unreachable!();
}
RenderTaskLocation::Dynamic(Some((_, ref mut texture_id, _)), _) => {
assert_eq!(*texture_id, CacheTextureId::INVALID);
match target_kind {
RenderTargetKind::Color => {
*texture_id = pass
.color
.texture_id
.expect("bug: color texture must be allocated by now");
}
RenderTargetKind::Alpha => {
*texture_id = pass
.alpha
.texture_id
.expect("bug: alpha texture must be allocated by now");
}
}
}
}
}
}
/// A rendering-oriented representation of the frame built by the render backend

Просмотреть файл

@ -265,7 +265,7 @@ pub enum TextureSource {
/// Equivalent to `None`, allowing us to avoid using `Option`s everywhere.
Invalid,
/// An entry in the texture cache.
TextureCache(CacheTextureId, ImageBufferKind, Swizzle),
TextureCache(CacheTextureId, Swizzle),
/// An external image texture, mananged by the embedding.
External(DeferredResolveIndex, ImageBufferKind),
/// Select a dummy 1x1 white texture. This can be used by image
@ -276,12 +276,12 @@ pub enum TextureSource {
impl TextureSource {
pub fn image_buffer_kind(&self) -> ImageBufferKind {
match *self {
TextureSource::TextureCache(_, image_buffer_kind, _) => image_buffer_kind,
TextureSource::TextureCache(..) => ImageBufferKind::Texture2D,
TextureSource::External(_, image_buffer_kind) => image_buffer_kind,
// Render tasks use texture arrays for now.
TextureSource::Dummy => ImageBufferKind::Texture2DArray,
TextureSource::Dummy => ImageBufferKind::Texture2D,
TextureSource::Invalid => ImageBufferKind::Texture2D,
}

Просмотреть файл

@ -4,13 +4,12 @@
use api::units::*;
use api::{ColorF, PremultipliedColorF, ImageFormat, LineOrientation, BorderStyle, ImageBufferKind};
use api::{ColorF, PremultipliedColorF, ImageFormat, LineOrientation, BorderStyle};
use crate::batch::{AlphaBatchBuilder, AlphaBatchContainer, BatchTextures, resolve_image};
use crate::batch::{ClipBatcher, BatchBuilder};
use crate::spatial_tree::{SpatialTree, ROOT_SPATIAL_NODE_INDEX};
use crate::clip::ClipStore;
use crate::composite::CompositeState;
use crate::device::Texture;
use crate::frame_builder::{FrameGlobalResources};
use crate::gpu_cache::{GpuCache, GpuCacheAddress};
use crate::gpu_types::{BorderInstance, SvgFilterInstance, BlurDirection, BlurInstance, PrimitiveHeaders, ScalingInstance};
@ -24,9 +23,9 @@ use crate::render_task::{RenderTaskKind, RenderTaskAddress, BlitSource};
use crate::render_task::{RenderTask, ScalingTask, SvgFilterInfo};
use crate::render_task_graph::{RenderTaskGraph, RenderTaskId};
use crate::resource_cache::ResourceCache;
use crate::guillotine_allocator::{GuillotineAllocator, FreeRectSlice};
use crate::guillotine_allocator::{GuillotineAllocator};
use crate::visibility::PrimitiveVisibilityMask;
use std::{cmp, mem};
use std::{mem};
const STYLE_SOLID: i32 = ((BorderStyle::Solid as i32) << 8) | ((BorderStyle::Solid as i32) << 16);
@ -37,9 +36,6 @@ const STYLE_MASK: i32 = 0x00FF_FF00;
/// we try to avoid it. This can go away when proper tiling support lands,
/// since we can then split large primitives across multiple textures.
const IDEAL_MAX_TEXTURE_DIMENSION: i32 = 2048;
/// If we ever need a larger texture than the ideal, we better round it up to a
/// reasonable number in order to have a bit of leeway in placing things inside.
const TEXTURE_DIMENSION_MASK: i32 = 0xFF;
/// A tag used to identify the output format of a `RenderTarget`.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
@ -89,6 +85,8 @@ pub struct RenderTargetContext<'a, 'rc> {
pub trait RenderTarget {
/// Creates a new RenderTarget of the given type.
fn new(
texture_id: CacheTextureId,
target_size: DeviceIntSize,
screen_size: DeviceIntSize,
gpu_supports_fast_clears: bool,
) -> Self;
@ -132,6 +130,13 @@ pub trait RenderTarget {
fn used_rect(&self) -> DeviceIntRect;
fn add_used(&mut self, rect: DeviceIntRect);
fn texture_id(&self) -> CacheTextureId;
fn save_target(&self) -> bool;
fn allocate(
&mut self,
size: DeviceIntSize,
) -> Option<(CacheTextureId, DeviceIntPoint)>;
}
/// A series of `RenderTarget` instances, serving as the high-level container
@ -164,17 +169,9 @@ pub trait RenderTarget {
pub struct RenderTargetList<T> {
screen_size: DeviceIntSize,
pub format: ImageFormat,
/// The maximum width and height of any single primitive we've encountered
/// that will be drawn to a dynamic location.
///
/// We initially create our per-slice allocators with a width and height of
/// IDEAL_MAX_TEXTURE_DIMENSION. If we encounter a larger primitive, the
/// allocation will fail, but we'll bump max_dynamic_size, which will cause the
/// allocator for the next slice to be just large enough to accomodate it.
pub max_dynamic_size: DeviceIntSize,
pub targets: Vec<T>,
pub alloc_tracker: GuillotineAllocator,
pub texture_id: Option<CacheTextureId>,
// pub alloc_tracker: GuillotineAllocator,
// pub texture_id: Option<CacheTextureId>,
gpu_supports_fast_clears: bool,
}
@ -187,10 +184,7 @@ impl<T: RenderTarget> RenderTargetList<T> {
RenderTargetList {
screen_size,
format,
max_dynamic_size: DeviceIntSize::new(0, 0),
targets: Vec::new(),
alloc_tracker: GuillotineAllocator::new(None),
texture_id: None,
gpu_supports_fast_clears,
}
}
@ -210,12 +204,6 @@ impl<T: RenderTarget> RenderTargetList<T> {
return;
}
// Get a bounding rect of all the layers, and round it up to a multiple
// of 256. This improves render target reuse when resizing the window,
// since we don't need to create a new render target for each slightly-
// larger frame.
let mut bounding_rect = DeviceIntRect::zero();
for target in &mut self.targets {
target.build(
ctx,
@ -227,83 +215,62 @@ impl<T: RenderTarget> RenderTargetList<T> {
z_generator,
composite_state,
);
bounding_rect = target.used_rect().union(&bounding_rect);
}
debug_assert_eq!(bounding_rect.origin, DeviceIntPoint::zero());
let dimensions = DeviceIntSize::new(
(bounding_rect.size.width + 255) & !255,
(bounding_rect.size.height + 255) & !255,
);
let texture_id = ctx.resource_cache.get_or_create_render_target_from_pool(
dimensions,
self.targets.len(),
self.format,
);
assert!(self.texture_id.is_none());
self.texture_id = Some(texture_id);
}
pub fn allocate(
&mut self,
alloc_size: DeviceIntSize,
) -> (RenderTargetIndex, DeviceIntPoint) {
let (free_rect_slice, origin) = match self.alloc_tracker.allocate(&alloc_size) {
Some(allocation) => allocation,
None => {
// Have the allocator restrict slice sizes to our max ideal
// dimensions, unless we've already gone bigger on a previous
// slice.
let rounded_dimensions = DeviceIntSize::new(
(self.max_dynamic_size.width + TEXTURE_DIMENSION_MASK) & !TEXTURE_DIMENSION_MASK,
(self.max_dynamic_size.height + TEXTURE_DIMENSION_MASK) & !TEXTURE_DIMENSION_MASK,
);
let allocator_dimensions = DeviceIntSize::new(
cmp::max(IDEAL_MAX_TEXTURE_DIMENSION, rounded_dimensions.width),
cmp::max(IDEAL_MAX_TEXTURE_DIMENSION, rounded_dimensions.height),
);
requested_size: DeviceIntSize,
resource_cache: &mut ResourceCache,
) -> (usize, CacheTextureId, DeviceIntPoint) {
let is_standalone =
requested_size.width > IDEAL_MAX_TEXTURE_DIMENSION ||
requested_size.height > IDEAL_MAX_TEXTURE_DIMENSION;
assert!(alloc_size.width <= allocator_dimensions.width &&
alloc_size.height <= allocator_dimensions.height);
let slice = FreeRectSlice(self.targets.len() as u32);
self.targets.push(T::new(self.screen_size, self.gpu_supports_fast_clears));
self.alloc_tracker.extend(
slice,
allocator_dimensions,
alloc_size,
);
(slice, DeviceIntPoint::zero())
}
let target_size = if is_standalone {
requested_size
} else {
DeviceIntSize::new(
IDEAL_MAX_TEXTURE_DIMENSION,
IDEAL_MAX_TEXTURE_DIMENSION,
)
};
if alloc_size.is_empty() && self.targets.is_empty() {
// push an unused target here, only if we don't have any
self.targets.push(T::new(self.screen_size, self.gpu_supports_fast_clears));
for (target_index, target) in self.targets.iter_mut().enumerate() {
if let Some((texture_id, origin)) = target.allocate(requested_size) {
// TODO(gw): Move `add_used` into `allocate` when adding the
// full graph functionality.
target.add_used(DeviceIntRect::new(origin, requested_size));
return (target_index, texture_id, origin);
}
}
self.targets[free_rect_slice.0 as usize]
.add_used(DeviceIntRect::new(origin, alloc_size));
let texture_id = resource_cache.get_or_create_render_target_from_pool(
target_size,
self.format,
);
(RenderTargetIndex(free_rect_slice.0 as usize), origin)
let mut target = T::new(
texture_id,
target_size,
self.screen_size,
self.gpu_supports_fast_clears,
);
let (texture_id, origin) = target.allocate(requested_size).expect("bug: unable to alloc");
target.add_used(DeviceIntRect::new(origin, requested_size));
let target_index = self.targets.len();
self.targets.push(target);
(target_index, texture_id, origin)
}
pub fn needs_depth(&self) -> bool {
self.targets.iter().any(|target| target.needs_depth())
}
pub fn check_ready(&self, t: &Texture) {
let dimensions = t.get_dimensions();
assert!(dimensions.width >= self.max_dynamic_size.width);
assert!(dimensions.height >= self.max_dynamic_size.height);
assert_eq!(t.get_format(), self.format);
assert_eq!(t.get_layer_count() as usize, self.targets.len());
assert!(t.supports_depth() >= self.needs_depth());
}
}
@ -327,10 +294,15 @@ pub struct ColorRenderTarget {
// we can set a scissor rect and only clear to the
// used portion of the target as an optimization.
pub used_rect: DeviceIntRect,
allocator: GuillotineAllocator,
pub texture_id: CacheTextureId,
save_target: bool,
}
impl RenderTarget for ColorRenderTarget {
fn new(
texture_id: CacheTextureId,
target_size: DeviceIntSize,
screen_size: DeviceIntSize,
_: bool,
) -> Self {
@ -344,9 +316,23 @@ impl RenderTarget for ColorRenderTarget {
alpha_tasks: Vec::new(),
screen_size,
used_rect: DeviceIntRect::zero(),
allocator: GuillotineAllocator::new(Some(target_size)),
texture_id,
save_target: false,
}
}
fn allocate(
&mut self,
size: DeviceIntSize,
) -> Option<(CacheTextureId, DeviceIntPoint)> {
self.allocator
.allocate(&size)
.map(|(_, origin)| {
(self.texture_id, origin)
})
}
fn build(
&mut self,
ctx: &mut RenderTargetContext,
@ -455,6 +441,14 @@ impl RenderTarget for ColorRenderTarget {
}
}
fn texture_id(&self) -> CacheTextureId {
self.texture_id
}
fn save_target(&self) -> bool {
self.save_target
}
fn add_task(
&mut self,
task_id: RenderTaskId,
@ -468,6 +462,8 @@ impl RenderTarget for ColorRenderTarget {
profile_scope!("add_task");
let task = &render_tasks[task_id];
self.save_target |= task.save_target;
match task.kind {
RenderTaskKind::VerticalBlur(..) => {
add_blur_instances(
@ -602,10 +598,15 @@ pub struct AlphaRenderTarget {
// we can set a scissor rect and only clear to the
// used portion of the target as an optimization.
pub used_rect: DeviceIntRect,
allocator: GuillotineAllocator,
pub texture_id: CacheTextureId,
save_target: bool,
}
impl RenderTarget for AlphaRenderTarget {
fn new(
texture_id: CacheTextureId,
target_size: DeviceIntSize,
_: DeviceIntSize,
gpu_supports_fast_clears: bool,
) -> Self {
@ -617,9 +618,31 @@ impl RenderTarget for AlphaRenderTarget {
zero_clears: Vec::new(),
one_clears: Vec::new(),
used_rect: DeviceIntRect::zero(),
allocator: GuillotineAllocator::new(Some(target_size)),
texture_id,
save_target: false,
}
}
fn allocate(
&mut self,
size: DeviceIntSize,
) -> Option<(CacheTextureId, DeviceIntPoint)> {
self.allocator
.allocate(&size)
.map(|(_, origin)| {
(self.texture_id, origin)
})
}
fn texture_id(&self) -> CacheTextureId {
self.texture_id
}
fn save_target(&self) -> bool {
self.save_target
}
fn add_task(
&mut self,
task_id: RenderTaskId,
@ -634,6 +657,8 @@ impl RenderTarget for AlphaRenderTarget {
let task = &render_tasks[task_id];
let (target_rect, _) = task.get_target_rect();
self.save_target |= task.save_target;
match task.kind {
RenderTaskKind::Readback |
RenderTaskKind::Picture(..) |
@ -881,7 +906,6 @@ fn add_blur_instances(
) {
let source = TextureSource::TextureCache(
render_tasks[src_task_id].get_target_texture(),
ImageBufferKind::Texture2DArray,
Swizzle::default(),
);
@ -945,7 +969,6 @@ fn add_scaling_instances(
(
TextureSource::TextureCache(
source_task.unwrap().get_target_texture(),
ImageBufferKind::Texture2DArray,
Swizzle::default(),
),
source_task.unwrap().location.to_source_rect(),
@ -979,7 +1002,6 @@ fn add_svg_filter_instances(
textures.input.colors[0] = TextureSource::TextureCache(
task.get_target_texture(),
ImageBufferKind::Texture2DArray,
Swizzle::default(),
);
}
@ -989,7 +1011,6 @@ fn add_svg_filter_instances(
textures.input.colors[1] = TextureSource::TextureCache(
task.get_target_texture(),
ImageBufferKind::Texture2DArray,
Swizzle::default(),
);
}

Просмотреть файл

@ -64,7 +64,7 @@ pub enum RenderTaskLocation {
/// build phase, we invoke `RenderTargetList::alloc()` and store the
/// resulting location in the first member. That location identifies the
/// render target and the offset of the allocated region within that target.
Dynamic(Option<(DeviceIntPoint, CacheTextureId, RenderTargetIndex)>, DeviceIntSize),
Dynamic(Option<(DeviceIntPoint, CacheTextureId)>, DeviceIntSize),
/// The output of the `RenderTask` will be persisted beyond this frame, and
/// thus should be drawn into the `TextureCache`.
TextureCache {
@ -106,7 +106,7 @@ impl RenderTaskLocation {
pub fn to_source_rect(&self) -> (DeviceIntRect, LayerIndex) {
match *self {
RenderTaskLocation::Dynamic(None, _) => panic!("Expected position to be set for the task!"),
RenderTaskLocation::Dynamic(Some((origin, _, layer)), size) => (DeviceIntRect::new(origin, size), layer.0 as LayerIndex),
RenderTaskLocation::Dynamic(Some((origin, _)), size) => (DeviceIntRect::new(origin, size), 0),
RenderTaskLocation::TextureCache { rect, layer, .. } => (rect, layer),
RenderTaskLocation::PictureCache { .. } => {
panic!("bug: picture cache tasks should never be a source!");
@ -1340,7 +1340,7 @@ impl RenderTask {
pub fn get_target_texture(&self) -> CacheTextureId {
match self.location {
RenderTaskLocation::Dynamic(Some((_, texture_id, _)), _) => {
RenderTaskLocation::Dynamic(Some((_, texture_id)), _) => {
assert_ne!(texture_id, CacheTextureId::INVALID);
texture_id
}
@ -1368,8 +1368,8 @@ impl RenderTask {
// TODO(gw): Consider some kind of tag or other method
// to mark a task as unused explicitly. This
// would allow us to restore this debug check.
RenderTaskLocation::Dynamic(Some((origin, _, target_index)), size) => {
(DeviceIntRect::new(origin, size), target_index)
RenderTaskLocation::Dynamic(Some((origin, _)), size) => {
(DeviceIntRect::new(origin, size), RenderTargetIndex(0))
}
RenderTaskLocation::Dynamic(None, _) => {
(DeviceIntRect::zero(), RenderTargetIndex(0))

Просмотреть файл

@ -7,12 +7,11 @@ use api::ImageFormat;
use api::units::*;
use crate::internal_types::{CacheTextureId, FastHashMap};
use crate::render_backend::FrameId;
use crate::render_target::{RenderTargetKind, RenderTargetList, ColorRenderTarget};
use crate::render_target::{RenderTargetList, ColorRenderTarget};
use crate::render_target::{PictureCacheTarget, TextureCacheRenderTarget, AlphaRenderTarget};
use crate::render_task::{BlitSource, RenderTask, RenderTaskKind, RenderTaskData};
use crate::render_task::{RenderTaskLocation};
use crate::util::{VecHelper, Allocation};
use std::{cmp, usize, f32, i32, u32};
use std::{usize, f32, i32, u32};
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
@ -196,12 +195,8 @@ impl RenderTaskGraph {
let task_id = RenderTaskId {
index: task_index as u32,
};
let task = &self.tasks[task_index];
passes[pass_index as usize].add_render_task(
task_id,
task.get_dynamic_size(),
task.target_kind(),
&task.location,
);
}
}
@ -431,23 +426,7 @@ impl RenderPass {
pub fn add_render_task(
&mut self,
task_id: RenderTaskId,
size: DeviceIntSize,
target_kind: RenderTargetKind,
location: &RenderTaskLocation,
) {
// If this will be rendered to a dynamically-allocated region on an
// off-screen render target, update the max-encountered size. We don't
// need to do this for things drawn to the texture cache, since those
// don't affect our render target allocation.
if location.is_dynamic() {
let max_size = match target_kind {
RenderTargetKind::Color => &mut self.color.max_dynamic_size,
RenderTargetKind::Alpha => &mut self.alpha.max_dynamic_size,
};
max_size.width = cmp::max(max_size.width, size.width);
max_size.height = cmp::max(max_size.height, size.height);
}
self.tasks.push(task_id);
}
}
@ -639,6 +618,10 @@ fn dump_task_dependency_link(
use euclid::size2;
#[cfg(test)]
use smallvec::SmallVec;
#[cfg(test)]
use crate::render_task::RenderTaskLocation;
#[cfg(test)]
use crate::render_target::RenderTargetKind;
#[cfg(test)]
fn dyn_location(w: i32, h: i32) -> RenderTaskLocation {

Просмотреть файл

@ -1170,7 +1170,7 @@ impl TextureResolver {
fn new(device: &mut Device) -> TextureResolver {
let dummy_cache_texture = device
.create_texture(
ImageBufferKind::Texture2DArray,
ImageBufferKind::Texture2D,
ImageFormat::RGBA8,
1,
1,
@ -1233,7 +1233,7 @@ impl TextureResolver {
device.bind_external_texture(sampler, texture);
Swizzle::default()
}
TextureSource::TextureCache(index, _, swizzle) => {
TextureSource::TextureCache(index, swizzle) => {
let texture = &self.texture_cache_map[&index];
device.bind_texture(sampler, texture, swizzle);
swizzle
@ -1253,7 +1253,7 @@ impl TextureResolver {
TextureSource::External(..) => {
panic!("BUG: External textures cannot be resolved, they can only be bound.");
}
TextureSource::TextureCache(index, _, swizzle) => {
TextureSource::TextureCache(index, swizzle) => {
Some((&self.texture_cache_map[&index], swizzle))
}
}
@ -4117,7 +4117,6 @@ impl Renderer {
let texture_source = TextureSource::TextureCache(
readback.get_target_texture(),
ImageBufferKind::Texture2DArray,
Swizzle::default(),
);
let (cache_texture, _) = self.texture_resolver
@ -4210,7 +4209,6 @@ impl Renderer {
let (source_rect, layer) = source.get_target_rect();
let source_texture = TextureSource::TextureCache(
source.get_target_texture(),
ImageBufferKind::Texture2DArray,
Swizzle::default(),
);
(source_texture, layer.0, source_rect)
@ -6027,13 +6025,10 @@ impl Renderer {
}
}
for (target_index, target) in pass.alpha.targets.iter().enumerate() {
for target in &pass.alpha.targets {
results.stats.alpha_target_count += 1;
let texture_id = pass
.alpha
.texture_id
.expect("bug: no surface for pass");
let texture_id = target.texture_id();
let alpha_tex = self.texture_resolver
.texture_cache_map
@ -6042,7 +6037,7 @@ impl Renderer {
let draw_target = DrawTarget::from_texture(
alpha_tex,
target_index,
0,
false,
);
@ -6066,13 +6061,10 @@ impl Renderer {
let color_rt_info = RenderTargetInfo { has_depth: pass.color.needs_depth() };
for (target_index, target) in pass.color.targets.iter().enumerate() {
for target in &pass.color.targets {
results.stats.color_target_count += 1;
let texture_id = pass
.color
.texture_id
.expect("bug: no surface for pass");
let texture_id = target.texture_id();
let color_tex = self.texture_resolver
.texture_cache_map
@ -6086,7 +6078,7 @@ impl Renderer {
let draw_target = DrawTarget::from_texture(
color_tex,
target_index,
0,
target.needs_depth(),
);
@ -7090,6 +7082,7 @@ struct PlainTexture {
format: ImageFormat,
filter: TextureFilter,
has_depth: bool,
is_array: bool,
}
@ -7197,6 +7190,7 @@ impl Renderer {
format: texture.get_format(),
filter: texture.get_filter(),
has_depth: texture.supports_depth(),
is_array: texture.is_array(),
}
}
@ -7435,6 +7429,7 @@ impl Renderer {
format: descriptor.format,
filter,
has_depth: false,
is_array: false,
};
let t = Self::load_texture(
target,
@ -7464,8 +7459,13 @@ impl Renderer {
}
for (id, texture) in renderer.textures {
info!("\t{}", texture.data);
let target = if texture.is_array {
ImageBufferKind::Texture2DArray
} else {
ImageBufferKind::Texture2D
};
let t = Self::load_texture(
ImageBufferKind::Texture2DArray,
target,
&texture,
Some(RenderTargetInfo { has_depth: texture.has_depth }),
&root,

Просмотреть файл

@ -425,7 +425,6 @@ pub struct BlobImageRasterizerEpoch(usize);
/// Internal information about allocated render targets in the pool
struct RenderTarget {
size: DeviceIntSize,
num_layers: usize,
format: ImageFormat,
texture_id: CacheTextureId,
/// If true, this is currently leant out, and not available to other passes
@ -436,7 +435,7 @@ struct RenderTarget {
impl RenderTarget {
fn size_in_bytes(&self) -> usize {
let bpp = self.format.bytes_per_pixel() as usize;
self.num_layers * (self.size.width * self.size.height) as usize * bpp
(self.size.width * self.size.height) as usize * bpp
}
/// Returns true if this texture was used within `threshold` frames of
@ -1578,12 +1577,10 @@ impl ResourceCache {
pub fn get_or_create_render_target_from_pool(
&mut self,
size: DeviceIntSize,
num_layers: usize,
format: ImageFormat,
) -> CacheTextureId {
for target in &mut self.render_target_pool {
if target.size == size &&
target.num_layers == num_layers &&
target.format == format &&
!target.is_active {
// Found a target that's not currently in use which matches. Update
@ -1598,13 +1595,11 @@ impl ResourceCache {
let texture_id = self.texture_cache.alloc_render_target(
size,
num_layers,
format,
);
self.render_target_pool.push(RenderTarget {
size,
num_layers,
format,
texture_id,
is_active: true,

Просмотреть файл

@ -25,7 +25,7 @@ use webrender_build::shader::{ShaderFeatures, ShaderFeatureFlags, get_shader_fea
pub(crate) fn get_feature_string(kind: ImageBufferKind) -> &'static str {
match kind {
ImageBufferKind::Texture2D => "TEXTURE_2D",
ImageBufferKind::Texture2DArray => "",
ImageBufferKind::Texture2DArray => "TEXTURE_2D_ARRAY",
ImageBufferKind::TextureRect => "TEXTURE_RECT",
ImageBufferKind::TextureExternal => "TEXTURE_EXTERNAL",
}

Просмотреть файл

@ -833,7 +833,6 @@ impl TextureCache {
uv_rect_handle,
texture_id: TextureSource::TextureCache(
texture_id,
ImageBufferKind::Texture2D,
swizzle,
),
uv_rect,
@ -1128,7 +1127,6 @@ impl TextureCache {
pub fn alloc_render_target(
&mut self,
size: DeviceIntSize,
num_layers: usize,
format: ImageFormat,
) -> CacheTextureId {
let texture_id = self.next_id;
@ -1136,12 +1134,12 @@ impl TextureCache {
// Push a command to allocate device storage of the right size / format.
let info = TextureCacheAllocInfo {
target: ImageBufferKind::Texture2DArray,
target: ImageBufferKind::Texture2D,
width: size.width,
height: size.height,
format,
filter: TextureFilter::Linear,
layer_count: num_layers as i32,
layer_count: 1,
is_shared_cache: false,
has_depth: false,
};

Просмотреть файл

@ -109,7 +109,7 @@ pub fn get_shader_features(flags: ShaderFeatureFlags) -> ShaderFeatures {
}
// Image brush shaders
let mut texture_types = vec!["", "TEXTURE_2D"];
let mut texture_types = vec!["TEXTURE_2D_ARRAY", "TEXTURE_2D"];
if flags.contains(ShaderFeatureFlags::GL) {
texture_types.push("TEXTURE_RECT");
}

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 56 KiB

После

Ширина:  |  Высота:  |  Размер: 56 KiB

Просмотреть файл

@ -61,7 +61,7 @@ fuzzy(1,1) platform(linux) == two-shadows.yaml two-shadows.png
== shadow-clip.yaml shadow-clip-ref.yaml
== shadow-fast-clip.yaml shadow-fast-clip-ref.yaml
skip_on(android,device) == shadow-partial-glyph.yaml shadow-partial-glyph-ref.yaml # Fails on Pixel2
fuzzy(2,120) platform(linux) == shadow-transforms.yaml shadow-transforms.png
fuzzy(2,130) platform(linux) == shadow-transforms.yaml shadow-transforms.png
fuzzy(1,200) platform(linux) == raster-space.yaml raster-space.png
skip_on(android) skip_on(mac,>=10.14) != allow-subpixel.yaml allow-subpixel-ref.yaml # Android: we don't enable sub-px aa on this platform.
skip_on(android,device) == bg-color.yaml bg-color-ref.yaml # Fails on Pixel2

Двоичный файл не отображается.

До

Ширина:  |  Высота:  |  Размер: 93 KiB

После

Ширина:  |  Высота:  |  Размер: 93 KiB

Просмотреть файл

@ -1782,7 +1782,7 @@ fuzzy-if(skiaContent,0-1,0-5) == 956513-1.svg 956513-1-ref.svg
== 957770-1.svg 957770-1-ref.svg
== 960277-1.html 960277-1-ref.html
fuzzy-if(skiaContent,0-1,0-80) == 961887-1.html 961887-1-ref.html
fuzzy-if(webrender&&swgl,1-1,42-42) == 961887-2.html 961887-2-ref.html
== 961887-2.html 961887-2-ref.html
== 961887-3.html 961887-3-ref.html
pref(layout.css.overflow-clip-box.enabled,true) fuzzy(0-50,0-145) fuzzy-if(asyncPan&&!layersGPUAccelerated,0-102,0-3712) fuzzy-if(webrender,0-255,0-180) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == 966992-1.html 966992-1-ref.html # Bug 1392106
== 966510-1.html 966510-1-ref.html