Skip to content

Commit

Permalink
WGSL Validation test for textureSampleCompareLevel
Browse files Browse the repository at this point in the history
  • Loading branch information
greggman committed Mar 14, 2024
1 parent 58d25c6 commit 4cda48b
Show file tree
Hide file tree
Showing 2 changed files with 257 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/webgpu/listing_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -1945,6 +1945,11 @@
"webgpu:shader,validation,expression,call,builtin,textureSampleCompare:depth_ref_argument:*": { "subcaseMS": 1.563 },
"webgpu:shader,validation,expression,call,builtin,textureSampleCompare:offset_argument,non_const:*": { "subcaseMS": 1.720 },
"webgpu:shader,validation,expression,call,builtin,textureSampleCompare:offset_argument:*": { "subcaseMS": 1.540 },
"webgpu:shader,validation,expression,call,builtin,textureSampleCompareLevel:array_index_argument:*": { "subcaseMS": 1.989 },
"webgpu:shader,validation,expression,call,builtin,textureSampleCompareLevel:coords_argument:*": { "subcaseMS": 1.932 },
"webgpu:shader,validation,expression,call,builtin,textureSampleCompareLevel:depth_ref_argument:*": { "subcaseMS": 1.578 },
"webgpu:shader,validation,expression,call,builtin,textureSampleCompareLevel:offset_argument,non_const:*": { "subcaseMS": 1.347 },
"webgpu:shader,validation,expression,call,builtin,textureSampleCompareLevel:offset_argument:*": { "subcaseMS": 1.619 },
"webgpu:shader,validation,expression,call,builtin,unpack4xI8:bad_args:*": { "subcaseMS": 121.263 },
"webgpu:shader,validation,expression,call,builtin,unpack4xI8:must_use:*": { "subcaseMS": 35.200 },
"webgpu:shader,validation,expression,call,builtin,unpack4xI8:supported:*": { "subcaseMS": 24.150 },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
const builtin = 'textureSampleCompareLevel';
export const description = `
Validation tests for the ${builtin}() builtin.
* test textureSampleCompareLevel coords parameter must be correct type
* test textureSampleCompareLevel array_index parameter must be correct type
* test textureSampleCompareLevel depth_ref parameter must be correct type
* test textureSampleCompareLevel offset parameter must be correct type
* test textureSampleCompareLevel offset parameter must be a const-expression
* test textureSampleCompareLevel offset parameter must be between -8 and +7 inclusive
`;

import { makeTestGroup } from '../../../../../../common/framework/test_group.js';
import { keysOf, objectsToRecord } from '../../../../../../common/util/data_tables.js';
import {
Type,
kAllScalarsAndVectors,
isConvertible,
ScalarType,
VectorType,
isUnsignedType,
} from '../../../../../util/conversion.js';
import { ShaderValidationTest } from '../../../shader_validation_test.js';

type TextureSampleCompareLevelArguments = {
coordsArgType: ScalarType | VectorType;
hasArrayIndexArg?: boolean;
offsetArgType?: VectorType;
};

const kValidTextureSampleCompareLevelParameterTypes: {
[n: string]: TextureSampleCompareLevelArguments;
} = {
texture_depth_2d: { coordsArgType: Type.vec2f, offsetArgType: Type.vec2i },
texture_depth_2d_array: {
coordsArgType: Type.vec2f,
hasArrayIndexArg: true,
offsetArgType: Type.vec2i,
},
texture_depth_cube: { coordsArgType: Type.vec3f },
texture_depth_cube_array: { coordsArgType: Type.vec3f, hasArrayIndexArg: true },
} as const;

const kTextureTypes = keysOf(kValidTextureSampleCompareLevelParameterTypes);
const kValuesTypes = objectsToRecord(kAllScalarsAndVectors);

export const g = makeTestGroup(ShaderValidationTest);

g.test('coords_argument')
.desc(
`
Validates that only incorrect coords arguments are rejected by ${builtin}
`
)
.params(u =>
u
.combine('textureType', keysOf(kValidTextureSampleCompareLevelParameterTypes))
.combine('coordType', keysOf(kValuesTypes))
.beginSubcases()
.combine('value', [-1, 0, 1] as const)
// filter out unsigned types with negative values
.filter(t => !isUnsignedType(kValuesTypes[t.coordType]) || t.value >= 0)
.expand('offset', ({ textureType }) => {
const offset = kValidTextureSampleCompareLevelParameterTypes[textureType].offsetArgType;
return offset ? [false, true] : [false];
})
)
.fn(t => {
const { textureType, coordType, offset, value } = t.params;
const coordArgType = kValuesTypes[coordType];
const {
offsetArgType,
coordsArgType: coordsRequiredType,
hasArrayIndexArg,
} = kValidTextureSampleCompareLevelParameterTypes[textureType];

const coordWGSL = coordArgType.create(value).wgsl();
const arrayWGSL = hasArrayIndexArg ? ', 0' : '';
const offsetWGSL = offset ? `, ${offsetArgType?.create(0).wgsl()}` : '';

const code = `
@group(0) @binding(0) var s: sampler_comparison;
@group(0) @binding(1) var t: ${textureType};
@fragment fn fs() -> @location(0) vec4f {
let v = textureSampleCompareLevel(t, s, ${coordWGSL}${arrayWGSL}, 0${offsetWGSL});
return vec4f(0);
}
`;
const expectSuccess = isConvertible(coordArgType, coordsRequiredType);
t.expectCompileResult(expectSuccess, code);
});

g.test('array_index_argument')
.desc(
`
Validates that only incorrect array_index arguments are rejected by ${builtin}
`
)
.params(u =>
u
.combine('textureType', kTextureTypes)
// filter out types with no array_index
.filter(t => !!kValidTextureSampleCompareLevelParameterTypes[t.textureType].hasArrayIndexArg)
.combine('arrayIndexType', keysOf(kValuesTypes))
.beginSubcases()
.combine('value', [-9, -8, 0, 7, 8])
// filter out unsigned types with negative values
.filter(t => !isUnsignedType(kValuesTypes[t.arrayIndexType]) || t.value >= 0)
)
.fn(t => {
const { textureType, arrayIndexType, value } = t.params;
const arrayIndexArgType = kValuesTypes[arrayIndexType];
const args = [arrayIndexArgType.create(value)];
const { coordsArgType, offsetArgType } =
kValidTextureSampleCompareLevelParameterTypes[textureType];

const coordWGSL = coordsArgType.create(0).wgsl();
const arrayWGSL = args.map(arg => arg.wgsl()).join(', ');
const offsetWGSL = offsetArgType ? `, ${offsetArgType.create(0).wgsl()}` : '';

const code = `
@group(0) @binding(0) var s: sampler_comparison;
@group(0) @binding(1) var t: ${textureType};
@fragment fn fs() -> @location(0) vec4f {
let v = textureSampleCompareLevel(t, s, ${coordWGSL}, ${arrayWGSL}, 0${offsetWGSL});
return vec4f(0);
}
`;
const expectSuccess =
isConvertible(arrayIndexArgType, Type.i32) || isConvertible(arrayIndexArgType, Type.u32);
t.expectCompileResult(expectSuccess, code);
});

g.test('depth_ref_argument')
.desc(
`
Validates that only incorrect depth_ref arguments are rejected by ${builtin}
`
)
.params(u =>
u
.combine('textureType', kTextureTypes)
.combine('depthRefType', keysOf(kValuesTypes))
.beginSubcases()
.combine('value', [-1, 0, 1])
// filter out unsigned types with negative values
.filter(t => !isUnsignedType(kValuesTypes[t.depthRefType]) || t.value >= 0)
)
.fn(t => {
const { textureType, depthRefType, value } = t.params;
const depthRefArgType = kValuesTypes[depthRefType];
const args = [depthRefArgType.create(value)];
const { coordsArgType, hasArrayIndexArg, offsetArgType } =
kValidTextureSampleCompareLevelParameterTypes[textureType];

const coordWGSL = coordsArgType.create(0).wgsl();
const arrayWGSL = hasArrayIndexArg ? ', 0' : '';
const depthRefWGSL = args.map(arg => arg.wgsl()).join(', ');
const offsetWGSL = offsetArgType ? `, ${offsetArgType.create(0).wgsl()}` : '';

const code = `
@group(0) @binding(0) var s: sampler_comparison;
@group(0) @binding(1) var t: ${textureType};
@fragment fn fs() -> @location(0) vec4f {
let v = textureSampleCompareLevel(t, s, ${coordWGSL}${arrayWGSL}, ${depthRefWGSL}${offsetWGSL});
return vec4f(0);
}
`;
const expectSuccess = isConvertible(depthRefArgType, Type.f32);
t.expectCompileResult(expectSuccess, code);
});

g.test('offset_argument')
.desc(
`
Validates that only incorrect offset arguments are rejected by ${builtin}
`
)
.params(u =>
u
.combine('textureType', kTextureTypes)
// filter out types with no offset
.filter(t => !!kValidTextureSampleCompareLevelParameterTypes[t.textureType].offsetArgType)
.combine('offsetType', keysOf(kValuesTypes))
.beginSubcases()
.combine('value', [-9, -8, 0, 7, 8])
// filter out unsigned types with negative values
.filter(t => !isUnsignedType(kValuesTypes[t.offsetType]) || t.value >= 0)
)
.fn(t => {
const { textureType, offsetType, value } = t.params;
const offsetArgType = kValuesTypes[offsetType];
const args = [offsetArgType.create(value)];
const {
coordsArgType,
hasArrayIndexArg,
offsetArgType: offsetRequiredType,
} = kValidTextureSampleCompareLevelParameterTypes[textureType];

const coordWGSL = coordsArgType.create(0).wgsl();
const arrayWGSL = hasArrayIndexArg ? ', 0' : '';
const offsetWGSL = args.map(arg => arg.wgsl()).join(', ');

const code = `
@group(0) @binding(0) var s: sampler_comparison;
@group(0) @binding(1) var t: ${textureType};
@fragment fn fs() -> @location(0) vec4f {
let v = textureSampleCompareLevel(t, s, ${coordWGSL}${arrayWGSL}, 0, ${offsetWGSL});
return vec4f(0);
}
`;
const expectSuccess =
isConvertible(offsetArgType, offsetRequiredType!) && value >= -8 && value <= 7;
t.expectCompileResult(expectSuccess, code);
});

g.test('offset_argument,non_const')
.desc(
`
Validates that only non-const offset arguments are rejected by ${builtin}
`
)
.params(u =>
u
.combine('textureType', kTextureTypes)
.combine('varType', ['c', 'u', 'l'])
// filter out types with no offset
.filter(t => !!kValidTextureSampleCompareLevelParameterTypes[t.textureType].offsetArgType)
)
.fn(t => {
const { textureType, varType } = t.params;
const { coordsArgType, hasArrayIndexArg, offsetArgType } =
kValidTextureSampleCompareLevelParameterTypes[textureType];

const coordWGSL = coordsArgType.create(0).wgsl();
const arrayWGSL = hasArrayIndexArg ? ', 0' : '';
const offsetWGSL = `${offsetArgType}(${varType})`;

const code = `
@group(0) @binding(0) var s: sampler_comparison;
@group(0) @binding(1) var t: ${textureType};
@group(0) @binding(2) var<uniform> u: ${offsetArgType};
@fragment fn fs() -> @location(0) vec4f {
const c = 1;
let l = ${offsetArgType?.create(0).wgsl()};
let v = textureSampleCompareLevel(t, s, ${coordWGSL}${arrayWGSL}, 0, ${offsetWGSL});
return vec4f(0);
}
`;
const expectSuccess = varType === 'c';
t.expectCompileResult(expectSuccess, code);
});

0 comments on commit 4cda48b

Please sign in to comment.