Hello. I tried to render a few textures in rgba8unorm and rgba32float formats on WebGPU, and encountered the error:
Filtering sampler [Sampler] is incompatible with non-filtering sampler binding.
- While validating entries[4] as a Sampler.
Expected entry layout: { binding: 5, visibility: ShaderStage::Fragment, sampler: { type: SamplerBindingType::NonFiltering } }
- While validating [BindGroupDescriptor] against [BindGroupLayout]
- While calling [Device].CreateBindGroup([BindGroupDescriptor]).
My browser doesnāt have āfloat32-filterableā feature enabled, so BJS detects it and automatically uses nearest sampler with ānon-filteringā binding. It works well by itself, but when the scene has rgba8unorm and rgba32float formats mixed together, it produces the error above and renders nothing. I suspect some internal states are incorrectly shared.
Demo: https://playground.babylonjs.com/?webgpu#3DM8LJ. It renders nothing on WebGPU, and the expected result can be seen in WebGL2 mode.
Testing environment:
- Windows 10 Home 21H2 19044.2728
- Chrome 113.0.5672.93 (64-bit)
- Babylon.js 6.3.1 and 6.2.0 (WebGPU)
" 32 bits float textures are not linear-filterable (see List of texture formats), meaning you canāt use the bi/tri linear filtering with them, for eg. You will need to use 16 bits float textures instead, until the spec (or an extension) adds support for it."
your 32 bit texture is using trilinear sampling
This isnāt an issue. As I mentioned, BJS detects it and automatically uses nearest sampler:
https://github.com/BabylonJS/Babylon.js/blob/bd15435c89d8dcad58b68852c6f4808b48fb8f6b/packages/dev/core/src/Materials/Textures/rawTexture.ts#L54
The bug is still reproduceable when TEXTURE_NEAREST_SAMPLINGMODE is used. I should have used it instead to avoid the confusion.
commenting these lines still broken for you?
No, it doesnāt break after commenting the lines in the box.
However, I do want to use float32 texture on webgpu, and babylonjs indeed handles it. The float32 texture actually works, if you comment out either āsphere1ā or āsphere3ā part below. In other words:
- a scene with a unorm8 texture, a float32 texture: works
- a scene with a float32 texture, a unorm8 texture: works
- a scene with a unorm8 texture, a float32 texture, a unorm8 texture: error
The specific order āfilterable, non-filterable, filterableā causes the error, which is clearly a bug. I digged into the source code but could not figure out what went wrong.
i think in order for it to autofix itself, it has to be be using float32 + a linear filter sampling mode on the SAME material, because its not looking through all materials. i think the fix would be to add a global flag and set it to true once a linear filter sample is specified, and check the global flag instead of the constructor arguments to determine if it needs to use the nearest sampling mode. make sense? im pretty tired lol. ah shit, itād have to go back through and fix any previously created materials tooā¦hmm
actually, i think it just needs more detailed checks.
Currently, if you use float texture and a tri/bi linear filter sampler, the conditional check will likely change your sampler mode to nearest sampling mode.
for example:
BABYLON.Constants.TEXTURE_TRILINEAR_SAMPLINGMODE,
BABYLON.Constants.TEXTURETYPE_FLOAT
ā it fails test and you end up with:
BABYLON.Constants.TEXTURE_NEAREST_SAMPLINGMODE,
BABYLON.Constants.TEXTURETYPE_FLOAT
then in a second material, you use:
BABYLON.Constants.TEXTURE_TRILINEAR_SAMPLINGMODE,
BABYLON.Constants.TEXTURETYPE_UNSIGNED_BYTE (or anything except float here)
it passes check.so you get it.
now you have one material with a linear filter sampler and a float texture in another. KABOOM.
I think it would be better to FIRST change flat to half float.
(original):
if (!this._engine._caps.textureFloatLinearFiltering && type === Constants.TEXTURETYPE_FLOAT) {
samplingMode = Constants.TEXTURE_NEAREST_SAMPLINGMODE;
}
if (!this._engine._caps.textureHalfFloatLinearFiltering && type === Constants.TEXTURETYPE_HALF_FLOAT) {
samplingMode = Constants.TEXTURE_NEAREST_SAMPLINGMODE;
}
(updated):
//check all linear sampling modes here
if ( (samplingMode === Constants.TEXTURE_TRILINEAR_SAMPLINGMODE) || (samplingMode === BABYLON.Constants.TEXTURE_BILINEAR_SAMPLINGMODE) ) {
// compare user defined precison to hardware caps
//handle user asking for float (unlikely to be supported as of May 2023)
if(type === Constants.TEXTURETYPE_FLOAT) {
//unlikely, but its what they asked for so check it first.
if(this._engine._caps.textureFloatLinearFiltering) { void(0) /*give'em what they want*/ };
//very likely user device supports half float, even though they asked for float. just downgrade precision to half float
if(this._engine._caps.textureHalfFloatLinearFiltering) {type = Constants.TEXTURETYPE_HALF_FLOAT};
//this was the previous implementation's default behavior. bad apples and balmer's too sweaty. change sampling mode and keep float
else samplingMode = Constants.TEXTURE_NEAREST_SAMPLINGMODE;
}
//handle user asking for half float (likely to be supported as of May 2023)
if(type === Constants.TEXTURETYPE_HALF_FLOAT) {
//very likely
if(this._engine._caps.textureHalfFloatLinearFiltering) {void(0) /*give'em what they want*/ };
//change sampling mode and keep half float
else samplingMode = Constants.TEXTURE_NEAREST_SAMPLINGMODE;
}
}
//feel so dirty with no assertions here
I believe the issue is deeper than just samplingMode downgrade. When I change all occurrences of TEXTURE_TRILINEAR_SAMPLINGMODE
into TEXTURE_NEAREST_SAMPLINGMODE
in the demo, it still fails, however with a different error:
Bind group layout [BindGroupLayout] of pipeline layout [PipelineLayout] does not match layout [BindGroupLayout] of bind group [BindGroup] set at group index 1.
1 Like
It seems thereās a problem with pipeline caching, if you create mat2 first it does workā¦
I will have to dig a bit more to find the problem.
1 Like