features property

  1. @override
DeviceFeatures features
latefinal

Every capability, decided once from what the device was granted — see webgpuDeviceFeatures, which is where each answer and each absence is explained, and which runs on the VM.

The answers the supportsX getters gave before 1.0 are these, read through DeviceCapabilityForwarders, and none of them moved:

  • gpu-timestamps and timestamp-query where the adapter granted timestamp-query — H2, written per labelled pass and read back a frame or two later.
  • compute always — H6: storage buffers, _pipelines built from the generated compute table, passes encoded as they go, and a readback through a mappable staging buffer.
  • float32-filterable where the adapter granted it, which open asks for whenever it is offered; float32-renderable is core, so supportsFloat32Filtering answers exactly what it did.
  • independent-blend always: every colour target in a WebGPU pipeline carries its own equation, and the pipeline signature keys on the list of them, so the index has always been honoured here — R8 only asked.
  • offscreen-multisample, stencil, manual-mipmaps always.
  • blend-constant never, and the absence is a finding rather than a limitation. See WebGpuEncoder.setBlendColor, which is the refusal it promises.
  • wireframe never: WebGPU has no polygon fill mode at all. A wireframe here is line primitives and an index buffer built for them, which is the renderer's decision — the same answer WebGL2 gives for the same reason.
  • alpha-to-coverage always — P7: a pipeline's alphaToCoverageEnabled, wherever the pass multisamples, which the scene pass does at four.
  • cube-textures always: a cube is a six-layer texture with a "cube" view over it, and the sky pass needs one.
  • render-to-mip-level always, and what it turns on is reflection probes.

The false render-to-mip-level used to be was honest when it was written and had stopped being so. It was written beside a createCubeRenderTarget that answered null: a probe needs a cube to draw six views into and a chain to convolve them down, ReflectionProbeNode.supportedOn asks for both, and answering yes to the second while the first was missing would have handed the renderer a probe and got a crash where a skip belonged. The cube arrived later — the conformance suite would not let supportsCubeTextures promise a face a pass could name and then hand back nothing — and the answer stayed false, which by then described no missing work at all. A refusal that outlives its reason is worse than the gap it once guarded, because nobody goes looking behind it.

There was nothing left to build. The chain a probe wants is not a generateMipmap — this API has none, and the engine never asks a device for one. Renderer._prefilterProbe writes every level itself, as an ordinary full-screen pass whose colour target names a face and a level, and on this backend both of those are one mechanism: baseArrayLayer picks the face and baseMipLevel picks the level on a plain 2D view, which WebGpuTexture.attachmentView has always made. The pass's initial viewport covers the level rather than the texture, because WebGPU takes it from the view's own size, so §7.2's last rule needs no arithmetic here either.

What said so is the picture rather than the reading: probe-car records through this backend and lands on Impeller's reference at nought of a hundred and seventy-two thousand eight hundred pixels, worst channel zero. test/reflection_probe_test.dart asks the question the capability actually promises: that a mirror ball between a red wall and a blue one shows each on its own side.

Implementation

@override
late final DeviceFeatures features = webgpuDeviceFeatures(
  granted: (String feature) => _gpuDevice.features.has(feature),
);