What exactly MAX_UNIFORM_BLOCK_SIZE limits?

82 views
Skip to first unread message

Mikhail Turkeev

unread,
Nov 27, 2023, 4:45:28 PM11/27/23
to WebGL Dev List
Interpretation 1) Judging by the name I would think that it is the maximum number of bytes that could go into a single uniform block binding. Or the maximum number that could go into the last argument of gl.bindBufferRange.

Interpretation 2) But for some devices it seems the number is actually the maximum size of the underlying buffer you're allowed to create for UBOs.

I've only had problems with the first interpretation on two devices, so I am not sure.
The devices are:
- Samsung Galaxy S22 (yes, with infamous Xclipse 920) and Chrome - it seems to sometimes use wrong uniform blocks.
- and iPhone X with iOS 16.5.1 and Safari - it either silently loses context or crashes the browser.

For some background, here is how we use UBOs. We gave up plain uniforms (except textures), and now we do this:

Camera, lights, some shadow parameters get their own uniform blocks, and their bindings are always the same so they are shared across the most of draw calls.

Every material gets one uniform block for their parameters (metalness, roughness, albedo, texture transforms etc.).

We also maintain CPU side copy of the underlying GPU buffers, so when we want to change a field in a uniform block we check if it actually changes, then if it does, grow a dirty range stored per buffer, and then only send the dirty range at most once per frame per buffer in bufferSubData calls.

We didn't have any problems with that when we've created a buffer per uniform block, except it got a little slow when there were thousands of materials. But when we've decided to create a buffer per uniform block size (with account for UNIFORM_BUFFER_OFFSET_ALIGNMENT) there the problems were.

Mikhail Turkeev

unread,
Nov 28, 2023, 4:49:04 AM11/28/23
to WebGL Dev List
Forgot to say the most essential thing.

When we decreased the size of GPU buffers for UBOs the problem started to appear less often. And with sizes below MAX_UNIFORM_BLOCK_SIZE it seems to disappear completely (on the iPhone at least).

Ivan Popelyshev

unread,
Nov 29, 2023, 2:10:39 AM11/29/23
to WebGL Dev List
UBO is stored as a linear block of memory, that's where the limits come from.

вторник, 28 ноября 2023 г. в 12:49:04 UTC+3, turk...@gmail.com:

Mikhail Turkeev

unread,
Nov 29, 2023, 4:38:21 AM11/29/23
to WebGL Dev List
Well yes.

Still it is a question.
Is it the maximum size of the underlying buffer or the maximum size of the binding, which I assume is the same as the byte-size of an interface block defined in a shader?

I mean a buffer can store data for multiple bindings. (I don't know how do you call actual data for the interface block, so I'll call it binding in this case)
In our case the size of each binding do not exceed 500 bytes.
But the size of the buffer can easily be something like 1 or 2 megabytes.

If we look at webglreport on iPhone, depending on whether "WebGL via Metal" is enabled MAX_UNIFORM_BLOCK_SIZE can be IIRC 16 kilobytes or 64 kilobytes.

I am trying to understand, if I am misinterpreting the spec, or is there a relevant bug in iPhones implementation of WebGL, or do I have to look for a problem somewhere else in our code.

Reply all
Reply to author
Forward
0 new messages