Skip to content

Commit

Permalink
Test CopyEI2T and GPUExternalTexture convert video contents to displa…
Browse files Browse the repository at this point in the history
…y-p3 color space (#3189)

* Test GPUExternalTexture sampling in display-p3 color space

This PR refactor video related utils and add tests to cover
GPUExternalTextureDescriptor:colorSpace = 'display-p3'.

* Address comments

* Add readonly annotations, remove unwanted mutation

---------

Co-authored-by: Kai Ninomiya <[email protected]>
  • Loading branch information
shaoboyan and kainino0x authored Nov 28, 2023
1 parent 4f3cbf4 commit 7da5c3c
Show file tree
Hide file tree
Showing 5 changed files with 322 additions and 254 deletions.
3 changes: 1 addition & 2 deletions src/webgpu/listing_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -2000,8 +2000,7 @@
"webgpu:web_platform,copyToTexture,image:from_image:*": { "subcaseMS": 21.869 },
"webgpu:web_platform,copyToTexture,video:copy_from_video:*": { "subcaseMS": 25.101 },
"webgpu:web_platform,external_texture,video:importExternalTexture,compute:*": { "subcaseMS": 36.270 },
"webgpu:web_platform,external_texture,video:importExternalTexture,sample:*": { "subcaseMS": 33.380 },
"webgpu:web_platform,external_texture,video:importExternalTexture,sampleWithRotationMetadata:*": { "subcaseMS": 34.968 },
"webgpu:web_platform,external_texture,video:importExternalTexture,sample:*": { "subcaseMS": 34.968 },
"webgpu:web_platform,external_texture,video:importExternalTexture,sampleWithVideoFrameWithVisibleRectParam:*": { "subcaseMS": 29.160 },
"webgpu:web_platform,worker,worker:worker:*": { "subcaseMS": 245.901 },
"_end": ""
Expand Down
27 changes: 5 additions & 22 deletions src/webgpu/util/color_space_conversion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,7 @@ function XYZ_to_lin_P3(XYZ: Array<Array<number>>) {
* https://drafts.csswg.org/css-color/#predefined-to-predefined
* display-p3 and sRGB share the same white points.
*/
export function displayP3ToSrgb(pixel: { R: number; G: number; B: number; A: number }): {
R: number;
G: number;
B: number;
A: number;
} {
export function displayP3ToSrgb(pixel: Readonly<RGBA>): RGBA {
assert(
pixel.R !== undefined && pixel.G !== undefined && pixel.B !== undefined,
'color space conversion requires all of R, G and B components'
Expand All @@ -161,11 +156,7 @@ export function displayP3ToSrgb(pixel: { R: number; G: number; B: number; A: num
rgbVec = [rgbMatrix[0][0], rgbMatrix[1][0], rgbMatrix[2][0]];
rgbVec = gam_sRGB(rgbVec);

pixel.R = rgbVec[0];
pixel.G = rgbVec[1];
pixel.B = rgbVec[2];

return pixel;
return { R: rgbVec[0], G: rgbVec[1], B: rgbVec[2], A: pixel.A };
}
/**
* @returns the converted pixels in `{R: number, G: number, B: number, A: number}`.
Expand All @@ -174,12 +165,7 @@ export function displayP3ToSrgb(pixel: { R: number; G: number; B: number; A: num
* https://drafts.csswg.org/css-color/#predefined-to-predefined
* display-p3 and sRGB share the same white points.
*/
export function srgbToDisplayP3(pixel: { R: number; G: number; B: number; A: number }): {
R: number;
G: number;
B: number;
A: number;
} {
export function srgbToDisplayP3(pixel: Readonly<RGBA>): RGBA {
assert(
pixel.R !== undefined && pixel.G !== undefined && pixel.B !== undefined,
'color space conversion requires all of R, G and B components'
Expand All @@ -192,13 +178,10 @@ export function srgbToDisplayP3(pixel: { R: number; G: number; B: number; A: num
rgbVec = [rgbMatrix[0][0], rgbMatrix[1][0], rgbMatrix[2][0]];
rgbVec = gam_P3(rgbVec);

pixel.R = rgbVec[0];
pixel.G = rgbVec[1];
pixel.B = rgbVec[2];

return pixel;
return { R: rgbVec[0], G: rgbVec[1], B: rgbVec[2], A: pixel.A };
}

export type RGBA = { R: number; G: number; B: number; A: number };
type InPlaceColorConversion = (rgba: {
R: number;
G: number;
Expand Down
75 changes: 53 additions & 22 deletions src/webgpu/web_platform/copyToTexture/video.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
export const description = `
copyToTexture with HTMLVideoElement and VideoFrame.
- videos with various encodings/formats (webm vp8, webm vp9, ogg theora, mp4), color spaces
(bt.601, bt.709, bt.2020)
- videos with various encodings/formats (webm vp8, webm vp9, ogg theora, mp4), video color spaces
(bt.601, bt.709, bt.2020) and dst color spaces(display-p3, srgb).
TODO: Test video in BT.2020 color space
`;

import { makeTestGroup } from '../../../common/framework/test_group.js';
Expand All @@ -11,7 +13,10 @@ import {
startPlayingAndWaitForVideo,
getVideoElement,
getVideoFrameFromVideoElement,
kVideoExpectations,
convertToUnorm8,
kPredefinedColorSpace,
kVideoNames,
kVideoInfo,
} from '../../web_platform/util.js';

const kFormat = 'rgba8unorm';
Expand All @@ -36,17 +41,17 @@ It creates HTMLVideoElement with videos under Resource folder.
- Valid 'flipY' config in 'GPUImageCopyExternalImage' (named 'srcDoFlipYDuringCopy' in cases)
- TODO: partial copy tests should be added
- TODO: all valid dstColorFormat tests should be added.
- TODO: dst color space tests need to be added
`
)
.params(u =>
u //
.combineWithParams(kVideoExpectations)
.combine('videoName', kVideoNames)
.combine('sourceType', ['VideoElement', 'VideoFrame'] as const)
.combine('srcDoFlipYDuringCopy', [true, false])
.combine('dstColorSpace', kPredefinedColorSpace)
)
.fn(async t => {
const { videoName, sourceType, srcDoFlipYDuringCopy } = t.params;
const { videoName, sourceType, srcDoFlipYDuringCopy, dstColorSpace } = t.params;

if (sourceType === 'VideoFrame' && typeof VideoFrame === 'undefined') {
t.skip('WebCodec is not supported');
Expand Down Expand Up @@ -88,27 +93,53 @@ It creates HTMLVideoElement with videos under Resource folder.
{ width, height, depthOrArrayLayers: 1 }
);

const expect = kVideoInfo[videoName].presentColors[dstColorSpace];

if (srcDoFlipYDuringCopy) {
t.expectSinglePixelComparisonsAreOkInTexture({ texture: dstTexture }, [
// Top-left should be blue.
{ coord: { x: width * 0.25, y: height * 0.25 }, exp: t.params._blueExpectation },
// Top-right should be green.
{ coord: { x: width * 0.75, y: height * 0.25 }, exp: t.params._greenExpectation },
// Bottom-left should be yellow.
{ coord: { x: width * 0.25, y: height * 0.75 }, exp: t.params._yellowExpectation },
// Bottom-right should be red.
{ coord: { x: width * 0.75, y: height * 0.75 }, exp: t.params._redExpectation },
// Flipped top-left.
{
coord: { x: width * 0.25, y: height * 0.25 },
exp: convertToUnorm8(expect.bottomLeftColor),
},
// Flipped top-right.
{
coord: { x: width * 0.75, y: height * 0.25 },
exp: convertToUnorm8(expect.bottomRightColor),
},
// Flipped bottom-left.
{
coord: { x: width * 0.25, y: height * 0.75 },
exp: convertToUnorm8(expect.topLeftColor),
},
// Flipped bottom-right.
{
coord: { x: width * 0.75, y: height * 0.75 },
exp: convertToUnorm8(expect.topRightColor),
},
]);
} else {
t.expectSinglePixelComparisonsAreOkInTexture({ texture: dstTexture }, [
// Top-left should be yellow.
{ coord: { x: width * 0.25, y: height * 0.25 }, exp: t.params._yellowExpectation },
// Top-right should be red.
{ coord: { x: width * 0.75, y: height * 0.25 }, exp: t.params._redExpectation },
// Bottom-left should be blue.
{ coord: { x: width * 0.25, y: height * 0.75 }, exp: t.params._blueExpectation },
// Bottom-right should be green.
{ coord: { x: width * 0.75, y: height * 0.75 }, exp: t.params._greenExpectation },
// Top-left.
{
coord: { x: width * 0.25, y: height * 0.25 },
exp: convertToUnorm8(expect.topLeftColor),
},
// Top-right.
{
coord: { x: width * 0.75, y: height * 0.25 },
exp: convertToUnorm8(expect.topRightColor),
},
// Bottom-left.
{
coord: { x: width * 0.25, y: height * 0.75 },
exp: convertToUnorm8(expect.bottomLeftColor),
},
// Bottom-right.
{
coord: { x: width * 0.75, y: height * 0.75 },
exp: convertToUnorm8(expect.bottomRightColor),
},
]);
}

Expand Down
Loading

0 comments on commit 7da5c3c

Please sign in to comment.