Loading a model with KHR_mesh_quantization extension in WebGPU

OS: Windows 10 x64
Browser: ungoogled-chromium 108.0.5359.95
Babylon.js: 5.36.0
Playground: Babylon.js Playground

Expected:
Load the model and renders it.

Actual:
Shows a white screen.

Manually switch to WebGPU to reproduce in the playground link.
Note the model is embedded into the playground as base64 data-uri.

Edit: Warnings from Console attached below:

Warnings

Attribute base type (Uint) does not match the shader’s base type (Float) in location (0).

  • While validating attributes[0].
  • While validating buffers[0].
  • While validating vertex state.
  • While calling [Device].CreateRenderPipeline([RenderPipelineDescriptor “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”]).

logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (1): [object GPUValidationError] - Attribute base type (Uint) does not match the shader’s base type (Float) in location (0).

  • While validating attributes[0].
  • While validating buffers[0].
  • While validating vertex state.
  • While calling [Device].CreateRenderPipeline([RenderPipelineDescriptor “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”]).

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
250[Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”] is invalid.

  • While encoding [RenderPassEncoder].SetPipeline([Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”]).

logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (2): [object GPUValidationError] - [Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”] is invalid.

  • While encoding [RenderPassEncoder].SetPipeline([Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”]).

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
249[Invalid CommandBuffer] is invalid.
at ValidateObject (…..\third_party\dawn\src\dawn\native\Device.cpp:651)
at ValidateSubmit (…..\third_party\dawn\src\dawn\native\Queue.cpp:393)

logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (3): [object GPUValidationError] - [Invalid CommandBuffer] is invalid.
at ValidateObject (…..\third_party\dawn\src\dawn\native\Device.cpp:651)
at ValidateSubmit (…..\third_party\dawn\src\dawn\native\Queue.cpp:393)

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (4): [object GPUValidationError] - [Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”] is invalid.

  • While encoding [RenderPassEncoder].SetPipeline([Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”]).

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (5): [object GPUValidationError] - [Invalid CommandBuffer] is invalid.
at ValidateObject (…..\third_party\dawn\src\dawn\native\Device.cpp:651)
at ValidateSubmit (…..\third_party\dawn\src\dawn\native\Queue.cpp:393)

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (6): [object GPUValidationError] - [Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”] is invalid.

  • While encoding [RenderPassEncoder].SetPipeline([Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”]).

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (7): [object GPUValidationError] - [Invalid CommandBuffer] is invalid.
at ValidateObject (…..\third_party\dawn\src\dawn\native\Device.cpp:651)
at ValidateSubmit (…..\third_party\dawn\src\dawn\native\Queue.cpp:393)

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (8): [object GPUValidationError] - [Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”] is invalid.

  • While encoding [RenderPassEncoder].SetPipeline([Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”]).

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (9): [object GPUValidationError] - [Invalid CommandBuffer] is invalid.
at ValidateObject (…..\third_party\dawn\src\dawn\native\Device.cpp:651)
at ValidateSubmit (…..\third_party\dawn\src\dawn\native\Queue.cpp:393)

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (10): [object GPUValidationError] - [Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”] is invalid.

  • While encoding [RenderPassEncoder].SetPipeline([Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”]).

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (11): [object GPUValidationError] - [Invalid CommandBuffer] is invalid.
at ValidateObject (…..\third_party\dawn\src\dawn\native\Device.cpp:651)
at ValidateSubmit (…..\third_party\dawn\src\dawn\native\Queue.cpp:393)

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (12): [object GPUValidationError] - [Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”] is invalid.

  • While encoding [RenderPassEncoder].SetPipeline([Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”]).

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (13): [object GPUValidationError] - [Invalid CommandBuffer] is invalid.
at ValidateObject (…..\third_party\dawn\src\dawn\native\Device.cpp:651)
at ValidateSubmit (…..\third_party\dawn\src\dawn\native\Queue.cpp:393)

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (14): [object GPUValidationError] - [Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”] is invalid.

  • While encoding [RenderPassEncoder].SetPipeline([Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”]).

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (15): [object GPUValidationError] - [Invalid CommandBuffer] is invalid.
at ValidateObject (…..\third_party\dawn\src\dawn\native\Device.cpp:651)
at ValidateSubmit (…..\third_party\dawn\src\dawn\native\Queue.cpp:393)

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (16): [object GPUValidationError] - [Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”] is invalid.

  • While encoding [RenderPassEncoder].SetPipeline([Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”]).

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (17): [object GPUValidationError] - [Invalid CommandBuffer] is invalid.
at ValidateObject (…..\third_party\dawn\src\dawn\native\Device.cpp:651)
at ValidateSubmit (…..\third_party\dawn\src\dawn\native\Queue.cpp:393)

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (18): [object GPUValidationError] - [Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”] is invalid.

  • While encoding [RenderPassEncoder].SetPipeline([Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”]).

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (19): [object GPUValidationError] - [Invalid CommandBuffer] is invalid.
at ValidateObject (…..\third_party\dawn\src\dawn\native\Device.cpp:651)
at ValidateSubmit (…..\third_party\dawn\src\dawn\native\Queue.cpp:393)

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error (20): [object GPUValidationError] - [Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”] is invalid.

  • While encoding [RenderPassEncoder].SetPipeline([Invalid RenderPipeline “RenderPipeline_bgra8unorm_depth24plus-stencil8_samples4”]).

e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:649
logger.ts:103 BJS - [16:30:40]: WebGPU uncaptured error: too many warnings (20), no more warnings will be reported to the console for this engine.
e._LogEnabled @ logger.ts:103
(anonymous) @ webgpuEngine.ts:651
/#E1F3AI:1 WebGPU: too many warnings, no more warnings will be reported to the console for this GPUDevice.

Welcome aboard!

That’s a known limitation, the feature is not implemented yet. See WebGPU Status | Babylon.js Documentation :

Support types other than float for the vertex buffers (position, normal, uv, ...)
* Contrary to WebGL, in WebGPU there's no automatic conversion from the type of the 
vertex buffer to the type used by shader

From the Editor’s Draft spec, there is unsigned int and signed int data types, so would it be possible to produce different shaders based on vertex type?

Our shaders expect some system attributes (position, uv, normal, etc) to be float data. We can’t duplicate these shaders so that they can handle other types like int, short, etc, it would be a maintenance nightmare.

In WebGL this works because there’s an automatic conversion to float if needed, but not in WebGPU. So, we will have to create (internally) new vertex buffers if we want to pass integer types to our shaders for these system attributes.

Thanks for reply.
Would it be possible to use type-aliases which can be replaced without fully parsing the WGSL code, or do it in the tintWASM module for runtime-compiled shaders?
Additionally, would it worth to fully parse the shaders and generate code for different types at compile time?

The solution must work in both GLSL and WGSL and type-aliases are only for WGSL. Even then, I don’t see how this would solve the problem as we don’t want to break backwards compatibility (users should not have to update their shaders to work in this scenario).

This can be a solution, it depends on whether we are able to solve the problem only by shader code injection or if we have to create a float vertex buffer instead.

we don’t want to break backwards compatibility

Is the 6.0 milestone planned next year acceptable for breaking changes?

it depends on whether we are able to solve the problem only by shader code injection

Since variables in custom shader codes are based on name of variable, parsers could locate and rewrite this, maybe to a new name, and prepend codes for type convertion in entry points.

create a float vertex buffer instead

Would this mean converting int attributes to floats in the device.createBuffer and device.queue.writeBuffer steps, making it consumes much more GPU memory than directly use int types?

No, breaking changes are not allowed in Babylon.js :slight_smile:

This is one of the core feature, so we only accept breaking changes when there is no other possibility (like in version 5.0 when we added WebGPU support, texture reading can’t be synchronous in WebGPU so readPixels was changed from synchronous to asynchronous).

Yes, doing it by hand is quite easy, what you need to do:

  • replace attribute vec3 position; with attribute ivec3 position; vec3 position_;
  • add position_ = vec3(position); to the beginning of the main function
  • make sure to use position_ instead of position in the remaining shader code

The last point is not so easy. Because position is declared globally, any function can use it, so we would need to parse all the code to replace position with position_, and doing it as a string replacement won’t do (imagine a function that takes a parameter named position, for eg)…

It would be easier to use attribute ivec3 position_; vec3 position; instead, that way we don’t have to do the global replacement. However, this won’t work because our js code expects the position attribute to be named position in the shader code (in various places: when creating an effect, when binding a vertex buffer to an attribute, in user APIs like getVerticesData / getVertexBuffer, …).

An additional difficulty is that the compilation of the shader is decoupled from the creation of the render pipeline: the compilation comes first (when the effect is created) and the creation of the render pipeline comes afterwards (just before drawing). The problem is that we only know if a vertex buffer contains integers at pipeline creation time, so we need a “retroaction” step in case we detect that a vertex buffer contains integers while the corresponding attribute is declared as a float/vector of floats in the shader code. And this has to work with our render pipeline cache mechanism…

Yes, that’s why it’s not the preferred solution :slight_smile:

Note, however, that it would be the fastest in terms of performance.

1 Like

Since babylon.js 6.0 is released and google is bringing webgpu to beta, what is the status of this?

This is still planned, but we also have other important tasks to consider (and as you said, WebGPU is still in the beta stage).

1 Like

It went to release now for chrome 113:

This PR will add support for non float vertex buffers:

2 Likes

Confirmed on chromium 113.0.5672.64