这是indexloc提供的服务,不要输入任何密码
Skip to content

Compat: Should requesting compat mode on a device that supports core, return core or compat? #4731

@greggman

Description

@greggman

The spec proposal currently says

When calling GPU.RequestAdapter(), passing compatibilityMode = true in the GPURequestAdapterOptions will indicate to the User Agent to select the Compatibility subset of WebGPU. Any Devices created from the resulting Adapter on supporting UAs will support only Compatibility mode. Calls to APIs unsupported by Compatibility mode will result in validation errors.

Note that a supporting User Agent may return a compatibilityMode = true Adapter which is backed by a fully WebGPU-capable hardware adapter, such as D3D12, Metal or Vulkan, so long as it validates all subsequent API calls made on the Adapter and the objects it vends against the Compatibility subset.

As a dev, I think I'd prefer that if a user agent can return core that it return core. Then, I can design my app to work if I get compat, but use more features if I get core. This seems similar to enabling features

core

const adapter = await navigator.gpu.requestAdapter();

const requiredFeatures = [];

// enable features both in the device and in my code if they exist
const canFilterF32 = adapter.features.has('float32-filterable');
if (canFilterF32) {
  requiredFeatures.push('float32-filterable');

const device = adapter.requestDevice({ requiredFeatures });

...

const sampler = device.createSampler({
  magFilter: canFilterF32 ? 'linear' : 'nearest',
  ...
});

In compat I'd like to do similar things

compat

const adapter = await navigator.gpu.requestAdapter({compatibilityMode: true});

const canUseSampleInterpolation = !adapter.isCompatibilityMode;

...

const module = device.createShaderModule({
  code: canUseSampleIterpolation
    ? higherQualityShader
    : lowerQualityShader,
});

This pattern seems intuitive to me. It will also work for some cases as a UA that doesn't support compat will return a non-compat adapter.

As it is currently implemented in Chrome, requesting compat gives you compat, period. So, the only way to do better than compat is to first request core and, only if it fails, then request compat

const adapter = await navigator.gpu.requestAdapter() ??
                await navigator.gpu.requestAdapter({compatibilityMode: true});

const canUseSampleInterpolation = !adapter.isCompatibilityMode;

...

I guess it's not that bad to do two requests, although it is slower. It's also less intuitive IMO but the spec can spell out how to do it.

The disadvantage to returning core when compat is requested is that you can't test compat validation in the CTS nor in your own code without either more flags, either to requestAdapter (forceCompatibilityModeIfSupported: true) or browser flags external to the page.

Whichever direction (1) return core if you can (2) return compat if requested, should it be specified which? The current proposal says "a supporting User Agent may return a compatibilityMode = true Adapter". Should that "may" change to "must" or "must not" or stay as "may"?

Note that regardless of these issues, a UA can of course completely ignore compatibility mode.

Metadata

Metadata

Assignees

No one assigned

    Labels

    apiWebGPU APIcompatWebGPU Compatibility Mode

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions