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 new file mode 100644 index 000000000000..82585090b499 --- /dev/null +++ b/src/webgpu/api/operation/device/all_limits_and_features.spec.ts @@ -0,0 +1,95 @@ +export const description = `Test you can request an device with all features and limits`; + +import { TestCaseRecorder, TestParams } from '../../../../common/framework/fixture.js'; +import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { + DeviceSelectionDescriptor, + GPUTest, + GPUTestSubcaseBatchState, + initUncanonicalizedDeviceDescriptor, +} from '../../../gpu_test.js'; +import { CanonicalDeviceDescriptor, DescriptorModifierFn } from '../../../util/device_pool.js'; + +/** + * Gets the adapter limits as a standard JavaScript object. + */ +function getAdapterLimitsAsDeviceRequiredLimits(adapter: GPUAdapter) { + const requiredLimits: Record = {}; + const adapterLimits = adapter.limits as unknown as Record; + for (const key in adapter.limits) { + requiredLimits[key] = adapterLimits[key]; + } + return requiredLimits; +} + +function setAllLimitsToAdapterLimitsAndAddAllFeatures( + adapter: GPUAdapter, + desc: CanonicalDeviceDescriptor | undefined +) { + const descWithMaxLimits: CanonicalDeviceDescriptor = { + defaultQueue: {}, + ...desc, + requiredFeatures: [...adapter.features] as GPUFeatureName[], + requiredLimits: getAdapterLimitsAsDeviceRequiredLimits(adapter), + }; + return descWithMaxLimits; +} + +/** + * Used by MaxLimitsTest to request a device with all the max limits of the adapter. + */ +export class AllLimitsAndFeaturesGPUTestSubcaseBatchState extends GPUTestSubcaseBatchState { + override selectDeviceOrSkipTestCase( + descriptor: DeviceSelectionDescriptor, + descriptorModifierFn?: DescriptorModifierFn + ): void { + const wrapper = (adapter: GPUAdapter, desc: CanonicalDeviceDescriptor | undefined) => { + desc = descriptorModifierFn ? descriptorModifierFn(adapter, desc) : desc; + return setAllLimitsToAdapterLimitsAndAddAllFeatures(adapter, desc); + }; + super.selectDeviceOrSkipTestCase(initUncanonicalizedDeviceDescriptor(descriptor), wrapper); + } +} + +/** + * A Test that requests all the max limits from the adapter on the device. + */ +export class AllLimitsAndFeaturesLimitsTest extends GPUTest { + public static override MakeSharedState( + recorder: TestCaseRecorder, + params: TestParams + ): GPUTestSubcaseBatchState { + return new AllLimitsAndFeaturesGPUTestSubcaseBatchState(recorder, params); + } +} + +export const g = makeTestGroup(AllLimitsAndFeaturesLimitsTest); + +g.test('everything') + .desc( + ` +Test we can request all features and limits. + +It is expected that, even though this is generally not recommended, because +it is possible, make sure it works and continues to work going forward so that +changes to WebGPU do not break sites requesting everything. +` + ) + .fn(t => { + // Test that all the limits on the device match the adapter. + const adapterLimits = t.adapter.limits as unknown as Record; + const deviceLimits = t.device.limits as unknown as Record; + for (const key in t.adapter.limits) { + const deviceLimit = deviceLimits[key]; + const adapterLimit = adapterLimits[key]; + t.expect( + deviceLimit === adapterLimit, + `device.limits.${key} (${deviceLimit}) === adapter.limits.${key} (${adapterLimit})` + ); + } + + // Test that all the adapter features are on the device. + for (const feature of t.adapter.features) { + t.expect(t.device.features.has(feature), `device has feature: ${feature}`); + } + }); diff --git a/src/webgpu/gpu_test.ts b/src/webgpu/gpu_test.ts index 66c7c1208c28..d6d6626109d4 100644 --- a/src/webgpu/gpu_test.ts +++ b/src/webgpu/gpu_test.ts @@ -78,7 +78,7 @@ export type ResourceState = (typeof kResourceStateValues)[number]; export const kResourceStates: readonly ResourceState[] = kResourceStateValues; /** Various "convenient" shorthands for GPUDeviceDescriptors for selectDevice functions. */ -type DeviceSelectionDescriptor = +export type DeviceSelectionDescriptor = | UncanonicalizedDeviceDescriptor | GPUFeatureName | undefined @@ -1294,6 +1294,11 @@ function getAdapterLimitsAsDeviceRequiredLimits(adapter: GPUAdapter) { const requiredLimits: Record = {}; const adapterLimits = adapter.limits as unknown as Record; for (const key in adapter.limits) { + // MAINTENANCE_TODO: Remove this once minSubgroupSize is removed from + // chromium. + if (key === 'maxSubgroupSize' || key === 'minSubgroupSize') { + continue; + } requiredLimits[key] = adapterLimits[key]; } return requiredLimits;