QOpenGLShader - version directive must be first statement and may not be repeated - c++

I'am building an OpenGL-application using Qt 5.11.2. When adding a tessellation shader the following error occurs:
QOpenGLShader::compile(Tessellation Control): 0(2) : error C0204: version directive must be first statement and may not be repeated
*** Problematic Tessellation Control shader source code ***
#define lowp
#define mediump
#define highp
#line 1
´╗┐#version 400
#line 1
layout (vertices = 4) out;
I'm working on Windows 10 with Geforce GTX 1050/PCIe/SSE2 GPU.
I've found similar reports, but none of the answers worked for me: unable to compile GLSL shaders on Qt 5.3 after Nvidia driver update
Serious rendering issues with OpenGL 4.1 and Qt 5
The shader looks like this:
#version 400
layout (vertices = 4) out;
uniform float animationFrame;
in vec3 v_vertex[];
out vec3 tc_vertex[];
void main()
{...}
To add the shader I use the following code:
addShader(QOpenGLShader::Vertex, "data/cube.vert", *m_program);
addShader(QOpenGLShader::Fragment, "data/cube.frag", *m_program);
addShader(QOpenGLShader::TessellationControl, "data/cube.tcs", *m_program);
addShader(QOpenGLShader::TessellationEvaluation, "data/cube.tes", *m_program);
addShader(QOpenGLShader::Geometry, "data/cube.geom", *m_program);
Obviously the first lines inserted by Qt produce the error. Any ideas how to fix this problem?

I have the same problem, my errors shows like this:
QOpenGLShader::compile(Fragment): 0(2) : error C0204: version directive must be first statement and may not be repeated
*** Problematic Fragment shader source code ***
#ifdef GL_KHR_blend_equation_advanced
#extension GL_ARB_fragment_coord_conventions : enable
#extension GL_KHR_blend_equation_advanced : enable
#endif
#define lowp
#define mediump
#define highp
#line 1
???#version 330 core
out vec4 FragColor;
void main(void)
{
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
***
as you can see, there are ??? in the messages, while you have ´╗┐
when I changed from "utf-8 with BOM" to "utf-8", it works~

I have the error like this:
???#version 330 core
I use visual code to change the file encoding from "utf-8 with BOM" to "utf-8". Then it works.

I guess the answer is "version directive must be first statement and may not be repeated"
So, put your version directive to the first line - before all defines and the same.
Just checked it - that is it.
When I put directive "#version 330 core" in the fourth line of code - the same error "version directive must be first statement and may not be repeated" occured;
So the right way is to put this directive to the first line as it should be:
1 #version 330 core
2 in highp vec3 vert;
3 in highp vec3 vertNormal;
Where 1,2,3 - line's numbers.

Related

when do i need GL_EXT_nonuniform_qualifier?

I want to compile the following code into SPIR-V
#version 450 core
#define BATCH_ID (PushConstants.Indices.x >> 16)
#define MATERIAL_ID (PushConstants.Indices.x & 0xFFFF)
layout (push_constant) uniform constants {
ivec2 Indices;
} PushConstants;
layout (constant_id = 1) const int MATERIAL_SIZE = 32;
in Vertex_Fragment {
layout(location = 0) vec4 VertexColor;
layout(location = 1) vec2 TexCoord;
} inData;
struct ParameterFrequence_3 {
int ColorMap;
};
layout (set = 3, binding = 0, std140) uniform ParameterFrequence_3 {
ParameterFrequence_3[MATERIAL_SIZE] data;
} Frequence_3;
layout (location = 0) out vec4 out_Color;
layout (set = 2, binding = 0) uniform sampler2D[] Sampler2DResources;
void main(void) {
vec4 color = vec4(1.0);
color *= texture(Sampler2DResources[Frequence_3.data[MATERIAL_ID].ColorMap], inData.TexCoord);
color *= inData.VertexColor;
out_Color = color;
}
(The code is generated by a program I am developing which is why the code might look a little strange, but it should make the problem clear)
When trying to do so, I am told
error: 'variable index' : required extension not requested: GL_EXT_nonuniform_qualifier
(for the third last line where the texture lookup also happens)
After I followed a lot of discussion around how dynamically uniform is specified and that the shading language spec basically says the scope is specified by the API while neither OpenGL nor Vulkan really do so (maybe that changed), I am confused why i get that error.
Initially I wanted to use instanced vertex attributes for the indices, those however are not dynamically uniform which is what I thought the PushConstants would be.
So when PushConstants are constant during the draw call (which is the max scope for dynamically uniform requirement), how can the above shader end up in any dynamically non-uniform state?
Edit: Does it have to do with the fact that the buffer backing the storage for the "ColorMap" could be aliased by another buffer via which the content might be modified during the invocation? Or is there a way to tell the compiler this is a "restricted" storage so it knows it is constant?
Thanks
It is 3 am in the morning over here, I should just go to sleep.
Chances anyone end up having the same problem are small, but I'd still rather answer it myself than delete it:
I simply had to add a SpecializationConstant to set the size of the sampler2D array, now it works without requiring any extension.
Good night

What is the syntax for 'pixel_interlock_ordered' in GLSL?

I'm trying out the ARB_fragment_shader_interlock extension in OpenGL 4.5 and am failing to get the shader to compile when trying to use pixel_interlock_ordered.
#version 430
#extension GL_ARB_shading_language_420pack : require
#extension GL_ARB_shader_image_load_store : require
#extension GL_ARB_fragment_shader_interlock : require
layout(location = 0, rg8, pixel_interlock_ordered) uniform image2D image1;
void main()
{
beginInvocationInterlockARB();
ivec2 coords = ivec2(gl_FragCoord.xy);
vec4 pixel = imageLoad(image1, coords);
pixel.g = pixel.g + 0.01;
if (pixel.g > 0.5)
pixel.r = pixel.r + 0.01;
else
pixel.r = pixel.r + 0.02;
imageStore(image1, coords, pixel);
endInvocationInterlockARB();
}
The following shader fails compilation with:
0(6) : error C7600: no value specified for layout qualifier 'pixel_interlock_ordered'
Which is the same error you would get for any random name instead of pixel_interlock_ordered. I guess the syntax is different somehow, but the spec (https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_fragment_shader_interlock.txt) refer to it as a "layout qualifier".
Googling "pixel_interlock_ordered" comes up short with just links to the official specs, so I can't find an example. What is the correct syntax?
Layout qualifiers in GLSL are a bit weird. They usually apply to declarations, but some of them effectively apply to the shader as a whole. Such qualifiers are basically shader-specific options you set from within the shader.
The interlock qualifiers are those kinds of qualifiers. You're not saying that this variable will be accessed via interlocking, because that's not what interlocking means. It means that the execution of the interlock-bound code will have a certain property, relative to executing interlock-bound code on other invocations of the same shader. The qualifier specifies the details of the execution restriction.
Qualifiers that apply to the shader as a whole are grammatically specified as qualifiers on in or out (most such qualifiers use in, but a few use out):
layout(pixel_interlock_ordered) in;

Uniform registers requirement on Nvidia with a sampler in vertex shader

The issue I'm going to write about can only be reproduced with some hardware and drivers.
I managed to reproduce it on GeForce GTX 760 with 399.24 driver and GeForce 950M with 416.34. The issue does not show up on GTX650 with 390.87 driver. All these GPUs return 1024 for GL_MAX_VERTEX_UNIFORM_VECTORS, so I hardcoded 1000 as vec4 array size in vertex shader.
I try to compile and link the following shader program.
Vertex shader:
#version 330
uniform vec4 vs[1000];
uniform sampler2D tex;
void main()
{
gl_Position = vs[42];
//gl_Position += texture(tex, vs[0].xy); // (1)
}
Fragment shader:
#version 330
out vec4 outFragColor;
void main()
{
outFragColor = vec4(0.0);
}
Everything is OK while line (1) is commented and thus tex sampler is optimized out. But if we uncomment it, link fails with the following log:
-----------
Internal error: assembly compile error for vertex shader at offset 427:
-- error message --
line 16, column 9: error: invalid parameter array size
line 20, column 16: error: out of bounds array access
line 22, column 30: error: out of bounds array access
-- internal assembly text --
!!NVvp5.0
OPTION NV_internal;
OPTION NV_gpu_program_fp64;
OPTION NV_bindless_texture;
Error: could not link.
# cgc version 3.4.0001, build date Oct 10 2018
# command line args:
#vendor NVIDIA Corporation
#version 3.4.0.1 COP Build Date Oct 10 2018
#profile gp5vp
#program main
#semantic vs
#semantic tex
#var float4 gl_Position : $vout.POSITION : HPOS : -1 : 1
#var float4 vs[0] : : c[0], 1000 : -1 : 1
#var ulong tex : : c[1000] : -1 : 1
PARAM c[2002] = { program.local[0..2001] };
TEMP R0;
LONG TEMP D0;
TEMP T;
PK64.U D0.x, c[1000];
TEX.F R0, c[0], handle(D0.x), 2D;
ADD.F result.position, R0, c[42];
END
# 3 instructions, 1 R-regs, 1 D-regs
Here we see that the array takes registers 0..999, and the sampler takes register 1000. Elements above 1000 are not referenced anywhere except line PARAM c[2002] = { program.local[0..2001] };.
Further experiments with array size showed that 2002 is not a constant, but a doubled amount of registers required.
I remember that
OpenGL implementations are allowed to reject shaders for
implementation-dependent reasons.
So is there a workaround to use all available registers along with a sampler in a vertex shader?
If not, what might be the rationale behind this behavior? Obviously, this shader does not use any registers for temporary computation results.
Is it a misoptimization in shader compiler?
UPD: a quick-n-diry reproduction example is here.
UPD2: Webgl repro with workaround description.

Fragment Shader IN variable causes nothing to appear

I'm trying to send a variable from my vertex shader to my fragment shader, but when I include a specific the in variable in an if statement, it causes nothing to show up. Removing the if statement causes everything to appear and work normally. What's weird is that if statement isn't actually doing anything and that no errors are being generated by the fragment shader.
I have several other variables I'm sending from my vertex shader to my fragment shader but this one specifically is the only one causing issues. I know type is being set correct because I'm using it for something else that's working correctly.
vertex shader
#version 150
in float type;
out int roofBool;
void main(void)
{
textureXY = texcoords;
roofBool = 0;
if(type == 2){
roofBool = 1;
}
}
fragment shader
#version 150
in int roofBool;
// The output. Always a color
out vec4 fragColor;
void main()
{
int a = 0;
if(roofBool == 1){ //removing this causes everything to work
a = 2;
}
}
int variables cannot be interpolated by the GL. You must declare both the output and the corresponding input with the flat qualifier`.
From the behavior you described, it seems like you are not properly checking the compile and link status of your shaders/programs, and don't seem to retrieve the compiler/linker info log. You would vert likely have gotten a useful error message if you did.

Use GLSL-Unit to compile fragment shader

I want to use GLSL-Unit to just minify a fragment shader. But if I do run this command:
sunbox$ glsl-compiler --input=/Users/sunbox/Sites/bessa-app/xyz.fshader
I'm getting these error messages:
/usr/local/bin/glsl-compiler: line 1: syntax error near unexpected token `b'
/usr/local/bin/glsl-compiler: line 1: `var COMPILED=true,goog=goog||{};goog.global=this;goog.DEBUG=true;goog.LOCALE="en";goog.provide=function(b){if(!COMPILED){if(goog.isProvided_(b))throw Error('Namespace "'+b+'" already declared.');delete goog.implicitNamespaces_[b];for(var f=b;f=f.substring(0,f.lastIndexOf("."));){if(goog.getObjectByName(f))break;goog.implicitNamespaces_[f]=true}}goog.exportPath_(b)};'
So, how do I simply minify a fragment shader?
I finally got it working. :D
For everyone who's interested, you need this file:
http://code.google.com/p/glsl-unit/source/browse/bin/template_glsl_compiler.js
... and NodeJS installed. Then add a simple comment in your shader file:
//! FRAGMENT
precision lowp float;
uniform sampler2D image;
varying vec2 src_position;
void main() {
gl_FragColor = texture2D(image, src_position);
}
... and annoyingly you have to use the .glsl file extension! :(
Now you can run this command:
sunbox$ node /Volumes/template_glsl_compiler.js --input=/Volumes/test.glsl --variable_renaming=INTERNAL --output=/Volumes/test.fshader.min
And that's it. Compiled output will be:
//! VERTEX
//! FRAGMENT
precision lowp float;uniform sampler2D image;varying vec2 a;void main(){gl_FragColor=texture2D(image,a);}
Really nice! :)