I'm using GLFW 3 and OpenGL 4 + GLSL 4 on a MacBook Pro.
I get the following syntax error, when starting my program:
ERROR: 0:5: 'varying' : syntax error syntax error
The shader code:
#version 410
varying vec3 vertex;
void main() {
}
Why am I not allowed to use varying variables?
Why am I not allowed to use varying variables?
Because they have been replaced by the more generic in/out variable concept since GLSL 1.30.
That became necessary because with GL3, the geometry shader was introduced, so a more generic communication method between shader stages was needed. Nowadays you just declare out variables in one shader stage and have the same declarations as in in the next shader stage you are using. The concept of varying is still the same - the outputs of the last shader stage (you use) before the rasterizer should match the inputs of the fragment shader (or the first shader stage after the rasterizer, but currently, there is no other), and the data will be interpolated across the primitive per default (if you don't declare it as flat, or use types which can't be interpolated).
Related
I'm doing a project using OpenCL and thought it can work on Mali 400 GPU. But I recently found that Mali 400 GPU only support OpenGL ES 2.0 standard.
I still have to use this GPU, So is there any way to let a shader act nearly the same as OpenCL kernel or CUDA kernel?
There are some main features I expect but not sure glsl will support:
For example, I created a global memory for GPU, and I want to read/write the global memory in shader, how should I pass the variable from host to vertex shader, can I expect that data be both 'in and out' like this?
layout (location = 0) inout vec3 a_Data;
I want to fetch a_Data as 64 float values, is there a easy way to declare it like vec64 or float[64], or I have to use multiple vec4 to assemble it?
So is there any way to let a vertex shader act nearly the same as OpenCL kernel or CUDA kernel?
No.
In ES 2.0, vertex shaders have no mechanism to write to memory. At all. All of their output variables go to the rasterizer to generate fragments to be processed by the fragment shader.
The only way to do GPGPU processing on such hardware is to use the fragment shader to write data. That means you have to manipulate your data to look like a rendering operation. Your vertex positions needs to set up your fragment shader to be able to write values to the appropriate places. And your fragment shader needs to be able to acquire whatever information it needs based on what the VS provides (which is at a per-vertex granularity and interpolated for each fragment).
One section of the OpenGL ES 3.0 spec is not completely clear to me.
https://www.khronos.org/registry/Ope...s_spec_3.0.pdf, page 185:
If an OpenGL ES Shading Language 1.00 fragment shader writes to
gl_FragColor or gl_FragData, DrawBuffers specifies the draw buffer, if
any, into which the single fragment color defined by gl_FragColor or
gl_FragData[0] is written. If an OpenGL ES Shading Language 3.00
fragment shader writes a user-defined varying out variable,
DrawBuffers specifies a set of draw buffers into which each of the
multiple output colors defined by these variables are separately
written.
I understand this the following way:
1) If I use OpenGL ES 3.0 and write shaders using GLSL 1.0, then the only way I can write to 2 buffers at once (COLOR0 and COLOR1) is to manually specify what gets written to gl_FragData[0] and gl_FragData[1] in my fragment shader. If I then want to get back to writing only to COLOR0, I must switch glPrograms to one that only writes to gl_FragData[0] (or gl_FragColor).
2) If on the other hand I use OpenGL ES 3.0 and write my shaders using GLSL 3.0, then I can write a single fragment shader with output defined to be a single varying out variable, and dynamically switch on and off writing to COLOR1 with calls to DrawBuffers() and with no need to swap glPrograms.
Is the above correct?
Is the above correct?
No. In ESSL 1.0 shaders you can only write to a single color buffer gl_FragData, or it's alias gl_FragData[0]. There is no such thing as gl_FragData[1] in ESSL 1.0.
and dynamically switch on and off writing to COLOR1 with calls to DrawBuffers() and with no need to swap glPrograms.
Yes, this is how it works in ESSL 3.x.
However, in most cases it's far more efficient just to swap programs. You execute the shader program millions of times (once per fragment), so having one program containing all of the code for all color targets and just masking out output writes is horribly inefficient. Don't do it. You want you shader programs to be as close to optimal as possible - that's where your GPU runtime goes ...
I've been tinkering with cg shaders for Retroarch, and I've encountered what appears to be a strange bug in the Cg Toolkit's compiler or code generator...or something. Consider the three-pass shader found here which simulates a CRT TV: https://github.com/libretro/common-shaders/tree/master/crt/crt-interlaced-halation
In particular, consider the final pass:
https://github.com/libretro/common-shaders/blob/master/crt/crt-interlaced-halation/crt-interlaced-halation-pass2.cg
As it stands, the shader output works as expected. If you comment out the "#define CURVATURE" at the top of this file (which simulates the curvature of a CRT TV), the shader output also works as expected. However, it's very particular to the member order of the vertex shader output struct here:
struct out_vertex {
float4 position : POSITION;
float4 color : COLOR;
float2 texCoord : TEXCOORD0;
float2 one;
float mod_factor;
float2 ilfac;
float3 stretch;
float2 sinangle;
float2 cosangle;
};
If you rearrange the order to the following, you will get corrupted output:
struct out_vertex {
float4 position : POSITION;
float4 color : COLOR;
float2 texCoord : TEXCOORD0;
float2 cosangle;
float2 one;
float mod_factor;
float2 ilfac;
float3 stretch;
float2 sinangle;
};
My desktop's nvidia card gives me a black screen with that order, and my laptop's ATI card gives me bizarre artifacts where the texture coordinates seem to be broken (perhaps). The exact nature of the error therefore depends on the GPU or drivers, but the presence of the error is vendor/driver-agnostic...so it appears to be a bug in the cg compiler that causes the varying attributes to become corrupt. There's pretty much no end to the kinds of corruption you can get. For instance, other member rearrangements screw up things like the "mod_factor" variable (storing the x pixel coordinate of the output), which causes the alternate magenta/green pixel tints to get stuck on one or the other, blanketing the entire image with the same tint. Still others cause a black screen except for halation/bloom contribution, etc.
The issue does not occur in this particular shader if you reenable "#define CURVATURE", but it doesn't have anything to do with errors in the "flat" codepath: In fact, in the part of the fragment shader within the "#ifdef CURVATURE" block, you can actually replace the final value with "xy = VAR.texCoord;" (the same value used by the uncurved version), and you'll get flat output without any errors. (EDIT: Oops, this isn't actually true with this particular shader, but it was in my own version. I should have checked that first before making the same assessment about this "simplified" example.) In reality, the fact that the flat codepath triggers the corruption but the curved codepath doesn't seems to indicate it has something to do with the curved codepath reading more of the varying attributes in the fragment shader (and maybe the read order or usage matters too...?), but I have not yet found a rhyme or reason to it. I have my own drastically different forked WIP where the same bizarre issues affect a curved codepath as well, but I'd rather keep it to myself until it's ready anyway.
So, I guess I have a few questions:
Has anyone else seen anything like this?
Is this nondeterminism simply expected with output struct members that aren't explicitly associated with any semantics?
Could this corruption be coming from cg shader profile limits I'm unaware of? I have no idea what shader profile Retroarch compiles for, but I can see this kind of corruption occurring if the size of the vertex output struct exceeds some maximum allowed size.
Are there any other possibilities I might be overlooking? I considered driver errors, but that went out the window once I realized it affected both nvidia and ATI hardware. Still, I want to do my homework before informing nvidia the Cg Toolkit seems to have a bug...
Thanks for any insights! :)
It turns out the problem has everything to do with relying on cg's auto-assigned semantics. I'll copy/paste my comment from above:
I'm starting to think the problem might have something to do with
relying on cg to auto-assign semantics: If for instance cg associates
a value with a full float range to a semantic that clamps to [0.0,
1.0], that would obviously cause issues. mod_factor, ilfac, and stretch would all fall into that category, and sinangle and cosangle
could be in [-1, 1], so the same probably applies to them. The
assignment of semantics is likely to be affected by dead code
elimination, which would explain the differences with and without
"#define CURVATURE." I'll have to test this hypothesis though...
There are only a limited number of semantics available depending on the profile (see this specification), and (I may be mistaken) Retroarch appears to use a lower profile, where only the following are available:
POSITION: must be set to the clipspace vertex position, not only because it informs the rasterizer, but also because it apparently can't even be read from the fragment shader.
COLOR0 and COLOR1: values are clamped to the [0, 1] range.
TEXCOORD0-7: safe for any scalar or vector float value
FOG: safe for any scalar float value
The BCOL0/BCOL1 semantics probably clamp too in profiles that support them, and PSIZE and CLP0-5 probably don't. The overall lesson seems to be that letting the cg compiler auto-assign semantics for values outside of the [0, 1] range is like playing Russian roulette, because you never know if they'll end up being associated with the clamped semantics or not, and the auto-assignment will change depending on the specifics of the shader code. For that reason, you need to carefully manage semantics so values potentially outside of [0, 1] get paired up with something like TEXCOORD0-7 or FOG (for a scalar float).
i want to get the const info( which also called uniform in ogl ) after shaders are compiled.
in d3d9, i can get ID3DXConstantTable by use D3DXGetShaderConstantTable interface, so i can get the const info of vertex shader or fragment shader.
but in ogl, there is no interface for shader but only the interface for program named glGetActiveUniform. used this interface can get all uniforms used by program, but can not know the uniform is used by vertex shader or used by fragment shader.
so is there any way?
I don't know for sure that it's not possible but I haven't seen a way to do this. I'll speculate that since uniforms can get optimized out at the linking stage, it makes sense that you can't (or rather, that the effort to include and implement an interface hasn't been made) query the individual shader and see what variables are "active".
As you say, you can get a list of active uniforms for the entire program:
glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &n)
for (i = 0..n)
glGetActiveUniform(program, i, ...)
But AFAIK there is no way to find which stage references them, and more to the point, which stages they are active in (for the former you could do some code parsing to guess).
The only thing that comes close is with uniform blocks, which aren't available in OpenGL ES2.0:
glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &n)
for (i = 0..n)
glGetActiveUniformBlockiv(program, i, ...)
Where you can query
GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER,
GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER,
GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER,
sorry if this is a duplicate I can't seem to find a solid answer.
If i use the same vertex shader in multiple programs is it safe to assume the getUniformLocation will stay the same?
example, if i use the following vertex shader in multiple programs (A,B,C,D):
uniform mat4 uMvp;
attribute vec3 aPosition;
void main() {
vec4 position = vec4(aPosition.xyz, 1.);
gl_Position = uMvp * position;
}
and at initialization I was to call
GLUint mvpLoc = getUniformLocation("uMvp");
while using program A, would i safely be able to switch to program B/C/D and carry on using mvploc? I am relatively new to GLES 2.0 and on the face of it this seems like bad practice but I assume there is overhead when calling getUniformLocation that would be good to avoid.
I have read about glBindAttribLocation so i could use that and instead have uMvp as a attribute but then I feel like i am missing a point as the common practice seems to be mvps as uniform variables.
No, each program program object will have separate uniform locations. There's no way to guarantee that two different programs use the same location for the same uniform.
Unless you have access to ARB_explicit_uniform_locations or GL 4.3 (which you don't, since you're using ES). This allows you to explicitly specify uniform locations in the shader.