works fine in my setup but want to be sure.
using glsl 430 and I have this in my geometry shader
#version 430
layout (points) in;
layout (triangle_strip) out;
layout (max_vertices = 24) out;
uniform mat4 u_projMatrix;
uniform mat4 u_viewMatrix;
mat4 viewProjection = u_projMatrix * u_viewMatrix;
void someFunction1(){
// uses viewProjection
}
void someFunction2(){
// uses viewProjection
}
void main()
{
// uses viewProjection
}
my concern is with viewProjection , I expect viewProjection to be initialized before main(). I went through the glsl manual and looks like it will do exactly that and should compile fine.If it is not valid code can someone please refer me to the section in the spec, thanks
Yes, this code is technically fine. The specification allows you to use arbitrary expressions to initialize global variables, even ones which use uniforms and the like. Essentially, they will execute before main starts.
But you shouldn't actually use this.
First, this sort of thing is very uncommon in shader code. As such, OpenGL implementations are less likely to be properly tested against it. Which means that there is a greater chance of the implementation getting this code wrong in some way. It's much safer to just write the code in main.
Second, you're hiding the cost of your shader. If your initializations are not constant expressions, then they will actually cost execution time. But you won't see it in main nor in any function main calls. It will exist outside of what you normally think of as "code". But it will still cost performance.
Related
For some reason cannot find the answer on the web. I want to update vertex attributes in GPU through the shader in similar form:
#version 330 core
layout(location = 0) in vec4 position;
uniform mat4 someTransformation;
void main()
{
position = position * someTransformation;
gl_Position = position;
}
Is it possible?
Can you write the code you have written? Yes, that is legal code.
Will that change the contents of any GPU storage? No.
While there are ways for a VS to directly manipulate the contents of a buffer, if the buffer region being manipulated is also potentially being used as an attribute array for a rendering command, then you will have undefined behavior.
You can use SSBOs to manipulate other storage which is not being used as the input for rendering. And you can use transform feedback to accumulate data output from vertex processing. But you cannot have a VS directly modify its own input array.
I was wondering if I can index into a uniform buffer array with a value contained in the vertices I draw, like:
layout (location = 0) in vec3 position;
layout (location = 1) in flat int idx;
layout(binding = 0, std140) uniform uniformValues
{
float values[100];
};
void main()
{
values[idx];
}
My understanding is that this is not possible because
'in flat int idx'
Is most likely not a 'dynamically uniform expression', and according to the documentation cannot be used to index into a uniform buffer array:
There are places where GLSL requires the expression to be dynamically
uniform. All of the following must use a dynamically uniform
expression:
-The index to buffer-backed interface block arrays.
However I came across information from the same source regarding how to access an array of samplers holding texture handles for 'bindless textures', and it says (emphasis mine):
Sampler and image types used in default block uniform variables can be
populated from handles rather than the index of a binding point.
These types can also now be passed as Shader Stage inputs/outputs (using the flat interpolation qualifier where needed). They can be
used as Vertex Attributes, where they are treated as 64-bit integers
on the OpenGL side. And they can be used in Interface Blocks of all
kinds; buffer-backed interface blocks treat them as 64-bit integers.
It's saying, I believe, that instead of doing this:
layout (location = 0) in flat int textureBinding;
layout (binding = 0) uniform sampler2D textures[16];
void main()
{
textures[textureBinding];
}
You do this:
layout (location = 0) in flat int bindlessTextureHandle;
layout (binding = 0) uniform textureBuffer
{
sampler2D textures[200];
}
void main()
{
textures[bindlessTextureHandle];
}
'bindlessTextureHandle' isn't a 'dynamically uniform expression', how can it be used to index into uniform buffer?
All of the following must use a dynamically uniformexpression:
-The index to buffer-backed interface block arrays.
So why is it saying that you can index into 'interface blocks' of all kinds with values from vertex inputs?
Also are you allowed to index into:
'uniform sampler2D[16] textures;'
with a 'non-dynamically uniform expression'?
My understanding is that this is not possible because
in flat int idx
Is most likely not a 'dynamically uniform expression', and according
to the documentation cannot be used to index into a uniform buffer
array.
You are right that you need a dynamically uniform value to index into an uniform buffer array. However, this:
layout(binding = 0, std140) uniform uniformValues
{
float values[100];
};
is not a uniform buffer array. That is an array inside a single uniform buffer object, and you can index with non-uniform values into this array as you like. A uniform buffer array would be:
layout(binding = 0, std140) uniform myUBO
{
float value;
} myUBOArray[4];
The rest of your question gets even more obscure. You sometimes reference "The index to buffer-backed interface block arrays", which your code never uses. This is talking about SSBOs, which use interface blocks of the form layout(...) buffer foo {...}.
So why is it saying that you can index into 'interface blocks' of all kinds with values from vertex inputs?
Because that is how it is. You just need to understand that indexing into an array of interface blocks is not the same as indexing some other array (which might or might not be defined inside an interface block, doesn't matter).
Also are you allowed to index into:
uniform sampler2D[16] textures; with a 'non-dynamically uniform expression'?
No, not in standard GL.
The first thing about bindless textures is that this is not a core feature of any OpenGL version released to date (which is 4.6 at the time of writing this).It is only defined as an extension GL_ARB_bindless_textures which some modern GPUs and drivers expose, but the availability of that feature is quite far from being universal.
Second, the extension spec above explains: "Sampler and image handles passed to texture built-in functions must be dynamically uniform", so it still doesn't get you there. However, the extension GL_NV_gpu_shader5 removes that restriction. So on recent NVIDIA GPUs, you can get a non-dymically uniform index into an array of bindless texture samplers - but performance will still suffer by a significant amount if you do so.
There are a myriad of separate, overlapping issues here.
Indexing an array within a uniform block has never been limited to dynamically uniform expressions (generally, see below). Even in GL 3.x, you can index an array within a buffer-backed block with an arbitrary index.
However, you're not asking about a general array; you're asking about arrays of textures. Or to be more general, the entire sequence of operations leading to the computation of a sampler type through bindless textures.
That entire sequence must be dynamically uniform (unless you're on NVIDIA, which allows arbitrary expressions). It doesn't matter if you're indexing an SSBO array, using an input variable to pass a texture handle directly, or anything else. The value that leads to the acquisition of a sampler type must be dynamically uniform.
So why is it saying that you can index into 'interface blocks' of all kinds with values from vertex inputs?
Because you can.
A common misunderstanding of what "dynamically uniform" means is that it is a static property. That an expression by itself is either dynamically uniform or not. This is close to true, but it's not actually true.
Some expressions are dynamically uniform by their nature. You could call these "statically dynamically uniform" expressions. A constant expression is always dynamically uniform, for example.
However, being dynamically uniform is about the value of the expression. All invocations (within the rendering command) must result in the same value. An in variable for a shader stage can be dynamically uniform so long as it just so happens to always have the same value within the rendering command. For example, a VS could access a value from a uniform array using gl_DrawID (which is dynamically uniform), pass that as an in to the FS, and the FS can use that value as a sampler. Or to access an array of samplers. Or whatever. All FS invocations will get the same value within the draw command, so that value is dynamically uniform.
If in a vertex shader there is:
#version 450 core
uniform bool v1;
void main()
{
if(v1 == true)
{
//do something
}
}
Since Uniform variables are constant throughout the shader run, how many times will the if be evaluated per frame? One? Or one per vertex (since we are in the vs)?
Either it will be evaluated once per vertex, or the system will recompile the shader every time you change that uniform (or maybe just have 2 forms of the shader). You should prefer the former to the latter.
I have problem with if here, for reasons uknown to me, it dosnt work.
When i delete if statment or malualy write shadowMap[0] 1 or 2 it works fine, but with if i just get set of white triangles and squares.
here is part of my frag shader
float shadow(float bias)
{
float visibility = 0;
int index=1;
if(gl_FragCoord.z<1.0){
index=0;
}
vec4 shadowCoord=depthPV*vPos;
if ( texture(shadowMap[index], shadowCoord.xy).z < shadowCoord.z+bias){
visibility = -1;
}
return visibility;
}
Other problem i have is with loading array of mat4 into uniform here is code i tried, but it dosnt work, i use lwjgl 3 libery in java
shadowPVs=GL20.glGetUniformLocation(pId, "shadowPVs");
ByteBuffer shadowPVbuff=BufferUtils.createByteBuffer(shadePV.length*16*4);
for(int i=0;i<shadePV.length;i++){
for(int v=0;v<16;v++){
shadowPVbuff.putFloat(shadePV[i].val[v]);
}
}
shadowPVbuff.flip();
GL20.glUniformMatrix4f(shadowPVs, shadePV.length, false, shadowPVbuff);
and in shader
uniform mat4 shadowPVs[3];
What you are trying to do is not possible with current GL.
As #gemse already pointed out in the comments, the relevant part of the GLSL 3.30 spec is:
Samplers aggregated into arrays within a shader (using square brackets
[ ]) can only be indexed with integral constant expressions (see
section 4.3.3 “Constant Expressions”).
In GL 4, this constraint has been somehwat relaxed, but not far enough. In the most current GLSL 4.50 spec, the statement is:
When aggregated into arrays within a shader, samplers can only be
indexed with a dynamically uniform integral expression, otherwise
results are undefined.
With dynamically uniform being defined as
A fragment-shader expression is dynamically uniform if all fragments
evaluating it get the same resulting value. When loops are involved,
this refers to the expression's value for the same loop iteration.
When functions are involved, this refers to calls from the same call
point. This is similarly defined for other shader stages, based on the
per-instance data they process. Note that constant expressions are
trivially dynamically uniform. It follows that typical loop counters
based on these are also dynamically uniform.
Your index depends on data which can vary per fragment, so you are getting undefined results.
Does the order and/or size of shader in/out variables make any difference in memory use or performance? For example, are these:
// vert example:
out vec4 colorRadius;
// tess control example:
out vec4 colorRadius[];
// frag example:
in smooth vec4 colorRadius;
equivalent to these:
// vert example:
out vec3 color;
out float radius;
// tess control example:
out vec3 color[];
out float radius[];
// frag example:
in smooth vec3 color;
in smooth float radius;
Is there any additional cost with the second form or will the compiler pack them together in memory and treat them exactly the same?
The compiler could pack these things together. But it doesn't have to, and there's little evidence that compilers commonly do this. So the top version will at least be no slower than the bottom version.
At the same time, this is more of a micro-optimization. So unless you know that this is a bottleneck, just let it go. It's best to write clear, easily understood code and optimize it when you know where your problems are, than to optimize it not knowing if it's going to be a concern.