Skip to content

Commit

Permalink
Refactor the rectangle fragment shader to work around a suspected ang…
Browse files Browse the repository at this point in the history
…le/mesa bug (#3948)

### What
:see_no_evil: 

This mitigates the crash reported in:
* #3931
but should be considered a workaround, rather than a proper fix.

After a fair bit of shooting in the dark, our best working theory is
that the there is a magic size threshold at which shaders fail to link
on angle+mesa.

On that hunch, I refactored this shader and am no longer seeing the
crash.

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested [demo.rerun.io](https://demo.rerun.io/pr/3948) (if
applicable)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG

- [PR Build Summary](https://build.rerun.io/pr/3948)
- [Docs
preview](https://rerun.io/preview/aae3dae91c18d6697fc5be06d84e0f9ca16d0ba9/docs)
<!--DOCS-PREVIEW-->
- [Examples
preview](https://rerun.io/preview/aae3dae91c18d6697fc5be06d84e0f9ca16d0ba9/examples)
<!--EXAMPLES-PREVIEW-->
- [Recent benchmark results](https://ref.rerun.io/dev/bench/)
- [Wasm size tracking](https://ref.rerun.io/dev/sizes/)
  • Loading branch information
jleibs authored Oct 23, 2023
1 parent d428f21 commit a8b581c
Showing 1 changed file with 57 additions and 40 deletions.
97 changes: 57 additions & 40 deletions crates/re_renderer/shader/rectangle_fs.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
#import <./utils/srgb.wgsl>
#import <./decodings.wgsl>

// WARNING! Adding anything else to this shader is very likely to push us over a size threshold that
// causes the failure reported in: https://github.com/rerun-io/rerun/issues/3931
// Make sure any changes are tested in Chrome on Linux using the Intel Mesa driver.

fn is_magnifying(pixel_coord: Vec2) -> bool {
return fwidth(pixel_coord.x) < 1.0;
}
Expand Down Expand Up @@ -47,78 +51,91 @@ fn clamp_to_edge_nearest_neighbor(coord: Vec2, texture_dimension: Vec2) -> IVec2
return IVec2(clamp(floor(coord), Vec2(0.0), texture_dimension - Vec2(1.0)));
}

fn filter_bilinear(coord: Vec2, v00: Vec4, v01: Vec4, v10: Vec4, v11: Vec4) -> Vec4 {
let top = mix(v00, v10, fract(coord.x - 0.5));
let bottom = mix(v01, v11, fract(coord.x - 0.5));
fn decode_color_and_filter_bilinear(coord: Vec2, v00: Vec4, v01: Vec4, v10: Vec4, v11: Vec4) -> Vec4 {
let c00 = decode_color(v00);
let c01 = decode_color(v01);
let c10 = decode_color(v10);
let c11 = decode_color(v11);
let top = mix(c00, c10, fract(coord.x - 0.5));
let bottom = mix(c01, c11, fract(coord.x - 0.5));
return mix(top, bottom, fract(coord.y - 0.5));
}

@fragment
fn fs_main(in: VertexOut) -> @location(0) Vec4 {
// Sample the main texture:
var normalized_value: Vec4;

var texture_dimensions: Vec2;
if rect_info.sample_type == SAMPLE_TYPE_FLOAT {
texture_dimensions = Vec2(textureDimensions(texture_float).xy);
} else if rect_info.sample_type == SAMPLE_TYPE_SINT {
texture_dimensions = Vec2(textureDimensions(texture_sint).xy);
} else if rect_info.sample_type == SAMPLE_TYPE_UINT {
texture_dimensions = Vec2(textureDimensions(texture_uint).xy);
} else if rect_info.sample_type == SAMPLE_TYPE_NV12 {
texture_dimensions = Vec2(textureDimensions(texture_uint).xy);
}

let coord = in.texcoord * texture_dimensions;
let clamped_coord = clamp_to_edge_nearest_neighbor(coord, texture_dimensions);
let v00_coord = clamp_to_edge_nearest_neighbor(coord + vec2(-0.5, -0.5), texture_dimensions);
let v01_coord = clamp_to_edge_nearest_neighbor(coord + vec2(-0.5, 0.5), texture_dimensions);
let v10_coord = clamp_to_edge_nearest_neighbor(coord + vec2( 0.5, -0.5), texture_dimensions);
let v11_coord = clamp_to_edge_nearest_neighbor(coord + vec2( 0.5, 0.5), texture_dimensions);

if rect_info.sample_type == SAMPLE_TYPE_FLOAT {
let texture_dimensions = Vec2(textureDimensions(texture_float).xy);
let coord = in.texcoord * texture_dimensions;
if tex_filter(coord) == FILTER_NEAREST {
// nearest
normalized_value = decode_color(textureLoad(texture_float,
clamp_to_edge_nearest_neighbor(coord, texture_dimensions), 0));
} else {
// bilinear
let v00 = decode_color(textureLoad(texture_float, clamp_to_edge_nearest_neighbor(coord + vec2(-0.5, -0.5), texture_dimensions), 0));
let v01 = decode_color(textureLoad(texture_float, clamp_to_edge_nearest_neighbor(coord + vec2(-0.5, 0.5), texture_dimensions), 0));
let v10 = decode_color(textureLoad(texture_float, clamp_to_edge_nearest_neighbor(coord + vec2( 0.5, -0.5), texture_dimensions), 0));
let v11 = decode_color(textureLoad(texture_float, clamp_to_edge_nearest_neighbor(coord + vec2( 0.5, 0.5), texture_dimensions), 0));
normalized_value = filter_bilinear(coord, v00, v01, v10, v11);
let v00 = textureLoad(texture_float, v00_coord, 0);
let v01 = textureLoad(texture_float, v01_coord, 0);
let v10 = textureLoad(texture_float, v10_coord, 0);
let v11 = textureLoad(texture_float, v11_coord, 0);
normalized_value = decode_color_and_filter_bilinear(coord, v00, v01, v10, v11);
}
} else if rect_info.sample_type == SAMPLE_TYPE_SINT {
let texture_dimensions = Vec2(textureDimensions(texture_sint).xy);
let coord = in.texcoord * texture_dimensions;
}
else if rect_info.sample_type == SAMPLE_TYPE_SINT {
if tex_filter(coord) == FILTER_NEAREST {
// nearest
normalized_value = decode_color(Vec4(textureLoad(texture_sint,
clamp_to_edge_nearest_neighbor(coord, texture_dimensions), 0)));
normalized_value = decode_color(Vec4(textureLoad(texture_sint, clamped_coord, 0)));
} else {
// bilinear
let v00 = decode_color(Vec4(textureLoad(texture_sint, clamp_to_edge_nearest_neighbor(coord + vec2(-0.5, -0.5), texture_dimensions), 0)));
let v01 = decode_color(Vec4(textureLoad(texture_sint, clamp_to_edge_nearest_neighbor(coord + vec2(-0.5, 0.5), texture_dimensions), 0)));
let v10 = decode_color(Vec4(textureLoad(texture_sint, clamp_to_edge_nearest_neighbor(coord + vec2( 0.5, -0.5), texture_dimensions), 0)));
let v11 = decode_color(Vec4(textureLoad(texture_sint, clamp_to_edge_nearest_neighbor(coord + vec2( 0.5, 0.5), texture_dimensions), 0)));
normalized_value = filter_bilinear(coord, v00, v01, v10, v11);
let v00 = Vec4(textureLoad(texture_sint, v00_coord, 0));
let v01 = Vec4(textureLoad(texture_sint, v01_coord, 0));
let v10 = Vec4(textureLoad(texture_sint, v10_coord, 0));
let v11 = Vec4(textureLoad(texture_sint, v11_coord, 0));
normalized_value = decode_color_and_filter_bilinear(coord, v00, v01, v10, v11);
}
} else if rect_info.sample_type == SAMPLE_TYPE_UINT {
let texture_dimensions = Vec2(textureDimensions(texture_uint).xy);
let coord = in.texcoord * texture_dimensions;
}
else if rect_info.sample_type == SAMPLE_TYPE_UINT {
if tex_filter(coord) == FILTER_NEAREST {
// nearest
normalized_value = decode_color(Vec4(textureLoad(texture_uint,
clamp_to_edge_nearest_neighbor(coord, texture_dimensions), 0)));
normalized_value = decode_color(Vec4(textureLoad(texture_uint, clamped_coord, 0)));
} else {
// bilinear
let v00 = decode_color(Vec4(textureLoad(texture_uint, clamp_to_edge_nearest_neighbor(coord + vec2(-0.5, -0.5), texture_dimensions), 0)));
let v01 = decode_color(Vec4(textureLoad(texture_uint, clamp_to_edge_nearest_neighbor(coord + vec2(-0.5, 0.5), texture_dimensions), 0)));
let v10 = decode_color(Vec4(textureLoad(texture_uint, clamp_to_edge_nearest_neighbor(coord + vec2( 0.5, -0.5), texture_dimensions), 0)));
let v11 = decode_color(Vec4(textureLoad(texture_uint, clamp_to_edge_nearest_neighbor(coord + vec2( 0.5, 0.5), texture_dimensions), 0)));
normalized_value = filter_bilinear(coord, v00, v01, v10, v11);
let v00 = Vec4(textureLoad(texture_uint, v00_coord, 0));
let v01 = Vec4(textureLoad(texture_uint, v01_coord, 0));
let v10 = Vec4(textureLoad(texture_uint, v10_coord, 0));
let v11 = Vec4(textureLoad(texture_uint, v11_coord, 0));
normalized_value = decode_color_and_filter_bilinear(coord, v00, v01, v10, v11);
}
} else if rect_info.sample_type == SAMPLE_TYPE_NV12 {
let texture_dimensions = Vec2(textureDimensions(texture_uint).xy);
let coord = in.texcoord * texture_dimensions;
if tex_filter(coord) == FILTER_NEAREST {
// nearest
normalized_value = decode_color(Vec4(decode_nv12(texture_uint,
clamp_to_edge_nearest_neighbor(coord, texture_dimensions))));
normalized_value = decode_color(Vec4(decode_nv12(texture_uint, clamped_coord)));
} else {
// bilinear
let v00 = decode_color(Vec4(decode_nv12(texture_uint, clamp_to_edge_nearest_neighbor(coord + vec2(-0.5, -0.5), texture_dimensions))));
let v01 = decode_color(Vec4(decode_nv12(texture_uint, clamp_to_edge_nearest_neighbor(coord + vec2(-0.5, 0.5), texture_dimensions))));
let v10 = decode_color(Vec4(decode_nv12(texture_uint, clamp_to_edge_nearest_neighbor(coord + vec2( 0.5, -0.5), texture_dimensions))));
let v11 = decode_color(Vec4(decode_nv12(texture_uint, clamp_to_edge_nearest_neighbor(coord + vec2( 0.5, 0.5), texture_dimensions))));
normalized_value = filter_bilinear(coord, v00, v01, v10, v11);
let v00 = decode_nv12(texture_uint, v00_coord);
let v01 = decode_nv12(texture_uint, v01_coord);
let v10 = decode_nv12(texture_uint, v10_coord);
let v11 = decode_nv12(texture_uint, v11_coord);
normalized_value = decode_color_and_filter_bilinear(coord, v00, v01, v10, v11);
}
}

else {
return ERROR_RGBA; // unknown sample type
}
Expand Down

0 comments on commit a8b581c

Please sign in to comment.