Repository navigation
Values for certain types of uniforms within UBOs are shown incorrectly #277
Description
Activity
Note
layout(std140)in the shader code - it should make the layout implementation independent, but if you want, you can try it yourself https://cib3.webgears.app/3D-Engine/228e665dc1d4cd9fd12ab71a4dbcf5abd64e26e3/shadows.html (look for draw calls with PBR_MESH_SHADER in shader names) The link is only going to be alive for a few days maximum.Though judging by the implementation of getUboValue it is expected that there are zeroes.
Spector.js/src/backend/states/drawCalls/drawCallUboInputState.ts
Lines 50 to 75 in 35385a5
public getUboValue(bindingPoint: number, offset: number, size: number, type: number): any { const uboType = DrawCallUboInputState.uboTypes[type]; if (!uboType) { return undefined; } const destination = new uboType.arrayBufferView(size * uboType.lengthMultiplier); const context2 = this.context as WebGL2RenderingContext; const ownerbuffer = context2.getIndexedParameter(WebGlConstants.UNIFORM_BUFFER_BINDING.value, bindingPoint); if (ownerbuffer) { const startOffset = context2.getIndexedParameter(WebGlConstants.UNIFORM_BUFFER_START.value, bindingPoint); const boundBuffer = context2.getParameter(WebGlConstants.UNIFORM_BUFFER_BINDING.value); try { context2.bindBuffer(WebGlConstants.UNIFORM_BUFFER.value, ownerbuffer); context2.getBufferSubData(WebGlConstants.UNIFORM_BUFFER.value, startOffset + offset, destination); } catch (e) { // Prevent back fromats to break the capture. return undefined; } if (boundBuffer) { context2.bindBuffer(WebGlConstants.UNIFORM_BUFFER.value, boundBuffer); } } return Array.prototype.slice.call(destination); In case of float x[3] the layout is the following:
[ 4 bytes x[0], 12 bytes to satisfy alignment, 4 bytes x[1], 12 bytes to satisfy alignment, 4 bytes x[2], 12 bytes padding, ]The implementation simply does getBufferSubdata and then seems to do nothing with it. Assuming uboType.lengthMultiplier is 1 and size is 3. It should indeed read the first float and two zero-paddings immediately following it.
According to the spec https://registry.khronos.org/OpenGL/extensions/ARB/ARB_uniform_buffer_object.txt column-major matrices are treated as arrays of columns regardless of the dimensions. And array elements are vec4-aligned. So mat4x2 is taking as much space as mat4.
Row-major matrices are the same except they should be treated as arrays of rows.
Although today I discovered that when on NVidia GPUs + Chrome row-major case does something else. As well as Android on Mali G68. So yeah. It seems that this stuff is still implementation-defined to some extent. Or maybe I am using the wrong spec :)
This is a really interesting one indeed :-)
@JannikGM, thanks a lot for your proposal here, this is going in the right direction and yes it was a complete oversight on my side.
I was using Spector.js Chrome extension to debug our migration to UBOs and stumbled upon this.
We have the following uniform block:
And spector shows the following for frustumSplits

The displayed value is
0.1683, 0, 0which is wrong. The last two values shouldn't be zeroes.I think Spector is ignoring arrayStride here, because when I put some numbers into the buffer one after another I can actually see them in Spector.