-
Notifications
You must be signed in to change notification settings - Fork 366
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce image data conversion pipeline, taking over existing YUV co…
…nversions (#7640) ### What * Major part of #7608 * Related to #3931 * since it makes the rectangle shader smaller which kept acting up in the past via `pixi run -e py python ./tests/python/chroma_downsample_image/main.py`: https://rerun.io/viewer/pr/7640?url=https%3A%2F%2Fstatic.rerun.io%2Frrd%2F0.19%2Fchroma_formats_ad9697d05933f4104fbbe66af23073ad4e9e4a58.rrd ![image](https://github.com/user-attachments/assets/76756c5f-75db-44b7-8db0-f04256f72e3a) The new functionality is tightly integrated into `TextureManager2D` which now ingests all incoming data via a new internal method `transfer_image_data_to_texture`. This in turn takes care of data upload via `GpuReadCpuWriteBelt` (new! previously, we would use `queue.write_texture` in this case) and may if needed run gpu based conversion. Gpu based conversion is for convenience implemented like a `Renderer` - while it is not _used_ like a typical `Renderer`, the lifecycle (create lazily once, store on context, feed with data bundles [...]) was so similar that it made sense to me to use this existing pattern even though it's not a perfect match. **A curious sideeffect of this is that you can now put chroma downsampled textures on custom meshes!** Next steps: * support formats required for AV1 * while on it, check if things could get simpler by us * move BGR handling into the new pipeline * revisit the re_renderer sided input data description. Not sure if I'm happy about it drifting away from the user facing one! * once we're there we're also very close to get rid of `SourceImageDataFormat::WgpuCompatible`. But it's not strictly necessary, this might yet prove a convenient loophole, although its presence makes me a little bit nervous (details see code comments) 🤔 * consider exposing color primaries to public API * the only thing keeping us from it is adding a new enum to the color format! * should it be called "primaries" or "color space" 🤔 ### Checklist * [x] test on web Mac Chrome/Firefox/Safari * [x] test on web Window Chrome/Firefox * [ ] test on web Firefox Chrome/Firefox (@jleibs plz 🥺 ) * [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 the web demo (if applicable): * Using examples from latest `main` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7640?manifest_url=https://app.rerun.io/version/main/examples_manifest.json) * Using full set of examples from `nightly` build: [rerun.io/viewer](https://rerun.io/viewer/pr/7640?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json) * [x] The PR title and labels are set such as to maximize their usefulness for the next release's CHANGELOG * [x] If applicable, add a new check to the [release checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)! * [x] If have noted any breaking changes to the log API in `CHANGELOG.md` and the migration guide - [PR Build Summary](https://build.rerun.io/pr/7640) - [Recent benchmark results](https://build.rerun.io/graphs/crates.html) - [Wasm size tracking](https://build.rerun.io/graphs/sizes.html) To run all checks from `main`, comment on the PR with `@rerun-bot full-check`.
- Loading branch information
Showing
21 changed files
with
984 additions
and
475 deletions.
There are no files selected for viewing
112 changes: 112 additions & 0 deletions
112
crates/viewer/re_renderer/shader/conversions/yuv_converter.wgsl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
#import <../types.wgsl> | ||
#import <../screen_triangle_vertex.wgsl> | ||
|
||
struct UniformBuffer { | ||
format: u32, | ||
primaries: u32, | ||
target_texture_size: vec2u, | ||
}; | ||
|
||
@group(0) @binding(0) | ||
var<uniform> uniform_buffer: UniformBuffer; | ||
|
||
@group(0) @binding(1) | ||
var input_texture: texture_2d<u32>; | ||
|
||
|
||
const YUV_LAYOUT_Y_UV = 0u; | ||
const YUV_LAYOUT_YUYV16 = 1u; | ||
|
||
const PRIMARIES_BT601 = 0u; | ||
const PRIMARIES_BT709 = 1u; | ||
|
||
|
||
/// Returns sRGB from YUV color. | ||
/// | ||
/// This conversion mirrors the function in `crates/store/re_types/src/datatypes/tensor_data_ext.rs` | ||
/// | ||
/// Specifying the color standard should be exposed in the future [#3541](https://github.com/rerun-io/rerun/pull/3541) | ||
fn srgb_from_yuv(yuv: vec3f, primaries: u32) -> vec3f { | ||
// rescale YUV values | ||
let y = (yuv[0] - 16.0) / 219.0; | ||
let u = (yuv[1] - 128.0) / 224.0; | ||
let v = (yuv[2] - 128.0) / 224.0; | ||
|
||
var rgb: vec3f; | ||
|
||
switch (primaries) { | ||
// BT.601 (aka. SDTV, aka. Rec.601). wiki: https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion | ||
// Also note according to https://en.wikipedia.org/wiki/SRGB#sYCC_extended-gamut_transformation | ||
// > Although the RGB color primaries are based on BT.709, | ||
// > the equations for transformation from sRGB to sYCC and vice versa are based on BT.601. | ||
case PRIMARIES_BT601: { | ||
rgb.r = y + 1.402 * v; | ||
rgb.g = y - 0.344 * u - 0.714 * v; | ||
rgb.b = y + 1.772 * u; | ||
} | ||
|
||
// BT.709 (aka. HDTV, aka. Rec.709). wiki: https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.709_conversion | ||
case PRIMARIES_BT709: { | ||
rgb.r = y + 1.575 * v; | ||
rgb.g = y - 0.187 * u - 0.468 * v; | ||
rgb.b = y + 1.856 * u; | ||
} | ||
|
||
default: { | ||
rgb = ERROR_RGBA.rgb; | ||
} | ||
} | ||
|
||
return clamp(rgb, vec3f(0.0), vec3f(1.0)); | ||
} | ||
|
||
/// Extracts YUV data from a chroma subsampling encoded texture at specific coordinates. | ||
/// | ||
/// See also `enum YuvPixelLayout` in `yuv_converter.rs for a specification of | ||
/// the expected data layout. | ||
fn sample_yuv(yuv_layout: u32, texture: texture_2d<u32>, coords: vec2f) -> vec3f { | ||
let texture_dim = vec2f(textureDimensions(texture).xy); | ||
var yuv: vec3f; | ||
|
||
switch (yuv_layout) { | ||
case YUV_LAYOUT_Y_UV: { | ||
let uv_offset = u32(floor(texture_dim.y / 1.5)); | ||
let uv_row = u32(coords.y / 2); | ||
var uv_col = u32(coords.x / 2) * 2u; | ||
|
||
yuv[0] = f32(textureLoad(texture, vec2u(coords), 0).r); | ||
yuv[1] = f32(textureLoad(texture, vec2u(u32(uv_col), uv_offset + uv_row), 0).r); | ||
yuv[2] = f32(textureLoad(texture, vec2u((u32(uv_col) + 1u), uv_offset + uv_row), 0).r); | ||
} | ||
|
||
case YUV_LAYOUT_YUYV16: { | ||
// texture is 2 * width * height | ||
// every 4 bytes is 2 pixels | ||
let uv_row = u32(coords.y); | ||
// multiply by 2 because the width is multiplied by 2 | ||
let y_col = u32(coords.x) * 2u; | ||
yuv[0] = f32(textureLoad(texture, vec2u(y_col, uv_row), 0).r); | ||
|
||
// at odd pixels we're in the second half of the yuyu block, offset back by 2 | ||
let uv_col = y_col - u32(coords.x % 2) * 2u; | ||
yuv[1] = f32(textureLoad(texture, vec2u(uv_col + 1u, uv_row), 0).r); | ||
yuv[2] = f32(textureLoad(texture, vec2u(uv_col + 3u, uv_row), 0).r); | ||
} | ||
|
||
default: { | ||
yuv = vec3f(0.0, 0.0, 0.0); // ERROR_RGBA doesn't apply here. | ||
} | ||
} | ||
|
||
return yuv; | ||
} | ||
|
||
@fragment | ||
fn fs_main(in: FragmentInput) -> @location(0) vec4f { | ||
let coords = vec2f(uniform_buffer.target_texture_size) * in.texcoord; | ||
|
||
let yuv = sample_yuv(uniform_buffer.format, input_texture, coords); | ||
let rgb = srgb_from_yuv(yuv, uniform_buffer.primaries); | ||
|
||
return vec4f(rgb, 1.0); | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.