.
diff --git a/sparse_strips/vello_dev_macros/src/test.rs b/sparse_strips/vello_dev_macros/src/test.rs index 2517367..267cb61 100644 --- a/sparse_strips/vello_dev_macros/src/test.rs +++ b/sparse_strips/vello_dev_macros/src/test.rs
@@ -31,9 +31,8 @@ skip_multithreaded: bool, /// Whether the test should not be run on the GPU (`vello_hybrid`). skip_hybrid: bool, - /// Whether `vello_hybrid` should generate the reference image instead of the scalar f32 CPU - /// renderer. - hybrid_reference: bool, + /// Whether only `vello_hybrid` should run and generate the reference image. + hybrid_only: bool, /// The maximum number of pixels that are allowed to completely deviate from the reference /// images. This attribute mainly exists because there are some test cases (like gradients), /// where, due to floating point inaccuracies, some pixels might land on a different color @@ -59,7 +58,7 @@ skip_cpu: false, skip_multithreaded: false, skip_hybrid: false, - hybrid_reference: false, + hybrid_only: false, no_ref: false, glyph: false, diff_pixels: 0, @@ -155,7 +154,7 @@ skip_cpu, skip_multithreaded, mut skip_hybrid, - hybrid_reference, + hybrid_only, ignore_reason, no_ref, glyph, @@ -217,8 +216,8 @@ || input_fn_name_str.contains("mask") }; assert!( - !(hybrid_reference && skip_hybrid), - "`hybrid_reference` cannot be combined with `skip_hybrid`" + !(hybrid_only && skip_hybrid), + "`hybrid_only` cannot be combined with `skip_hybrid`" ); let empty_snippet = quote! {}; @@ -332,7 +331,7 @@ f32_fn_name_str_scalar, input_fn_name_str.clone(), cpu_f32_tolerance_scalar, - !hybrid_reference, + !hybrid_only, 0, quote! {"fallback"}, skip_cpu, @@ -356,7 +355,7 @@ f32_fn_name_wasm_str, input_fn_name_str.clone(), cpu_f32_tolerance_scalar, - !hybrid_reference, + !hybrid_only, 0, wasm_simd_level, skip_cpu, @@ -471,7 +470,7 @@ cached_cpu_f32_fn_name_str, cached_reference_test_name.clone(), cpu_f32_tolerance_scalar, - !hybrid_reference, + !hybrid_only, 0, quote! {"fallback"}, skip_cpu, @@ -495,7 +494,7 @@ #invoke_cached_test ctx.flush(); if !#no_ref { - check_ref(&mut ctx, #cached_reference_test_name, #cached_hybrid_fn_name_str, #hybrid_tolerance, #diff_pixels, #hybrid_reference, #reference_image_name); + check_ref(&mut ctx, #cached_reference_test_name, #cached_hybrid_fn_name_str, #hybrid_tolerance, #diff_pixels, #hybrid_only, #reference_image_name); } } } @@ -545,7 +544,7 @@ #invoke_test ctx.flush(); if !#no_ref { - check_ref(&mut ctx, #input_fn_name_str, #hybrid_fn_name_str, #hybrid_tolerance, #diff_pixels, #hybrid_reference, #reference_image_name); + check_ref(&mut ctx, #input_fn_name_str, #hybrid_fn_name_str, #hybrid_tolerance, #diff_pixels, #hybrid_only, #reference_image_name); } } @@ -606,7 +605,10 @@ "skip_cpu" => args.skip_cpu = true, "skip_multithreaded" => args.skip_multithreaded = true, "skip_hybrid" => args.skip_hybrid = true, - "hybrid_reference" => args.hybrid_reference = true, + "hybrid_only" => { + args.skip_cpu = true; + args.hybrid_only = true; + } "no_ref" => args.no_ref = true, "glyph" => args.glyph = true, "ignore" => {
diff --git a/sparse_strips/vello_hybrid/src/render/common.rs b/sparse_strips/vello_hybrid/src/render/common.rs index 92c40b2..372382e 100644 --- a/sparse_strips/vello_hybrid/src/render/common.rs +++ b/sparse_strips/vello_hybrid/src/render/common.rs
@@ -579,7 +579,8 @@ ((x as u32) << 16) | (y as u32) } -/// Pack image `quality`, extend modes, and `atlas_index` into a single u32. +/// Pack image `quality`, extend modes, `atlas_index`, and source type into a single u32. +/// `is_external`: stored in bit 14 /// `atlas_index`: stored in bits 6-13 (8 bits, supports up to 256 atlases) /// `extend_y`: stored in bits 4-5 (2 bits) /// `extend_x`: stored in bits 2-3 (2 bits) @@ -590,12 +591,17 @@ extend_x: u32, extend_y: u32, atlas_index: u32, + is_external: bool, ) -> u32 { debug_assert!(extend_x <= 3, "extend_x must be 0-3 (2 bits)"); debug_assert!(extend_y <= 3, "extend_y must be 0-3 (2 bits)"); debug_assert!(quality <= 3, "quality must be 0-3 (2 bits)"); debug_assert!(atlas_index <= 255, "atlas_index must be 0-255 (8 bits)"); - (atlas_index << 6) | (extend_y << 4) | (extend_x << 2) | quality + (u32::from(is_external) << 14) + | (atlas_index << 6) + | (extend_y << 4) + | (extend_x << 2) + | quality } /// Pack an optional [`Tint`](vello_common::paint::Tint) into a (`tint_color_u32`, `tint_mode_u32`) pair for the GPU.
diff --git a/sparse_strips/vello_hybrid/src/render/webgl.rs b/sparse_strips/vello_hybrid/src/render/webgl.rs index c52d56b..fee372c 100644 --- a/sparse_strips/vello_hybrid/src/render/webgl.rs +++ b/sparse_strips/vello_hybrid/src/render/webgl.rs
@@ -86,8 +86,6 @@ transform: [0.0; 6], }); -const EXTERNAL_IMAGE_SOURCE_FLAG: u32 = 1 << 14; - /// Texture unit the strip program samples external textures from. const EXTERNAL_TEXTURE_UNIT: u32 = 5; @@ -782,6 +780,7 @@ image.sampler.x_extend as u32, image.sampler.y_extend as u32, image_resource.atlas_id.as_u32(), + false, ); let (tint, tint_mode) = pack_tint(image.tint); @@ -806,7 +805,8 @@ texture.sampler.x_extend as u32, texture.sampler.y_extend as u32, 0, - ) | EXTERNAL_IMAGE_SOURCE_FLAG; + true, + ); let (tint, tint_mode) = pack_tint(texture.tint); GpuEncodedPaint::Image(GpuEncodedImage { @@ -2509,9 +2509,7 @@ /// Draw `count` strip instances starting at `first_instance`, split into one draw per /// external texture run. /// - /// WebGL2 cannot offset the instance index at draw time, so each range is drawn by - /// re-specifying the vertex attribute pointers at that range's byte offset. The offsets are - /// restored to the start of the buffer before returning. + /// Strip attribute offsets are restored to the start of the buffer before returning. fn draw_strips( &self, external_texture_runs: &[ExternalTextureRun],
diff --git a/sparse_strips/vello_hybrid/src/render/wgpu.rs b/sparse_strips/vello_hybrid/src/render/wgpu.rs index a71825a..ea9ba9a 100644 --- a/sparse_strips/vello_hybrid/src/render/wgpu.rs +++ b/sparse_strips/vello_hybrid/src/render/wgpu.rs
@@ -83,8 +83,6 @@ transform: [0.0; 6], }); -const EXTERNAL_IMAGE_SOURCE_FLAG: u32 = 1 << 14; - /// Options for the renderer #[derive(Debug)] pub struct RenderTargetConfig { @@ -745,6 +743,7 @@ image.sampler.x_extend as u32, image.sampler.y_extend as u32, image_resource.atlas_id.as_u32(), + false, ); let (tint, tint_mode) = pack_tint(image.tint); @@ -769,7 +768,8 @@ image.sampler.x_extend as u32, image.sampler.y_extend as u32, 0, - ) | EXTERNAL_IMAGE_SOURCE_FLAG; + true, + ); let (tint, tint_mode) = pack_tint(image.tint); GpuEncodedPaint::Image(GpuEncodedImage {
diff --git a/sparse_strips/vello_sparse_tests/snapshots/external_texture_opaque_interleaving.png b/sparse_strips/vello_sparse_tests/snapshots/external_texture_opaque_interleaving.png new file mode 100644 index 0000000..8491b61 --- /dev/null +++ b/sparse_strips/vello_sparse_tests/snapshots/external_texture_opaque_interleaving.png
@@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a55e59bab17dd19dd33efdff70b089aea3f5611003b2f7e288a6abb1d3aac54 +size 153
diff --git a/sparse_strips/vello_sparse_tests/snapshots/external_texture_runs_with_opaque_prefix.png b/sparse_strips/vello_sparse_tests/snapshots/external_texture_runs_with_opaque_prefix.png new file mode 100644 index 0000000..cb20bdc --- /dev/null +++ b/sparse_strips/vello_sparse_tests/snapshots/external_texture_runs_with_opaque_prefix.png
@@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd506155eb000faa21fda117e7f0c65578851d87e966827e7197bcc273227443 +size 164
diff --git a/sparse_strips/vello_sparse_tests/tests/external_texture.rs b/sparse_strips/vello_sparse_tests/tests/external_texture.rs index 4f925a8..e7f262d 100644 --- a/sparse_strips/vello_sparse_tests/tests/external_texture.rs +++ b/sparse_strips/vello_sparse_tests/tests/external_texture.rs
@@ -86,7 +86,7 @@ ctx.fill_path(&circle.to_path(0.1)); } - #[vello_test(width = 96, height = 96, skip_cpu, hybrid_reference)] + #[vello_test(width = 96, height = 96, hybrid_only)] fn external_texture_composite(ctx: &mut impl Renderer) { let texture_id = ctx.register_external_texture(load_image!("glyphs_colr_noto")); ctx.draw_texture_rects( @@ -109,7 +109,37 @@ ); } - #[vello_test(skip_cpu, hybrid_reference)] + #[vello_test(width = 96, height = 96, hybrid_only)] + fn external_texture_opaque_interleaving(ctx: &mut impl Renderer) { + let texture_id = ctx.register_external_texture(solid_pixmap(192, 0, 0, 192)); + + ctx.set_paint(AlphaColor::from_rgba8(0, 0, 255, 255)); + ctx.fill_rect(&Rect::new(8., 8., 64., 64.)); + + ctx.draw_texture_rects(texture_id, ImageQuality::Low, texture_rect_at(28., 28.)); + + ctx.set_paint(AlphaColor::from_rgba8(0, 255, 0, 255)); + ctx.fill_rect(&Rect::new(48., 16., 88., 56.)); + } + + #[vello_test(width = 96, height = 96, hybrid_only)] + fn external_texture_runs_with_opaque_prefix(ctx: &mut impl Renderer) { + let red_texture = ctx.register_external_texture(solid_pixmap(255, 0, 0, 255)); + let green_texture = ctx.register_external_texture(solid_pixmap(0, 255, 0, 255)); + + ctx.set_paint(AlphaColor::from_rgba8(32, 32, 32, 255)); + ctx.fill_rect(&Rect::new(4., 4., 92., 92.)); + + ctx.draw_texture_rects(red_texture, ImageQuality::Low, texture_rect_at(8., 8.)); + + ctx.set_paint(AlphaColor::from_rgba8(255, 255, 255, 128)); + ctx.fill_rect(&Rect::new(24., 24., 72., 72.)); + + ctx.draw_texture_rects(green_texture, ImageQuality::Low, texture_rect_at(28., 28.)); + ctx.draw_texture_rects(red_texture, ImageQuality::Low, texture_rect_at(48., 48.)); + } + + #[vello_test(hybrid_only)] fn external_texture_atlas_interleaving(ctx: &mut impl Renderer) { let atlas_red = ctx.get_image_source(solid_pixmap(254, 0, 0, 254)); let external_green = ctx.register_external_texture(solid_pixmap(0, 254, 0, 254)); @@ -138,7 +168,7 @@ draw_atlas_rect(ctx, atlas_magenta, Rect::new(66., 66., 90., 90.)); } - #[vello_test(skip_cpu, hybrid_reference)] + #[vello_test(hybrid_only)] fn external_texture_layer_before_external(ctx: &mut impl Renderer) { let texture_id = ctx.register_external_texture(solid_pixmap(128, 0, 0, 128)); @@ -152,7 +182,7 @@ ctx.pop_layer(); } - #[vello_test(skip_cpu, hybrid_reference)] + #[vello_test(hybrid_only)] fn external_texture_external_before_layer(ctx: &mut impl Renderer) { let texture_id = ctx.register_external_texture(solid_pixmap(0, 255, 0, 255)); @@ -166,7 +196,7 @@ ctx.pop_layer(); } - #[vello_test(skip_cpu, hybrid_reference)] + #[vello_test(hybrid_only)] fn external_texture_layer_circle_orders(ctx: &mut impl Renderer) { let blue_texture = ctx.register_external_texture(solid_pixmap(0, 0, 255, 255)); let red_texture = ctx.register_external_texture(solid_pixmap(255, 0, 0, 255)); @@ -243,7 +273,7 @@ ); } - #[vello_test(width = 96, height = 96, skip_cpu, hybrid_reference)] + #[vello_test(width = 96, height = 96, hybrid_only)] fn external_texture_skewed(ctx: &mut impl Renderer) { let texture_id = ctx.register_external_texture(load_image!("glyphs_colr_noto")); ctx.draw_texture_rects( @@ -256,7 +286,7 @@ ); } - #[vello_test(width = 96, height = 96, skip_cpu, hybrid_reference)] + #[vello_test(width = 96, height = 96, hybrid_only)] fn external_texture_clipped(ctx: &mut impl Renderer) { let texture_id = ctx.register_external_texture(load_image!("glyphs_colr_noto")); let clip = Circle::new((48., 48.), 24.).to_path(0.1); @@ -279,13 +309,7 @@ ctx.pop_layer(); } - #[vello_test( - width = 96, - height = 96, - skip_cpu, - hybrid_reference, - hybrid_tolerance = 2 - )] + #[vello_test(width = 96, height = 96, hybrid_only, hybrid_tolerance = 2)] fn external_texture_blurred(ctx: &mut impl Renderer) { let texture_id = ctx.register_external_texture(load_image!("glyphs_colr_noto")); let blur = Filter::from_primitive(FilterPrimitive::GaussianBlur { @@ -305,7 +329,7 @@ ctx.pop_layer(); } - #[vello_test(width = 192, height = 132, skip_cpu, hybrid_reference)] + #[vello_test(width = 192, height = 132, hybrid_only)] fn external_texture_many_sprites(ctx: &mut impl Renderer) { let texture_id = ctx.register_external_texture(load_image!("glyphs_colr_noto")); let placements = [ @@ -333,13 +357,7 @@ ); } - #[vello_test( - width = 96, - height = 96, - skip_cpu, - hybrid_reference, - hybrid_tolerance = 2 - )] + #[vello_test(width = 96, height = 96, hybrid_only, hybrid_tolerance = 2)] fn external_texture_with_scene_transform(ctx: &mut impl Renderer) { let texture_id = ctx.register_external_texture(load_image!("glyphs_colr_noto"));