| export const description = ` |
| Test for texture_ok utils. |
| `; |
| |
| import { makeTestGroup } from '../common/framework/test_group.js'; |
| import { typedArrayFromParam, typedArrayParam } from '../common/util/util.js'; |
| import { RegularTextureFormat } from '../webgpu/format_info.js'; |
| import { TexelView } from '../webgpu/util/texture/texel_view.js'; |
| import { findFailedPixels } from '../webgpu/util/texture/texture_ok.js'; |
| |
| import { UnitTest } from './unit_test.js'; |
| |
| class F extends UnitTest { |
| test(act: string, exp: string): void { |
| this.expect(act === exp, 'got: ' + act.replace('\n', '⏎')); |
| } |
| } |
| |
| export const g = makeTestGroup(F); |
| g.test('findFailedPixels') |
| .desc( |
| ` |
| Test findFailedPixels passes what is expected to pass and fails what is expected |
| to fail. For example NaN === NaN should be true in a texture that allows NaN. |
| 2 different representations of the same rgb9e5ufloat should compare as equal. |
| etc... |
| ` |
| ) |
| .params(u => |
| u.combineWithParams([ |
| // Sanity Check |
| { |
| format: 'rgba8unorm' as RegularTextureFormat, |
| actual: typedArrayParam('Uint8Array', [0x00, 0x40, 0x80, 0xff]), |
| expected: typedArrayParam('Uint8Array', [0x00, 0x40, 0x80, 0xff]), |
| isSame: true, |
| }, |
| // Slightly different values |
| { |
| format: 'rgba8unorm' as RegularTextureFormat, |
| actual: typedArrayParam('Uint8Array', [0x00, 0x40, 0x80, 0xff]), |
| expected: typedArrayParam('Uint8Array', [0x00, 0x40, 0x81, 0xff]), |
| isSame: false, |
| }, |
| // Different representations of the same value |
| { |
| format: 'rgb9e5ufloat' as RegularTextureFormat, |
| actual: typedArrayParam('Uint8Array', [0x78, 0x56, 0x34, 0x12]), |
| expected: typedArrayParam('Uint8Array', [0xf0, 0xac, 0x68, 0x0c]), |
| isSame: true, |
| }, |
| // Slightly different values |
| { |
| format: 'rgb9e5ufloat' as RegularTextureFormat, |
| actual: typedArrayParam('Uint8Array', [0x78, 0x56, 0x34, 0x12]), |
| expected: typedArrayParam('Uint8Array', [0xf1, 0xac, 0x68, 0x0c]), |
| isSame: false, |
| }, |
| // Test NaN === NaN |
| { |
| format: 'r32float' as RegularTextureFormat, |
| actual: typedArrayParam('Float32Array', [parseFloat('abc')]), |
| expected: typedArrayParam('Float32Array', [parseFloat('def')]), |
| isSame: true, |
| }, |
| // Sanity Check |
| { |
| format: 'r32float' as RegularTextureFormat, |
| actual: typedArrayParam('Float32Array', [1.23]), |
| expected: typedArrayParam('Float32Array', [1.23]), |
| isSame: true, |
| }, |
| // Slightly different values. |
| { |
| format: 'r32float' as RegularTextureFormat, |
| actual: typedArrayParam('Uint32Array', [0x3f9d70a4]), |
| expected: typedArrayParam('Uint32Array', [0x3f9d70a5]), |
| isSame: false, |
| }, |
| // Slightly different |
| { |
| format: 'rg11b10ufloat' as RegularTextureFormat, |
| actual: typedArrayParam('Uint32Array', [0x3ce]), |
| expected: typedArrayParam('Uint32Array', [0x3cf]), |
| isSame: false, |
| }, |
| // Positive.Infinity === Positive.Infinity (red) |
| { |
| format: 'rg11b10ufloat' as RegularTextureFormat, |
| actual: typedArrayParam('Uint32Array', [0b11111000000]), |
| expected: typedArrayParam('Uint32Array', [0b11111000000]), |
| isSame: true, |
| }, |
| // Positive.Infinity === Positive.Infinity (green) |
| { |
| format: 'rg11b10ufloat' as RegularTextureFormat, |
| actual: typedArrayParam('Uint32Array', [0b11111000000_00000000000]), |
| expected: typedArrayParam('Uint32Array', [0b11111000000_00000000000]), |
| isSame: true, |
| }, |
| // Positive.Infinity === Positive.Infinity (blue) |
| { |
| format: 'rg11b10ufloat' as RegularTextureFormat, |
| actual: typedArrayParam('Uint32Array', [0b1111100000_00000000000_00000000000]), |
| expected: typedArrayParam('Uint32Array', [0b1111100000_00000000000_00000000000]), |
| isSame: true, |
| }, |
| // NaN === NaN (red) |
| { |
| format: 'rg11b10ufloat' as RegularTextureFormat, |
| actual: typedArrayParam('Uint32Array', [0b11111000001]), |
| expected: typedArrayParam('Uint32Array', [0b11111000010]), |
| isSame: true, |
| }, |
| // NaN === NaN (green) |
| { |
| format: 'rg11b10ufloat' as RegularTextureFormat, |
| actual: typedArrayParam('Uint32Array', [0b11111000100_00000000000]), |
| expected: typedArrayParam('Uint32Array', [0b11111001000_00000000000]), |
| isSame: true, |
| }, |
| // NaN === NaN (blue) |
| { |
| format: 'rg11b10ufloat' as RegularTextureFormat, |
| actual: typedArrayParam('Uint32Array', [0b1111110000_00000000000_00000000000]), |
| expected: typedArrayParam('Uint32Array', [0b1111101000_00000000000_00000000000]), |
| isSame: true, |
| }, |
| ]) |
| ) |
| .fn(t => { |
| const { format, actual, expected, isSame } = t.params; |
| const actualData = new Uint8Array(typedArrayFromParam(actual).buffer); |
| const expectedData = new Uint8Array(typedArrayFromParam(expected).buffer); |
| |
| const actTexelView = TexelView.fromTextureDataByReference(format, actualData, { |
| bytesPerRow: actualData.byteLength, |
| rowsPerImage: 1, |
| subrectOrigin: [0, 0, 0], |
| subrectSize: [1, 1, 1], |
| }); |
| const expTexelView = TexelView.fromTextureDataByReference(format, expectedData, { |
| bytesPerRow: expectedData.byteLength, |
| rowsPerImage: 1, |
| subrectOrigin: [0, 0, 0], |
| subrectSize: [1, 1, 1], |
| }); |
| |
| const zero = { x: 0, y: 0, z: 0 }; |
| const failedPixelsMessage = findFailedPixels( |
| format, |
| zero, |
| { width: 1, height: 1, depthOrArrayLayers: 1 }, |
| { actTexelView, expTexelView }, |
| { |
| maxFractionalDiff: 0, |
| } |
| ); |
| |
| t.expect(isSame === !failedPixelsMessage, failedPixelsMessage); |
| }); |