diff --git a/.eslintrc.json b/.eslintrc.json index 969f6f09fb49..9ac62202119a 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -58,6 +58,11 @@ "message": "Use requestDeviceTracked() instead of requestDevice().", // We don't seem to need direct calls to requestDevice() at all so we can just disallow all of them. "selector": "CallExpression > MemberExpression > Identifier[name=\"requestDevice\"]" + }, + { + "message": "Use hasFeature() instead of features.has().", + // features.has takes any string. We want only valid feature names. + "selector": "CallExpression[callee.property.name='has'][callee.object.name='features'],CallExpression[callee.property.name='has'][callee.object.property.name='features']" } ], diff --git a/src/common/framework/test_config.ts b/src/common/framework/test_config.ts index 0b034c1d962c..7311428f0504 100644 --- a/src/common/framework/test_config.ts +++ b/src/common/framework/test_config.ts @@ -1,4 +1,4 @@ -import { assert } from '../util/util.js'; +import { assert, hasFeature } from '../util/util.js'; export type TestConfig = { /** @@ -90,7 +90,7 @@ export const globalTestConfig: TestConfig = { // is trying to test that compatibility devices have the correct validation. export function isCompatibilityDevice(device: GPUDevice) { if (globalTestConfig.compatibility) { - assert(!device.features.has('core-features-and-limits')); + assert(!hasFeature(device.features, 'core-features-and-limits')); } return globalTestConfig.compatibility; } diff --git a/src/common/util/navigator_gpu.ts b/src/common/util/navigator_gpu.ts index d23ceb091a8c..cc3b54b7ab0f 100644 --- a/src/common/util/navigator_gpu.ts +++ b/src/common/util/navigator_gpu.ts @@ -2,7 +2,7 @@ import { TestCaseRecorder } from '../framework/fixture.js'; import { globalTestConfig } from '../framework/test_config.js'; -import { ErrorWithExtra, assert, objectEquals } from './util.js'; +import { ErrorWithExtra, assert, hasFeature, objectEquals } from './util.js'; /** * Finds and returns the `navigator.gpu` object (or equivalent, for non-browser implementations). @@ -164,7 +164,9 @@ export function getGPU(recorder: TestCaseRecorder | null): GPU { Object.defineProperty(adapter, 'features', { enumerable: false, value: new Set( - adapter.features.has('core-features-and-limits') ? ['core-features-and-limits'] : [] + hasFeature(adapter.features, 'core-features-and-limits') + ? ['core-features-and-limits'] + : [] ), }); } @@ -177,6 +179,7 @@ export function getGPU(recorder: TestCaseRecorder | null): GPU { for (const [feature] of desc.requiredFeatures) { // Note: This adapter has had its features property over-ridden and will only return // have nothing or 'core-features-and-limits'. + // eslint-disable-next-line no-restricted-syntax if (!adapter.features.has(feature)) { throw new TypeError(`requested feature ${feature} does not exist on adapter`); } diff --git a/src/common/util/util.ts b/src/common/util/util.ts index 4e5a6aa13b5e..b534c7d898b5 100644 --- a/src/common/util/util.ts +++ b/src/common/util/util.ts @@ -496,3 +496,12 @@ export function filterUniqueValueTestVariants(valueTestVariants: ValueTestVarian export function makeValueTestVariant(base: number, variant: ValueTestVariant) { return base * variant.mult + variant.add; } + +/** + * Use instead of features.has because feature's has takes any string + * and we want to prevent typos. + */ +export function hasFeature(features: GPUSupportedFeatures, feature: GPUFeatureName) { + // eslint-disable-next-line no-restricted-syntax + return features.has(feature); +} diff --git a/src/resources/cache/hashes.json b/src/resources/cache/hashes.json index d9ec08c7485e..20f81ccf29c8 100644 --- a/src/resources/cache/hashes.json +++ b/src/resources/cache/hashes.json @@ -1,112 +1,112 @@ { - "webgpu/shader/execution/binary/af_addition.bin": "b1b71eea", - "webgpu/shader/execution/binary/af_logical.bin": "bca2200a", - "webgpu/shader/execution/binary/af_division.bin": "cfda1ac2", - "webgpu/shader/execution/binary/af_matrix_addition.bin": "4473c45a", - "webgpu/shader/execution/binary/af_matrix_subtraction.bin": "e945ec79", - "webgpu/shader/execution/binary/af_multiplication.bin": "eb6c672", - "webgpu/shader/execution/binary/af_remainder.bin": "e971fba9", - "webgpu/shader/execution/binary/af_subtraction.bin": "72293f91", - "webgpu/shader/execution/binary/f16_addition.bin": "ea5505aa", - "webgpu/shader/execution/binary/f16_logical.bin": "7cf1347f", - "webgpu/shader/execution/binary/f16_division.bin": "c05f4feb", - "webgpu/shader/execution/binary/f16_matrix_addition.bin": "429f8589", - "webgpu/shader/execution/binary/f16_matrix_matrix_multiplication.bin": "5ce1d443", - "webgpu/shader/execution/binary/f16_matrix_scalar_multiplication.bin": "ff07ce52", - "webgpu/shader/execution/binary/f16_matrix_subtraction.bin": "8693f3e", - "webgpu/shader/execution/binary/f16_matrix_vector_multiplication.bin": "1a4cc717", - "webgpu/shader/execution/binary/f16_multiplication.bin": "604b8407", - "webgpu/shader/execution/binary/f16_remainder.bin": "bc510eb0", - "webgpu/shader/execution/binary/f16_subtraction.bin": "81718e04", - "webgpu/shader/execution/binary/f32_addition.bin": "a04733a4", - "webgpu/shader/execution/binary/f32_logical.bin": "83d3ec3d", - "webgpu/shader/execution/binary/f32_division.bin": "d5c79df7", - "webgpu/shader/execution/binary/f32_matrix_addition.bin": "803f74e9", - "webgpu/shader/execution/binary/f32_matrix_matrix_multiplication.bin": "2e1e2af9", - "webgpu/shader/execution/binary/f32_matrix_scalar_multiplication.bin": "f60c6997", - "webgpu/shader/execution/binary/f32_matrix_subtraction.bin": "bf68cb89", - "webgpu/shader/execution/binary/f32_matrix_vector_multiplication.bin": "9a6401bb", - "webgpu/shader/execution/binary/f32_multiplication.bin": "f1e1ef9a", - "webgpu/shader/execution/binary/f32_remainder.bin": "da5afd13", - "webgpu/shader/execution/binary/f32_subtraction.bin": "830b567f", - "webgpu/shader/execution/binary/i32_arithmetic.bin": "c18da799", - "webgpu/shader/execution/binary/i32_comparison.bin": "848ceb5c", - "webgpu/shader/execution/binary/u32_arithmetic.bin": "dc0b2ed9", - "webgpu/shader/execution/binary/u32_comparison.bin": "2bae879f", - "webgpu/shader/execution/abs.bin": "561a28e0", - "webgpu/shader/execution/acos.bin": "8cc074ad", - "webgpu/shader/execution/acosh.bin": "8a510d97", - "webgpu/shader/execution/asin.bin": "14d5064", - "webgpu/shader/execution/asinh.bin": "1e00159", - "webgpu/shader/execution/atan.bin": "7a1fc6e9", - "webgpu/shader/execution/atan2.bin": "3a2974c9", - "webgpu/shader/execution/atanh.bin": "8d6dab0b", - "webgpu/shader/execution/bitcast.bin": "e307a369", - "webgpu/shader/execution/ceil.bin": "d02bdaad", - "webgpu/shader/execution/clamp.bin": "fcbe35ac", - "webgpu/shader/execution/cos.bin": "ccb1c23f", - "webgpu/shader/execution/cosh.bin": "a0a406ad", - "webgpu/shader/execution/cross.bin": "2a875fef", - "webgpu/shader/execution/degrees.bin": "50bb915a", - "webgpu/shader/execution/determinant.bin": "3e6249da", - "webgpu/shader/execution/distance.bin": "a29c5aa", - "webgpu/shader/execution/dot.bin": "466765d5", - "webgpu/shader/execution/exp.bin": "c2640231", - "webgpu/shader/execution/exp2.bin": "274b093f", - "webgpu/shader/execution/faceForward.bin": "4492d11d", - "webgpu/shader/execution/floor.bin": "d41f1c95", - "webgpu/shader/execution/fma.bin": "2fb1c38f", - "webgpu/shader/execution/fract.bin": "c9080e98", - "webgpu/shader/execution/frexp.bin": "b675bee4", - "webgpu/shader/execution/inverseSqrt.bin": "8b23d93a", - "webgpu/shader/execution/ldexp.bin": "ee536142", - "webgpu/shader/execution/length.bin": "b3384a6", - "webgpu/shader/execution/log.bin": "bd3a55f0", - "webgpu/shader/execution/log2.bin": "ff3794ac", - "webgpu/shader/execution/max.bin": "fce16c8a", - "webgpu/shader/execution/min.bin": "ff191ba4", - "webgpu/shader/execution/mix.bin": "4c4935e9", - "webgpu/shader/execution/modf.bin": "da3ae106", - "webgpu/shader/execution/normalize.bin": "35a5ec27", - "webgpu/shader/execution/pack2x16float.bin": "fec8b248", - "webgpu/shader/execution/pow.bin": "ee753258", - "webgpu/shader/execution/quantizeToF16.bin": "2c4ffde2", - "webgpu/shader/execution/radians.bin": "1fdd20d3", - "webgpu/shader/execution/reflect.bin": "ca02fe50", - "webgpu/shader/execution/refract.bin": "bdb6610", - "webgpu/shader/execution/round.bin": "b8be95b4", - "webgpu/shader/execution/saturate.bin": "74f21503", - "webgpu/shader/execution/sign.bin": "533d2185", - "webgpu/shader/execution/sin.bin": "e1c39c1b", - "webgpu/shader/execution/sinh.bin": "61da608d", - "webgpu/shader/execution/smoothstep.bin": "a6dd83ed", - "webgpu/shader/execution/sqrt.bin": "ca8cd266", - "webgpu/shader/execution/step.bin": "34459d7f", - "webgpu/shader/execution/tan.bin": "b5513d60", - "webgpu/shader/execution/tanh.bin": "6f67098a", - "webgpu/shader/execution/transpose.bin": "1dd8473f", - "webgpu/shader/execution/trunc.bin": "6df96e09", - "webgpu/shader/execution/unpack2x16float.bin": "1c7505ba", - "webgpu/shader/execution/unpack2x16snorm.bin": "ade8ed16", - "webgpu/shader/execution/unpack2x16unorm.bin": "d7b00631", - "webgpu/shader/execution/unpack4x8snorm.bin": "a21a1f80", - "webgpu/shader/execution/unpack4x8unorm.bin": "edb0945d", - "webgpu/shader/execution/unary/af_arithmetic.bin": "5f835ed1", - "webgpu/shader/execution/unary/af_assignment.bin": "ede88653", - "webgpu/shader/execution/unary/bool_conversion.bin": "1d58a0ac", - "webgpu/shader/execution/unary/f16_arithmetic.bin": "f01f7be8", - "webgpu/shader/execution/unary/f16_conversion.bin": "798114db", - "webgpu/shader/execution/unary/f32_arithmetic.bin": "dd24b472", - "webgpu/shader/execution/unary/f32_conversion.bin": "38c55dc0", - "webgpu/shader/execution/unary/i32_arithmetic.bin": "65d2d245", - "webgpu/shader/execution/unary/i32_conversion.bin": "6059380d", - "webgpu/shader/execution/unary/u32_conversion.bin": "9918d0a7", - "webgpu/shader/execution/unary/ai_assignment.bin": "587d799a", - "webgpu/shader/execution/binary/ai_arithmetic.bin": "3c8862bd", - "webgpu/shader/execution/unary/ai_arithmetic.bin": "d46137bc", - "webgpu/shader/execution/binary/af_matrix_matrix_multiplication.bin": "ba58dd07", - "webgpu/shader/execution/binary/af_matrix_scalar_multiplication.bin": "5fe0a0e3", - "webgpu/shader/execution/binary/af_matrix_vector_multiplication.bin": "9f8ed988", - "webgpu/shader/execution/derivatives.bin": "7a039a71", - "webgpu/shader/execution/fwidth.bin": "30b40017" + "webgpu/shader/execution/binary/af_addition.bin": "da003be4", + "webgpu/shader/execution/binary/af_logical.bin": "14ad43ca", + "webgpu/shader/execution/binary/af_division.bin": "1296892b", + "webgpu/shader/execution/binary/af_matrix_addition.bin": "1317ab16", + "webgpu/shader/execution/binary/af_matrix_subtraction.bin": "2853ad41", + "webgpu/shader/execution/binary/af_multiplication.bin": "5ee6bde6", + "webgpu/shader/execution/binary/af_remainder.bin": "366f8d30", + "webgpu/shader/execution/binary/af_subtraction.bin": "3c19e6fb", + "webgpu/shader/execution/binary/f16_addition.bin": "319185c0", + "webgpu/shader/execution/binary/f16_logical.bin": "94a83cb4", + "webgpu/shader/execution/binary/f16_division.bin": "635bbc5f", + "webgpu/shader/execution/binary/f16_matrix_addition.bin": "30070be5", + "webgpu/shader/execution/binary/f16_matrix_matrix_multiplication.bin": "7e0e00db", + "webgpu/shader/execution/binary/f16_matrix_scalar_multiplication.bin": "d538842d", + "webgpu/shader/execution/binary/f16_matrix_subtraction.bin": "4b5ce37c", + "webgpu/shader/execution/binary/f16_matrix_vector_multiplication.bin": "7a4445de", + "webgpu/shader/execution/binary/f16_multiplication.bin": "b2c70232", + "webgpu/shader/execution/binary/f16_remainder.bin": "d138c173", + "webgpu/shader/execution/binary/f16_subtraction.bin": "e2515ca5", + "webgpu/shader/execution/binary/f32_addition.bin": "60286efc", + "webgpu/shader/execution/binary/f32_logical.bin": "a578e65b", + "webgpu/shader/execution/binary/f32_division.bin": "36d196b1", + "webgpu/shader/execution/binary/f32_matrix_addition.bin": "a11d772e", + "webgpu/shader/execution/binary/f32_matrix_matrix_multiplication.bin": "d578a451", + "webgpu/shader/execution/binary/f32_matrix_scalar_multiplication.bin": "a0259221", + "webgpu/shader/execution/binary/f32_matrix_subtraction.bin": "9eb43464", + "webgpu/shader/execution/binary/f32_matrix_vector_multiplication.bin": "939f2e70", + "webgpu/shader/execution/binary/f32_multiplication.bin": "d34ce65d", + "webgpu/shader/execution/binary/f32_remainder.bin": "6fa6b892", + "webgpu/shader/execution/binary/f32_subtraction.bin": "ddb575f5", + "webgpu/shader/execution/binary/i32_arithmetic.bin": "5bc8c900", + "webgpu/shader/execution/binary/i32_comparison.bin": "9165629b", + "webgpu/shader/execution/binary/u32_arithmetic.bin": "fc8c6726", + "webgpu/shader/execution/binary/u32_comparison.bin": "598d0773", + "webgpu/shader/execution/abs.bin": "f4ea4f10", + "webgpu/shader/execution/acos.bin": "f7ccbfca", + "webgpu/shader/execution/acosh.bin": "11315a9f", + "webgpu/shader/execution/asin.bin": "7349a03b", + "webgpu/shader/execution/asinh.bin": "fdebffc6", + "webgpu/shader/execution/atan.bin": "723ae9a5", + "webgpu/shader/execution/atan2.bin": "57241996", + "webgpu/shader/execution/atanh.bin": "e72a7c31", + "webgpu/shader/execution/bitcast.bin": "3de97de", + "webgpu/shader/execution/ceil.bin": "29fd5fae", + "webgpu/shader/execution/clamp.bin": "8d0eafdb", + "webgpu/shader/execution/cos.bin": "eac17036", + "webgpu/shader/execution/cosh.bin": "575d952c", + "webgpu/shader/execution/cross.bin": "34b3306c", + "webgpu/shader/execution/degrees.bin": "e95cfd56", + "webgpu/shader/execution/determinant.bin": "cbf20e3c", + "webgpu/shader/execution/distance.bin": "1c119356", + "webgpu/shader/execution/dot.bin": "4da666a3", + "webgpu/shader/execution/exp.bin": "69ee596e", + "webgpu/shader/execution/exp2.bin": "1b0d4107", + "webgpu/shader/execution/faceForward.bin": "d9e806e", + "webgpu/shader/execution/floor.bin": "d04aaaed", + "webgpu/shader/execution/fma.bin": "ea6f3d9d", + "webgpu/shader/execution/fract.bin": "6041dbd3", + "webgpu/shader/execution/frexp.bin": "4f14eae", + "webgpu/shader/execution/inverseSqrt.bin": "a31d31ec", + "webgpu/shader/execution/ldexp.bin": "bc8d5e62", + "webgpu/shader/execution/length.bin": "52fc048a", + "webgpu/shader/execution/log.bin": "bdb94ae0", + "webgpu/shader/execution/log2.bin": "b92a3bca", + "webgpu/shader/execution/max.bin": "436f8f21", + "webgpu/shader/execution/min.bin": "21cb02b4", + "webgpu/shader/execution/mix.bin": "ef3d6b1b", + "webgpu/shader/execution/modf.bin": "55ff0437", + "webgpu/shader/execution/normalize.bin": "fd315393", + "webgpu/shader/execution/pack2x16float.bin": "8443853d", + "webgpu/shader/execution/pow.bin": "e1f4e61", + "webgpu/shader/execution/quantizeToF16.bin": "564caff5", + "webgpu/shader/execution/radians.bin": "3d50fa1a", + "webgpu/shader/execution/reflect.bin": "de3cdc23", + "webgpu/shader/execution/refract.bin": "a6b7cf0c", + "webgpu/shader/execution/round.bin": "5735993c", + "webgpu/shader/execution/saturate.bin": "58cb0de5", + "webgpu/shader/execution/sign.bin": "b59874a7", + "webgpu/shader/execution/sin.bin": "59c3422", + "webgpu/shader/execution/sinh.bin": "427c6297", + "webgpu/shader/execution/smoothstep.bin": "b0d9c07e", + "webgpu/shader/execution/sqrt.bin": "f207f4ac", + "webgpu/shader/execution/step.bin": "18a574a0", + "webgpu/shader/execution/tan.bin": "40504049", + "webgpu/shader/execution/tanh.bin": "7c1b22bd", + "webgpu/shader/execution/transpose.bin": "af20793c", + "webgpu/shader/execution/trunc.bin": "2d9f23e5", + "webgpu/shader/execution/unpack2x16float.bin": "de3c9cb4", + "webgpu/shader/execution/unpack2x16snorm.bin": "2cfc1791", + "webgpu/shader/execution/unpack2x16unorm.bin": "85ff09e", + "webgpu/shader/execution/unpack4x8snorm.bin": "e4c5b1f4", + "webgpu/shader/execution/unpack4x8unorm.bin": "1fd43872", + "webgpu/shader/execution/unary/af_arithmetic.bin": "daccee7d", + "webgpu/shader/execution/unary/af_assignment.bin": "fb1a84b1", + "webgpu/shader/execution/unary/bool_conversion.bin": "65b450a7", + "webgpu/shader/execution/unary/f16_arithmetic.bin": "79ee24a3", + "webgpu/shader/execution/unary/f16_conversion.bin": "920adf7", + "webgpu/shader/execution/unary/f32_arithmetic.bin": "9496759c", + "webgpu/shader/execution/unary/f32_conversion.bin": "dddb7940", + "webgpu/shader/execution/unary/i32_arithmetic.bin": "e9c53cb5", + "webgpu/shader/execution/unary/i32_conversion.bin": "87b5fd7", + "webgpu/shader/execution/unary/u32_conversion.bin": "70718f67", + "webgpu/shader/execution/unary/ai_assignment.bin": "4fad3c69", + "webgpu/shader/execution/binary/ai_arithmetic.bin": "a00c8197", + "webgpu/shader/execution/unary/ai_arithmetic.bin": "3b481d45", + "webgpu/shader/execution/binary/af_matrix_matrix_multiplication.bin": "47b72af2", + "webgpu/shader/execution/binary/af_matrix_scalar_multiplication.bin": "1a5c6719", + "webgpu/shader/execution/binary/af_matrix_vector_multiplication.bin": "1b8f17cf", + "webgpu/shader/execution/derivatives.bin": "6d72e1fb", + "webgpu/shader/execution/fwidth.bin": "c00ddf59" } \ No newline at end of file diff --git a/src/webgpu/api/operation/adapter/info.spec.ts b/src/webgpu/api/operation/adapter/info.spec.ts index 7856997f9eaa..fa4d7529e1bd 100644 --- a/src/webgpu/api/operation/adapter/info.spec.ts +++ b/src/webgpu/api/operation/adapter/info.spec.ts @@ -6,7 +6,7 @@ import { Fixture } from '../../../../common/framework/fixture.js'; import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { keysOf } from '../../../../common/util/data_tables.js'; import { getGPU } from '../../../../common/util/navigator_gpu.js'; -import { assert, objectEquals } from '../../../../common/util/util.js'; +import { assert, hasFeature, objectEquals } from '../../../../common/util/util.js'; import { isPowerOfTwo } from '../../../util/math.js'; export const g = makeTestGroup(Fixture); @@ -158,7 +158,7 @@ If they exist, they must both exist and be powers of two, and // Once 'subgroups' lands, the properties should be defined with default values 4 and 128 // when adapter does not support the feature. // https://github.com/gpuweb/gpuweb/pull/4963 - if (adapter.features.has('subgroups')) { + if (hasFeature(adapter.features, 'subgroups')) { t.expect( subgroupMinSize !== undefined, 'GPUAdapterInfo.subgroupMinSize must exist when subgroups supported' diff --git a/src/webgpu/api/operation/adapter/requestDevice.spec.ts b/src/webgpu/api/operation/adapter/requestDevice.spec.ts index 86a94692d0f1..6e3c5155c752 100644 --- a/src/webgpu/api/operation/adapter/requestDevice.spec.ts +++ b/src/webgpu/api/operation/adapter/requestDevice.spec.ts @@ -8,7 +8,7 @@ potentially limited native resources. import { Fixture } from '../../../../common/framework/fixture.js'; import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { getGPU } from '../../../../common/util/navigator_gpu.js'; -import { assert, assertReject, typedEntries } from '../../../../common/util/util.js'; +import { assert, assertReject, hasFeature, typedEntries } from '../../../../common/util/util.js'; import { getDefaultLimitsForCTS, kFeatureNames, @@ -44,7 +44,7 @@ g.test('default') if (device.features.size === 1) { t.expect( - device.features.has('core-features-and-limits'), + hasFeature(device.features, 'core-features-and-limits'), 'Default device should not have any features other than "core-features-and-limits"' ); } else { @@ -204,9 +204,9 @@ g.test('features,known') assert(adapter !== null); const promise = t.requestDeviceTracked(adapter, { requiredFeatures: [feature] }); - if (adapter.features.has(feature)) { + if (hasFeature(adapter.features, feature)) { const device = await promise; - t.expect(device.features.has(feature), 'Device should include the required feature'); + t.expect(hasFeature(device.features, feature), 'Device should include the required feature'); } else { t.shouldReject('TypeError', promise); } @@ -496,12 +496,12 @@ g.test('always_returns_device') const device = await t.requestDeviceTracked(adapter); assert(device instanceof GPUDevice, 'requestDevice must return a device or throw'); - if (featureLevel === 'core' && adapter.features.has('core-features-and-limits')) { + if (featureLevel === 'core' && hasFeature(adapter.features, 'core-features-and-limits')) { // Check if the device supports core, when featureLevel is core and adapter supports core. // This check is to make sure something lower-level is not forcing compatibility mode. t.expect( - device.features.has('core-features-and-limits'), + hasFeature(device.features, 'core-features-and-limits'), 'must not get a Compatibility adapter if not requested' ); } diff --git a/src/webgpu/api/operation/device/all_limits_and_features.spec.ts b/src/webgpu/api/operation/device/all_limits_and_features.spec.ts index 440113c9cc47..7da52a55f910 100644 --- a/src/webgpu/api/operation/device/all_limits_and_features.spec.ts +++ b/src/webgpu/api/operation/device/all_limits_and_features.spec.ts @@ -103,6 +103,7 @@ changes to WebGPU do not break sites requesting everything. // Test that all the adapter features are on the device. for (const feature of t.adapter.features) { + // eslint-disable-next-line no-restricted-syntax t.expect(t.device.features.has(feature), `device has feature: ${feature}`); } }); diff --git a/src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts b/src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts index ff3164d7aadd..ca8ccec77dac 100644 --- a/src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts +++ b/src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts @@ -4,7 +4,7 @@ Tests for capability checking for features enabling optional texture formats. import { makeTestGroup } from '../../../../../common/framework/test_group.js'; import { getGPU } from '../../../../../common/util/navigator_gpu.js'; -import { assert } from '../../../../../common/util/util.js'; +import { assert, hasFeature } from '../../../../../common/util/util.js'; import { kCanvasTextureFormats } from '../../../../capability_info.js'; import { kASTCCompressedTextureFormats, @@ -551,11 +551,11 @@ g.test('check_capability_guarantees') const features = adapter.features; - const supportsBC = features.has('texture-compression-bc'); - const supportsBCSliced3D = features.has('texture-compression-bc-sliced-3d'); - const supportsASTC = features.has('texture-compression-astc'); - const supportsASTCSliced3D = features.has('texture-compression-astc-sliced-3d'); - const supportsETC2 = features.has('texture-compression-etc2'); + const supportsBC = hasFeature(features, 'texture-compression-bc'); + const supportsBCSliced3D = hasFeature(features, 'texture-compression-bc-sliced-3d'); + const supportsASTC = hasFeature(features, 'texture-compression-astc'); + const supportsASTCSliced3D = hasFeature(features, 'texture-compression-astc-sliced-3d'); + const supportsETC2 = hasFeature(features, 'texture-compression-etc2'); t.expect( supportsBC || (supportsETC2 && supportsASTC), diff --git a/src/webgpu/api/validation/capability_checks/features/texture_formats_tier1.spec.ts b/src/webgpu/api/validation/capability_checks/features/texture_formats_tier1.spec.ts index 1a7e162a1b5d..0bed24ad392a 100644 --- a/src/webgpu/api/validation/capability_checks/features/texture_formats_tier1.spec.ts +++ b/src/webgpu/api/validation/capability_checks/features/texture_formats_tier1.spec.ts @@ -13,6 +13,7 @@ when the feature is not enabled. This includes: `; import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { hasFeature } from '../../../../../common/util/util.js'; import { kTextureFormatTier1AllowsRenderAttachmentBlendableMultisample, kTextureFormatTier1ThrowsWhenNotEnabled, @@ -32,7 +33,7 @@ g.test('enables_rg11b10ufloat_renderable') ) .beforeAllSubcases(t => t.selectDeviceOrSkipTestCase('texture-formats-tier1')) .fn(t => { - t.expect(() => t.device.features.has('rg11b10ufloat-renderable')); + t.expect(() => hasFeature(t.device.features, 'rg11b10ufloat-renderable')); }); g.test('texture_usage,render_attachment') diff --git a/src/webgpu/api/validation/capability_checks/features/texture_formats_tier2.spec.ts b/src/webgpu/api/validation/capability_checks/features/texture_formats_tier2.spec.ts index db72933ff4c8..752da9ad17ed 100644 --- a/src/webgpu/api/validation/capability_checks/features/texture_formats_tier2.spec.ts +++ b/src/webgpu/api/validation/capability_checks/features/texture_formats_tier2.spec.ts @@ -5,10 +5,11 @@ Test that enabling texture-formats-tier2 also enables rg11b10ufloat-renderable a Tests that abilities enabled by 'texture-formats-tier2' correctly generate validation errors when the feature is not enabled. This includes: -- read-write stoorage access formats gaining this capability. +- read-write storage access formats gaining this capability. `; import { makeTestGroup } from '../../../../../common/framework/test_group.js'; +import { hasFeature } from '../../../../../common/util/util.js'; import { kTextureFormatsTier2EnablesStorageReadWrite } from '../../../../format_info.js'; import { UniqueFeaturesOrLimitsGPUTest } from '../../../../gpu_test.js'; import * as vtu from '../../validation_test_utils.js'; @@ -23,8 +24,8 @@ g.test('enables_rg11b10ufloat_renderable_and_texture_formats_tier1') ) .beforeAllSubcases(t => t.selectDeviceOrSkipTestCase('texture-formats-tier2')) .fn(t => { - t.expect(() => t.device.features.has('rg11b10ufloat-renderable')); - t.expect(() => t.device.features.has('texture-formats-tier1')); + t.expect(() => hasFeature(t.device.features, 'rg11b10ufloat-renderable')); + t.expect(() => hasFeature(t.device.features, 'texture-formats-tier1')); }); g.test('bind_group_layout,storage_binding_read_write_access') diff --git a/src/webgpu/api/validation/capability_checks/limits/maxComputeWorkgroupStorageSize.spec.ts b/src/webgpu/api/validation/capability_checks/limits/maxComputeWorkgroupStorageSize.spec.ts index 8a9176983d38..69101c308208 100644 --- a/src/webgpu/api/validation/capability_checks/limits/maxComputeWorkgroupStorageSize.spec.ts +++ b/src/webgpu/api/validation/capability_checks/limits/maxComputeWorkgroupStorageSize.spec.ts @@ -1,5 +1,5 @@ import { keysOf } from '../../../../../common/util/data_tables.js'; -import { assert } from '../../../../../common/util/util.js'; +import { assert, hasFeature } from '../../../../../common/util/util.js'; import { align, roundDown } from '../../../../util/math.js'; import { @@ -152,7 +152,7 @@ g.test('createComputePipeline,at_over') const { limitTest, testValueName, async, wgslType } = t.params; const { defaultLimit, adapterLimit: maximumLimit } = t; - const hasF16 = t.adapter.features.has('shader-f16'); + const hasF16 = hasFeature(t.adapter.features, 'shader-f16'); if (!hasF16 && wgslType in wgslF16Types) { return; } diff --git a/src/webgpu/api/validation/render_pipeline/primitive_state.spec.ts b/src/webgpu/api/validation/render_pipeline/primitive_state.spec.ts index 59133cd5be55..6fac5288900e 100644 --- a/src/webgpu/api/validation/render_pipeline/primitive_state.spec.ts +++ b/src/webgpu/api/validation/render_pipeline/primitive_state.spec.ts @@ -3,6 +3,7 @@ This test dedicatedly tests validation of GPUPrimitiveState of createRenderPipel `; import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { hasFeature } from '../../../../common/util/util.js'; import { kPrimitiveTopology, kIndexFormat } from '../../../capability_info.js'; import * as vtu from '../validation_test_utils.js'; @@ -38,6 +39,6 @@ g.test('unclipped_depth') const descriptor = t.getDescriptor({ primitive: { unclippedDepth } }); - const _success = !unclippedDepth || t.device.features.has('depth-clip-control'); + const _success = !unclippedDepth || hasFeature(t.device.features, 'depth-clip-control'); vtu.doCreateRenderPipelineTest(t, isAsync, _success, descriptor); }); diff --git a/src/webgpu/capability_info.ts b/src/webgpu/capability_info.ts index 54f3e8d25939..d9c669fc96be 100644 --- a/src/webgpu/capability_info.ts +++ b/src/webgpu/capability_info.ts @@ -12,7 +12,7 @@ import { valueof, } from '../common/util/data_tables.js'; import { assertTypeTrue, TypeEqual } from '../common/util/types.js'; -import { unreachable } from '../common/util/util.js'; +import { hasFeature, unreachable } from '../common/util/util.js'; import { GPUConst, kMaxUnsignedLongValue, kMaxUnsignedLongLongValue } from './constants.js'; @@ -839,7 +839,9 @@ export function getDefaultLimitsForCTS() { } export function getDefaultLimitsForDevice(device: GPUDevice) { - const featureLevel = device.features.has('core-features-and-limits') ? 'core' : 'compatibility'; + const featureLevel = hasFeature(device.features, 'core-features-and-limits') + ? 'core' + : 'compatibility'; return getDefaultLimits(featureLevel); } diff --git a/src/webgpu/format_info.ts b/src/webgpu/format_info.ts index a3d8f3148997..0e537063c9b6 100644 --- a/src/webgpu/format_info.ts +++ b/src/webgpu/format_info.ts @@ -1,6 +1,6 @@ import { isCompatibilityDevice } from '../common/framework/test_config.js'; import { keysOf } from '../common/util/data_tables.js'; -import { assert, unreachable } from '../common/util/util.js'; +import { assert, unreachable, hasFeature } from '../common/util/util.js'; import { align, roundDown } from './util/math.js'; import { getTextureDimensionFromView } from './util/texture/base.js'; @@ -2068,8 +2068,10 @@ export function textureDimensionAndFormatCompatibleForDevice( ): boolean { if ( dimension === '3d' && - ((isBCTextureFormat(format) && device.features.has('texture-compression-bc-sliced-3d')) || - (isASTCTextureFormat(format) && device.features.has('texture-compression-astc-sliced-3d'))) + ((isBCTextureFormat(format) && + hasFeature(device.features, 'texture-compression-bc-sliced-3d')) || + (isASTCTextureFormat(format) && + hasFeature(device.features, 'texture-compression-astc-sliced-3d'))) ) { return true; } @@ -2357,10 +2359,10 @@ export function isTextureFormatUsableAsRenderAttachment( format: GPUTextureFormat ) { if (format === 'rg11b10ufloat') { - return device.features.has('rg11b10ufloat-renderable'); + return hasFeature(device.features, 'rg11b10ufloat-renderable'); } if (isTextureFormatTier1EnablesRenderAttachmentBlendableMultisample(format)) { - return device.features.has('texture-formats-tier1'); + return hasFeature(device.features, 'texture-formats-tier1'); } return kTextureFormatInfo[format].colorRender || isDepthOrStencilTextureFormat(format); } @@ -2373,10 +2375,10 @@ export function isTextureFormatColorRenderable( format: GPUTextureFormat ): boolean { if (format === 'rg11b10ufloat') { - return device.features.has('rg11b10ufloat-renderable'); + return hasFeature(device.features, 'rg11b10ufloat-renderable'); } if (isTextureFormatTier1EnablesRenderAttachmentBlendableMultisample(format)) { - return device.features.has('texture-formats-tier1'); + return hasFeature(device.features, 'texture-formats-tier1'); } return !!kAllTextureFormatInfo[format].colorRender; } @@ -2389,10 +2391,10 @@ export function isTextureFormatBlendable(device: GPUDevice, format: GPUTextureFo return false; } if (format === 'rg11b10ufloat') { - return device.features.has('rg11b10ufloat-renderable'); + return hasFeature(device.features, 'rg11b10ufloat-renderable'); } if (is32Float(format)) { - return device.features.has('float32-blendable'); + return hasFeature(device.features, 'float32-blendable'); } return !!kAllTextureFormatInfo[format].colorRender?.blend; } @@ -2528,12 +2530,12 @@ function isTextureFormatUsableAsWriteOnlyStorageTexture( return false; } } - if (format === 'bgra8unorm' && device.features.has('bgra8unorm-storage')) { + if (format === 'bgra8unorm' && hasFeature(device.features, 'bgra8unorm-storage')) { return true; } if ( isTextureFormatTier1EnablesStorageReadOnlyWriteOnly(format) && - device.features.has('texture-formats-tier1') + hasFeature(device.features, 'texture-formats-tier1') ) { return true; } @@ -2610,7 +2612,7 @@ function isTextureFormatUsableAsReadWriteStorageTexture( format: GPUTextureFormat ): boolean { if (isTextureFormatTier2EnablesStorageReadWrite(format)) { - return device.features.has('texture-formats-tier2'); + return hasFeature(device.features, 'texture-formats-tier2'); } return !!kTextureFormatInfo[format].color?.readWriteStorage; } @@ -2666,10 +2668,10 @@ export function isTextureFormatMultisampled(device: GPUDevice, format: GPUTextur } } if (format === 'rg11b10ufloat') { - return device.features.has('rg11b10ufloat-renderable'); + return hasFeature(device.features, 'rg11b10ufloat-renderable'); } if (isTextureFormatTier1EnablesRenderAttachmentBlendableMultisample(format)) { - return device.features.has('texture-formats-tier1'); + return hasFeature(device.features, 'texture-formats-tier1'); } return kAllTextureFormatInfo[format].multisample; } @@ -2680,10 +2682,10 @@ export function isTextureFormatMultisampled(device: GPUDevice, format: GPUTextur */ export function isTextureFormatResolvable(device: GPUDevice, format: GPUTextureFormat): boolean { if (format === 'rg11b10ufloat') { - return device.features.has('rg11b10ufloat-renderable'); + return hasFeature(device.features, 'rg11b10ufloat-renderable'); } if (isTextureFormatTier1EnablesResolve(format)) { - return device.features.has('texture-formats-tier1'); + return hasFeature(device.features, 'texture-formats-tier1'); } // You can't resolve a non-multisampled format. if (!isTextureFormatMultisampled(device, format)) { diff --git a/src/webgpu/gpu_test.ts b/src/webgpu/gpu_test.ts index c2ebe5402c42..e0af076fa4b4 100644 --- a/src/webgpu/gpu_test.ts +++ b/src/webgpu/gpu_test.ts @@ -19,6 +19,7 @@ import { TypedArrayBufferView, TypedArrayBufferViewConstructor, unreachable, + hasFeature, } from '../common/util/util.js'; import { kPossibleLimits, kQueryTypeInfo, WGSLLanguageFeature } from './capability_info.js'; @@ -460,7 +461,10 @@ export class GPUTestBase extends Fixture { * Note: Try to use one of the more specific skipIf tests if possible. */ skipIfDeviceDoesNotHaveFeature(feature: GPUFeatureName) { - this.skipIf(!this.device.features.has(feature), `device does not have feature: '${feature}'`); + this.skipIf( + !hasFeature(this.device.features, feature), + `device does not have feature: '${feature}'` + ); } /** @@ -497,7 +501,7 @@ export class GPUTestBase extends Fixture { } const feature = getRequiredFeatureForTextureFormat(format); this.skipIf( - !!feature && !this.device.features.has(feature), + !!feature && !hasFeature(this.device.features, feature), `texture format '${format}' requires feature: '${feature}'` ); } @@ -603,7 +607,7 @@ export class GPUTestBase extends Fixture { this.skipIf(isSintOrUintFormat(format), 'sint/uint formats are not blendable'); if (is32Float(format)) { this.skipIf( - !this.device.features.has('float32-blendable'), + !hasFeature(this.device.features, 'float32-blendable'), `texture format '${format}' is not blendable` ); } @@ -616,7 +620,7 @@ export class GPUTestBase extends Fixture { this.skipIf(isSintOrUintFormat(format), 'sint/uint formats are not filterable'); if (is32Float(format)) { this.skipIf( - !this.device.features.has('float32-filterable'), + !hasFeature(this.device.features, 'float32-filterable'), `texture format '${format}' is not filterable` ); } diff --git a/src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts b/src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts index 295a68603a76..c5a58c0a9960 100644 --- a/src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts +++ b/src/webgpu/shader/execution/expression/call/builtin/texture_utils.ts @@ -1,5 +1,5 @@ import { keysOf } from '../../../../../../common/util/data_tables.js'; -import { assert, range, unreachable } from '../../../../../../common/util/util.js'; +import { assert, range, unreachable, hasFeature } from '../../../../../../common/util/util.js'; import { Float16Array } from '../../../../../../external/petamoriken/float16/float16.js'; import { ColorTextureFormat, @@ -2438,7 +2438,8 @@ function getComponentsToCheck( } const gbaUndefined = - isDepthOrStencilTextureFormat(format) && !device.features.has('texel-component-swizzle'); + isDepthOrStencilTextureFormat(format) && + !hasFeature(device.features, 'texture-component-swizzle'); if (gbaUndefined) { return kRComponent; } @@ -2585,7 +2586,7 @@ export async function checkCallResults( isDepthOrStencilTextureFormat(format) && isBuiltinGather(call.builtin) && call.component! > 0 && - !t.device.features.has('texture-component-swizzle') + !hasFeature(t.device.features, 'texture-component-swizzle') ) { continue; } @@ -5320,7 +5321,7 @@ ${stageWGSL} : type ?? 'float'; if (isFiltering && sampleType === 'unfilterable-float') { assert(is32Float(format)); - assert(t.device.features.has('float32-filterable')); + assert(hasFeature(t.device.features, 'float32-filterable')); sampleType = 'float'; } if (sampleCount > 1 && sampleType === 'float') { diff --git a/src/webgpu/util/device_pool.ts b/src/webgpu/util/device_pool.ts index 9342c37e7e91..ba3135777998 100644 --- a/src/webgpu/util/device_pool.ts +++ b/src/webgpu/util/device_pool.ts @@ -7,6 +7,7 @@ import { raceWithRejectOnTimeout, assertReject, unreachable, + hasFeature, } from '../../common/util/util.js'; import { getDefaultLimits, kPossibleLimits } from '../capability_info.js'; @@ -319,7 +320,7 @@ function supportsFeature( } for (const feature of descriptor.requiredFeatures) { - if (!adapter.features.has(feature)) { + if (!hasFeature(adapter.features, feature)) { return false; } }