Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update an uniform variable in several shader programs at once

I have several shaders with uniform variables, which have the same names in all shaders. What is the best way to update uniforms with same names in all shaders at once? I consider the following approaches:

1) Just store locations of that uniform for each program and update it just after the program is assigned as "used" program (glUseProgram).

Disadvantages: All "shared" uniform variables will be updated after each glUseProgram call. Moreover, if a program is being used not for the first time during the current frame, all glUniform* calls will be redundant. Alternatively there should be a set of flags which will tell if the program is used for the first time or not. "Unused" flags should be reset every frame.

2) Use uniform buffers and shared (or even std140) layout. In this approach we can set an uniform at once and then change shader programs without updating buffers. But what if there is a bunch of simple shaders, where the only shared variable is transformation matrix? Is it okay to use uniform buffers for such a small amount of memory? In some forum discussions I've read that

glBindBuffer(GL_UNIFORM_BUFFER,buf);
glBufferSubData(/*just 16 floats*/);
glBindBuffer(GL_UNIFORM_BUFFER,0);

is much slower than glUniform* call. Here we can notice, that the choice between first and second approach depends on the following conditions:

  • How often will the shaders change per frame and how often will they repeat?
  • How many "shared" uniforms are there?
  • What amount of data should be passed to shader program in each frame?

Is there any compromise design pattern which will have good performance regardless of answers for these three questions?

3) Use ubershader. Mentioned here in the second paragraph: GLSL multiple shaderprogram VS uniforms switches. I have two questions about it:

What has better performance: one glUseProgram call or several uniform switches, which will change ubershader's functionality?

Author of that question mentioned

Uniforms have to be changed many times per frame

as one of disadvantages of ubershader. But why is it bad? Does it have bad performance? If so, is it okay to pass transformation matrices and some other low-sized stuff as uniform variables and update them each frame?

And the main question to summarize all above: may you suggest any other techniques or design patterns for updating same-named uniform variables in several different shader programs?

UPD: the answer is accepted, nevertheless if you can suggest a nontrivial high-level design technique (in C++ or language-independent), plese leave it here.

like image 649
Sergey Avatar asked Jan 18 '13 16:01

Sergey


Video Answer


1 Answers

In some forum discussions I've read that [...] is much slower than glUniform* call.

So what if it is (assuming that there is evidence that it even is, of course)? You only do that once per frame, while glUniform calls are one per modified program.

I'd go with uniform blocks (always use std140 by default) for any shared data. There's a fixed cost to updating them, while there's a variable cost to updating the others.

like image 187
Nicol Bolas Avatar answered Nov 13 '22 10:11

Nicol Bolas