import {
  DeviceTabs,
  Info,
  Feature as F,
  Limit as L,
  WebGLLimit as WL,
  WebGLExtensions
} from '@site/src/react-luma';

# DeviceFeature

The luma.gl `Device` provides a range of fields and functions to help an application
determine the capabilities of the underlying platform and API.

The tables on this page use luma.gl Device APIs to display the capabilities of your current browser.
Open this page in different browsers to compare capabilities.

## Fields

### Device.info

A `DeviceInfo` object with fields that describe the device.

<DeviceTabs />

| Field                    | This Browser                        | Description                                                |
| ------------------------ | ----------------------------------- | ---------------------------------------------------------- |
| `type`                   | <Info f="type" />                   | Device type `webgpu`, `webgl2` or `webgl`                  |
| `vendor`                 | <Info f="vendor" />                 | GPU vendor                                                 |
| `renderer`               | <Info f="renderer" />               | GPU Driver                                                 |
| `version`                | <Info f="version" />                | Driver version                                             |
| `gpu`                    | <Info f="gpu" />                    | `apple`, `intel`, `nvidia`, `amd`, `software` or `unknown` |
| `gpuType`                | <Info f="gpuType" />                | `discrete`, `integrated`, `cpu` or `unknown`               |
| `gpuBackend`             | <Info f="gpuBackend" />             | `metal`, `opengl`, `vulkan`, `d3d12`, ... or `unknown`     |
| `gpuArchitecture`        | <Info f="gpuArchitecture" />        | `common-3` on Apple                                        |
| `shadingLanguage`        | <Info f="shadingLanguage" />        | Shanding language `wgsl`, `glsl`                           |
| `shadingLanguageVersion` | <Info f="shadingLanguageVersion" /> | Shading language version GLSL 3.00 = 300, GLSL 1.00 = 100) |

- Note that the Chrome browser only exposes limited information by default. Set the [chrome://flags/#enable-webgpu-developer-features](chrome://flags/#enable-webgpu-developer-features) flag to see more WebGPU info.

### Device.features

luma.gl provides a unified feature detection system across WebGPU, WebGL and GLSL.
Each device has a `device.features` field that holds a set of strings (`Set<DeviceFeature>`).

A substantial set of features are devoted to texture capabilites, however these can also
be queried on a per-texture basis

<DeviceTabs />

| `luma.gl Feature`                      | This<br /> Browser                            | Description                            |
| -------------------------------------- | --------------------------------------------- | -------------------------------------- |
| **Platform**                           |
| `webgpu`                               | <F f="webgpu"/>                               | WebGPU device.                         |
| `webgl`                                | <F f="webgl"/>                                | WebGL2 device.                         |
| `glsl`                                 | <F f="glsl"/>                                 | GLSL shader language.                  |
| `wgsl`                                 | <F f="wgsl"/>                                 | WGSL shader language.                  |
| **Features**                           |
| `depth-clip-control`                   | <F f="depth-clip-control"/>                   | Depth clamps instead of clips.         |
| `indirect-first-instance`              | <F f="indirect-first-instance"/>              | Specify via GPU buffer                 |
| `timestamp-query`                      | <F f="timestamp-query"/>                      |                                        |
| `timer-query-webgl`                    | <F f="timer-query-webgl"/>                    | GPU timer support                      |
| `shader-status-async-webgl`            | <F f="shader-status-async-webgl"/>            | Non-blocking compile/link status       |
| `provoking-vertex-webgl`               | <F f="provoking-vertex-webgl"/>               | Primitive vertex used for flat shading |
| **WebGL-only Features**                |
| `transform-feedback-webgl`             | <F f="transform-feedback-webgl"/>             | `TransformFeedback` support            |
| `uniforms-webgl`                       | <F f="uniforms-webgl"/>                       | non-UBO uniforms support               |
| `constant-attributes-webgl`            | <F f="constant-attributes-webgl"/>            | Constant attributes                    |
| **Shaders**                            |
| `shader-f16`                           | <F f="shader-f16"/>                           | WGSL supports `f16`                    |
| **Textures**                           |
| `depth24unorm-stencil8`                | <F f="depth24unorm-stencil8"/>                | `UNSIGNED_INT_24_8_WEBGL`              |
| `depth32float-stencil8`                | <F f="depth32float-stencil8"/>                | WebGPU only                            |
| `float32-filterable`                   | <F f="float32-filterable"/>                   | float32 textures are filterable        |
| `float32-filterable-linear-webgl`      | <F f="float32-filterable-linear-webgl"/>      | float32 `linear` filtering             |
| `float16-filterable-linear-webgl`      | <F f="float16-filterable-linear-webgl`" />    | float16 `linear` filtering             |
| `rg11b10ufloat-renderable`             | <F f="rg11b10ufloat-renderable"/>             | rg11b10ufloat textures renderable      |
| `float32-renderable-webgl`             | <F f="float32-renderable-webgl"/>             | float32 textures renderable            |
| `float16-renderable-webgl`             | <F f="float16-renderable-webgl"/>             | float16 textures renderable            |
| `bgra8unorm-storage`                   | <F f="bgra8unorm-storage"/>                   | can be used as storage binding.        |
| `texture-filterable-anisotropic-webgl` | <F f="texture-filterable-anisotropic-webgl"/> | anisotropic filtering, common          |
| `texture-blend-float-webgl`            | <F f="texture-blend-float-webgl"/>            | float texture blending                 |
| **Compressed Textures**                |
| `texture-compression-bc`               | <F f="texture-compression-bc"/>               | DXT (BC1-BC7). Desktops.               |
| `texture-compression-bc5-webgl`        | <F f="texture-compression-bc5-webgl"/>        | DXT (BC1-BC5). Desktops.               |
| `texture-compression-etc2`             | <F f="texture-compression-etc2"/>             | Performance caveats.                   |
| `texture-compression-astc`             | <F f="texture-compression-astc"/>             | ASTC.                                  |
| `texture-compression-etc1-webgl`       | <F f="texture-compression-etc1-webgl"/>       | Qualcomm Snapdragon. Android.          |
| `texture-compression-pvrtc-webgl`      | <F f="texture-compression-pvrtc-webgl"/>      | PowerVR GPUs, iOS devices.             |
| `texture-compression-atc-webgl`        | <F f="texture-compression-atc-webgl"/>        | Qualcomm Adreno GPUs. Android.         |

## Usage

Another example of feature detection

```typescript
// Checks if `Query` objects can do async queries of GPU timings
if (device.features.has('timer-query-webgl')) {
   ...
}
// Alternatively - do the same query using raw WebGL extensions
if (webglDevice.gl.getExtension('EXT_disjoint_timer_query') || webglDevice.gl.getExtension('EXT_disjoint_timer_query_webgl2')) {
   ...
}
```

## WebGL

If you know that you are running on WebGL, you don't need to go through
the luma.gl Device APIs. You can access "raw" WebGL extensions and limits directly.

### WebGL extensions

It is easy to get the list of actual WebGL extensions from `WebGLDevice`:

```typescript
const webglDevice = device instanceof WebGLDevice ? (device as WebGLDevice) : null;
const extensions = webglDevice ? webglDevice.gl.getSupportedExtensions() : [];
console.log(extensions);
```

On your current browser, this would yield:

<DeviceTabs />

<WebGLExtensions />

The following table illustrates how WebGL extensions map to luma.gl features.

:::info
Caveat: this table is mainly included for reference purposes, in cases where
it is helpful to understand exactly which extensions are being used by luma.gl
under the hood.
:::

:::caution
WebGL extensions can be demanding to work with directly. The extensions are very granular,
enabling subfeatures of bigger features.
:::

| `luma.gl feature`                           | WebGL Extension                                                | Description                                                                                                                     |
| ------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| **General WebGL Features**                  |                                                                |                                                                                                                                 |
| `webgl`                                     | True for WebGL Context                                         |                                                                                                                                 |
| `timer-query-webgl`                         | [`EXT_disjoint_timer_query_webgl2`][timer_query_webgl2]        |                                                                                                                                 |
| \*\* GLSL extensions\*\*                    |                                                                |                                                                                                                                 |
| **`Texture`s and `Framebuffer`s**           |                                                                |                                                                                                                                 |
| `texture-float32-webgl1`                    | [`OES_texture_float`][texture_float]                           | Floating point textures can be created and sampled (filtering/rendering are queried separately)                                 |
| `texture-float16-webgl1` (Extension 1 of 2) | [`OES_texture_half_float`][texture_half_float]                 | Half float (`Uint16Array`) textures can be created and set as samplers                                                          |
| `texture-float16-webgl1` (Extension 2 of 2) | [`WEBGL_color_buffer_float`][webgl_color_buffer_float]         | (This feature depends on 2 extensions)                                                                                          |
| `float32-renderable-webgl`                  | [`EXT_color_buffer_float`][ext_color_buffer_float]             | Floating point `Texture`s are renderable/readable, (attach to `Framebuffer`, write in fragment shaders, read with `readPixels`. |
| `float16-renderable-webgl`                  | [`EXT_color_buffer_half_float`][color_buffer_half_float]       | Half float format `Texture`s are renderable and readable                                                                        |
| `float-blend-webgl1`                        | [`EXT_float_blend`][float_blend]                               | Blending with 32-bit floating point color buffers                                                                               |
| `depth_buffers`                             | [`WEBGL_depth_texture`][depth_texture]                         | Depth buffers can be stored in `Texture`s, e.g. for shadow map calculations                                                     |
| `texture-filter-linear-float`               | [`OES_texture_float_linear`][texture_float_linear]             | Linear texture filtering for floating point textures                                                                            |
| `texture-filter-linear-half-float-webgl`    | [`OES_texture_half_float_linear`][texture_half_float_linear]   | Linear texture filtering for half float textures                                                                                |
| `texture_filter-anisotropic-webgl`          | [`EXT_texture_filter_anisotropic`][texture_filter_anisotropic] | Anisotropic texture filtering                                                                                                   |

## Remarks

- Some extensions will not be enabled until they have been queried. luma always queries on startup to enable, app only needs to query again it wants to test platform.
- The capability detection system works regardless of whether the app is running in a browser or in headless mode under Node.js.
- Naturally, given that queries to driver and GPU are typically expensive in WebGL, the capabilities system will cache any queries.

[instanced_arrays]: https://developer.mozilla.org/en-US/docs/Web/API/ANGLE_instanced_arrays
[vertex_array_object]: https://developer.mozilla.org/en-US/docs/Web/API/OES_vertex_array_object
[element_index_uint]: https://developer.mozilla.org/en-US/docs/Web/API/OES_element_index_uint
[blend_minmax]: https://developer.mozilla.org/en-US/docs/Web/API/EXT_blend_minmax
[timer_query_webgl]: https://developer.mozilla.org/en-US/docs/Web/API/EXT_disjoint_timer_query
[timer_query_webgl2]: https://www.khronos.org/registry/webgl/extensions/EXT_disjoint_timer_query_webgl2/
[texture_compression_bptc]: https://developer.mozilla.org/en-US/docs/Web/API/EXT_texture_compression_bptc
[texture_compression_rgtc]: https://developer.mozilla.org/en-US/docs/Web/API/EXT_texture_compression_rgtc
[texture_float]: https://developer.mozilla.org/en-US/docs/Web/API/OES_texture_float
[texture_half_float]: https://developer.mozilla.org/en-US/docs/Web/API/OES_texture_half_float
[draw_buffers]: https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_draw_buffers
[ext_color_buffer_float]: https://developer.mozilla.org/en-US/docs/Web/API/EXT_color_buffer_float
[webgl_color_buffer_float]: https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_color_buffer_float
[shader_texture_lod]: https://developer.mozilla.org/en-US/docs/Web/API/EXT_shader_texture_lod
[draw_buffers]: https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_draw_buffers
[frag_depth]: https://developer.mozilla.org/en-US/docs/Web/API/EXT_frag_depth
[standard_derivatives]: https://developer.mozilla.org/en-US/docs/Web/API/OES_standard_derivatives
[color_buffer_float]: https://developer.mozilla.org/en-US/docs/Web/API/EXT_color_buffer_float
[color_buffer_half_float]: https://developer.mozilla.org/en-US/docs/Web/API/EXT_color_buffer_half_float
[float_blend]: https://developer.mozilla.org/en-US/docs/Web/API/EXT_float_blend
[depth_texture]: https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_depth_texture
[texture_float_linear]: https://developer.mozilla.org/en-US/docs/Web/API/OES_texture_float_linear
[texture_half_float_linear]: https://developer.mozilla.org/en-US/docs/Web/API/OES_texture_half_float_linear
[texture_filter_anisotropic]: https://developer.mozilla.org/en-US/docs/Web/API/EXT_texture_filter_anisotropic
[sRGB]: https://developer.mozilla.org/en-US/docs/Web/API/EXT_sRGB
