bevyengine / bevyengine/bevy

Web: StandardMaterial can exceed maxSamplersPerShaderStage when enabling multiple glTF/PBR texture features

Open
#24,711 2 comments 0 reactions 0 assignees View on GitHub
A-Rendering C-Bug C-Feature D-Modest O-Web S-Ready-For-Implementation X-Contentious
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 16h
Merged PRs (30d)
171

Description

## What problem does this solve or what need does it fill?

When targeting the Web with WebGPU, enabling several glTF/PBR material texture features can make `StandardMaterial` quickly exceed the per-stage sampler limit exposed by browsers/devices.

In a Wasm/WebGPU build, this can crash rendering with the following error:

```text
Caught rendering error: The number of samplers (19) in the Fragment stage exceeds the maximum per-stage limit (16).
```

This is easy to hit because `maxSampledTexturesPerShaderStage` may be much higher while `maxSamplersPerShaderStage` remains 16. For example, a [WebGPU report](https://webgpureport.org/) may show:

```text
maxSampledTexturesPerShaderStage: 48
maxSamplersPerShaderStage: 16
```

So the issue is not the number of sampled textures, but the number of distinct sampler bindings used by the fragment shader.

There is a related issue here: https://github.com/bevyengine/bevy/issues/13974

## What solution would you like?

Add an option to reduce sampler usage for `StandardMaterial`, especially for WebGPU/Web targets.

One possible implementation is a feature-gated shared sampler mode for PBR materials:

- keep the base color texture sampler binding;
- sample metallic-roughness, normal, occlusion, emissive, transmission, specular, anisotropy, and similar PBR maps using the same base color sampler;
- enable this through a feature or render setting, for example `pbr_single_texture_sampler`.

In practice, it can reduce the PBR material sampler count from many bindings down to one material sampler, avoiding the WebGPU `maxSamplersPerShaderStage` crash.

The tradeoff is that per-texture sampler settings are ignored for those PBR maps while the option is enabled, but this is often acceptable as a WebGPU compatibility mode.

## What alternative(s) have you considered?

A more advanced solution could use a sampler cache/deduplication system, so identical sampler descriptors are only bound once instead of creating duplicate sampler bindings. This seems like a more flexible long-term solution, but it also looks significantly more complicated to implement than a shared sampler compatibility mode.

Contributor guide

Open the contributing guide

Research direction

No file or test is named. Start by locating StandardMaterial's PBR shader and sampler-binding entry points, then compare the behavior with related issue #13974. Define how the opt-in shared-sampler setting should work and verify that enabling the relevant glTF/PBR features stays within WebGPU's per-stage sampler limit.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, wasm
Domain
computer-graphics, web-dev
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.