PDA

View Full Version : UBO or 'normal' uniforms



aronsatie
02-03-2017, 06:17 AM
Hi,
I am planning to rewrite my rendering shaders (GLSL 1.2) for modern OpenGL and I was wondering if it would be worth using UBOs with as much data as possible (lights, materials, not just matrices) instead of old style uniforms? I am planning to use subroutines and would like to end up with a single rendering shader (if I can), so sharing uniforms between shaders would not be an issue. The question is if performance could improve if I do not have to update e.g. parameters of the current material just set an index into an array? With UBOs I can access a lot of data from the shader directly, so it would seem to be well worth using this feature even from a single shader.
But I read that performance can be actually worse with buffer objects if they are updated too frequently.

Thanks.

Dark Photon
02-03-2017, 06:18 PM
What you've read mirrors what I've seen. Normal uniform sets can be pretty efficient. UBOs less so, depending on usage. IIRC, recommendations are to update the UBOs once per frame and share them across many batch invocations. That helps amortize the cost.

If in doubt, I'd try both and see. It's probably going to depend on the specifics of your use case. That said, if you don't measure uniform set up to be a significant cost in your app, it might not be worth the trouble.

aronsatie
02-04-2017, 12:41 AM
My original thinking was that built-in parameters for materials and lights (in 'old' open gl) are uniforms and, together with a few other things, need to be set per object/draw call. The only way that I can get away with a once per frame update is if I keep all of these in arrays in UBOs and set only a few indices ('bind' the currently needed) as normal uniforms per object/draw call. I would probably end up with a few big UBOs and I suspect that updating only a few things at arbitrary locations in a UBO is a bad thing.

Silence
02-04-2017, 05:09 AM
My original thinking was that built-in parameters for materials and lights (in 'old' open gl) are uniforms and, together with a few other things, need to be set per object/draw call.

Up to GL 1.5 they were certainly not exactly this, since uniforms did not existed yet. However, these "variables" were kept on some stacks (see https://www.opengl.org/sdk/docs/man2/xhtml/glPushAttrib.xml for example).
On OpenGL 2.x, as far as I remember well, the fixed pipeline was simulated by shaders on most hardwares/drivers, so yes (but with a stack).
With compatibility profile on OpenGL >3.0, there's a lot of chances things remain emulated.

aronsatie
02-09-2017, 04:25 AM
Thanks for the tips. I think that parameters that change only per frame at the most, I will move to a uniform buffer. Most of these parameters were updated per draw call before, so the higher cost (UBO) vs more frequent use (normal uniform) will make it more efficient. I will try to use blocks that are not bigger than 16K, so far I came up with 10 such blocks. It seems that these numbers are within the limits so hopefully it will work well. Thanks again.