Visualisation shader compilation failure
MILeach opened this issue · 12 comments
Attempting to run a visualisation enabled build on Ubuntu 21.04 and dependencies installed via apt fails shader compilation at runtime with the error message
Shader compilation error (material_flat_Tcolor.frag) :
0:26(10): error: syntax error, unexpected '(', expecting ',' or ';'
It would be helpful if someone else could try running on a different system to see if this is a code issue or system configuration issue.
You should be able to find the shader in /tmp/fgpu2/vis
, it will just have a hash of the filename appended to the the name shown in the error. That might make it clearer what the syntax error is.
I'll try and reproduce this after I've had some dinner tonight.
I would also dig into dependencies, to check that both fgpu2lib and vis are on latest master. Always a chance somehow they've gone out of sync.
Also, your operating system shouldn't matter. Graphics driver is used for shader compilation, so main differences come from intel/nv/amd, though we should all be on nv given CUDA is required.
Built fresh master, and it worked fine, so as I said above, check that fgpu2/fgpu2_vis are both upto date. It's possible if you haven't done a hard configure, they won't have both updated. Although the only recent change to touch frag shader would be colours, so wouldn't expect a conflict as there shouldn't be any templating going on with the frag shaders.
This is the frag shader my build is using.
#version 430
const uint B_NONE = 1<<0;
const uint B_AMBIENT = 1<<1;
const uint B_DIFFUSE = 1<<2;
const uint B_SPECULAR = 1<<3;
const uint B_EMISSIVE = 1<<4;
const uint B_HEIGHT = 1<<5;
const uint B_NORMAL = 1<<6;
const uint B_SHININESS = 1<<7;
const uint B_OPACITY = 1<<8;
const uint B_DISPLACEMENT = 1<<9;
const uint B_LIGHT = 1<<10;
const uint B_REFLECTION = 1<<11;
const uint B_UNKNOWN = 1<<12;
struct MaterialProperties {
vec3 ambient; //Ambient color
float opacity;
vec3 diffuse; //Diffuse color
float shininess;
vec3 specular; //Specular color
float shininessStrength;
vec3 emissive; //Emissive color (light emitted)
float refractionIndex;
vec3 transparent; //Transparent color, multiplied with translucent light to construct final color
uint bitmask;
bool has(uint check) { return (bitmask&check)!=0;}
};
struct LightProperties {
vec3 ambient; // Aclarri
float spotExponent; // Srli
vec3 diffuse; // Dcli
float PADDING1; // Crli (ex spot cutoff, this value is nolonger set internally)
vec3 specular; // Scli
float spotCosCutoff; // Derived: cos(Crli) (Valid spotlight range: [1.0,0.0]), negative == pointlight, greater than 1.0 == directional light
vec3 position; // Ppli
float constantAttenuation; // K0
vec3 halfVector; // Derived: Hi (This is calculated as the vector half way between vector-light and vector-viewer)
float linearAttenuation; // K1
vec3 spotDirection; // Sdli
float quadraticAttenuation;// K2
};
const uint MAX_LIGHTS = 50;
const uint MAX_MATERIALS = 50;
uniform uint _materialID;
uniform _materials {
MaterialProperties material[MAX_MATERIALS];
};
uniform _lights {
uint lightsCount;
//<12 bytes of padding>
LightProperties light[MAX_LIGHTS];
};
uniform sampler2D t_ambient;
uniform sampler2D t_diffuse;
uniform sampler2D t_specular;
in vec3 eyeVertex;
in vec2 texCoords;
in vec4 colorOverride;
flat in int shaderColor;
out vec4 fragColor;
vec3 getAmbient() {
if (bool(shaderColor)) // _materialID >= MAX_MATERIALS
return colorOverride.rgb * 0.2f;
return material[_materialID].has(B_AMBIENT) ? texture(t_ambient, texCoords).rgb : material[_materialID].ambient;
}
vec4 getDiffuse() {
if (bool(shaderColor)) // _materialID >= MAX_MATERIALS
return colorOverride;
return material[_materialID].has(B_DIFFUSE) ? texture(t_diffuse, texCoords) : vec4(material[_materialID].diffuse, 1.0f);
}
vec3 getSpecular() {
if (bool(shaderColor)) // _materialID >= MAX_MATERIALS
return vec3(0.5f);
return material[_materialID].has(B_SPECULAR) ? texture(t_specular, texCoords).rgb : material[_materialID].specular;
}
void main() {
//Calculate face normal
vec3 eyeNormal = normalize(cross(dFdx(eyeVertex), dFdy(eyeVertex)));
//Find material colours for each type of light
vec3 ambient = getAmbient();
vec4 diffuse = getDiffuse();
vec3 specular = getSpecular();
float shininess = (bool(shaderColor)) ? 1.0f : material[_materialID].shininess;
float shininessStrength = (bool(shaderColor)) ? 0.0f : material[_materialID].shininessStrength; // Currently unused anyway
float opacity = (_materialID >= MAX_MATERIALS) ? 1.0f : material[_materialID].opacity;
//No lights, so render full bright
if(lightsCount>0) {
//Init colours to build light values in
vec3 lightAmbient = vec3(0);
vec3 lightDiffuse = vec3(0);
vec3 lightSpecular = vec3(0);
//Init general values used in light computation
for(uint i = 0;i<lightsCount;i++) {
float attenuation;
float intensity = 1.0f;
vec3 surfaceToLight;
//Init light specific values
if(light[i].spotCosCutoff>1.0f) { // Light is directional
attenuation = light[i].constantAttenuation;
surfaceToLight = -light[i].spotDirection;
} else {
surfaceToLight = normalize(light[i].position.xyz - eyeVertex);
if(light[i].spotCosCutoff>=0.0f) { // Spotlight
float spotCos = dot(surfaceToLight,-light[i].spotDirection);
//Step works as (spotCos>light[i].spotCosCutoff?0:1)
//Handle spotExponent
intensity = step(light[i].spotCosCutoff, spotCos) * pow(spotCos, light[i].spotExponent);
}
//Pointlight(or in range spotlight)
float dist2 = dot(surfaceToLight, surfaceToLight);
float dist = sqrt(dist2);
attenuation = (light[i].constantAttenuation)+(light[i].linearAttenuation*dist)+(light[i].quadraticAttenuation*dist2);
}
attenuation = clamp(intensity/attenuation,0.0f,1.0f);
{ // Process Ambient
lightAmbient += light[i].ambient * attenuation;
}
{ // Process Diffuse
float lambertian = max(dot(surfaceToLight,eyeNormal),0.0f);//phong
lightDiffuse += light[i].diffuse.rgb * lambertian * attenuation;
}
// Process Specular
if (shininess == 0 || shininessStrength == 0)
continue; // Skip if no shiny
{
vec3 reflectDir = reflect(-surfaceToLight, eyeNormal);
float specAngle = max(dot(reflectDir, normalize(-eyeVertex)), 0.0);
float spec = clamp(pow(specAngle, material[_materialID].shininess/4.0), 0.0f, 1.0f);
lightSpecular += light[i].specular * spec * attenuation;
}
}
// Export lights
ambient *= lightAmbient;
diffuse *= vec4(lightDiffuse, 1.0f);
specular *= lightSpecular;
} else {
//No lights, so render full bright pretending eye is the light source
vec3 surfaceToLight = normalize(-eyeVertex);
// Process Ambient
{// Ambient component: 0.2f
ambient *= 0.2f;
}
// Process Diffuse
{// Diffuse component: 0.85f
float lambertian = max(dot(surfaceToLight,eyeNormal),0.0f);//phong
diffuse *= vec4(vec3(lambertian * 0.85f), 1.0f);
}
// Process Specular
vec3 reflectDir = reflect(-surfaceToLight, eyeNormal);
float specAngle = max(dot(reflectDir, surfaceToLight), 0.0);
float shininess = 1.0f;
float spec = clamp(pow(specAngle, shininess), 0.0f, 1.0f);
specular *= 0.2f * spec;
}
vec3 color = clamp(ambient + diffuse.rgb + specular,0,1);
fragColor = vec4(color, min(diffuse.a, opacity)); // What to do with opac?
// Discard full alpha fragments (partially removes requirement of back to front render/glblend)
if(fragColor.a<=0.0f)
discard;
}
Vis runs fine for me locally on Ubuntu 20.04, GTX 1070, driver 465.19.01. Generated sharder in /tmp
matches the above.
Hmm generated shader is exactly the same for me. FGPU & the vis library should both be up to date, it was a fresh install with them pulled in via CMake - I'll check a bit later though. Driver Version: 460.73.01 which is slightly older, so I could see if I can update that too.
I think that would make this line 26, which it's complaining about though.
What model is the GPU? I suppose it's possible older GPUs have different GLSL support (although this shouldn't really affect shader compiler).
bool has(uint check) { return (bitmask&check)!=0;}
If you're on a laptop, and for whatever reason Linux is failing to automatically trigger Optimus due to CUDA. You could perhaps add this to a file and see if it fixes it. I've previously used this to force enable Optimus on non-cuda sdl_exp projects on my laptop, so it works on Windows. Though _declspec
is MSVC specific, so not sure what Linux equivalent would be.
extern "C" {
_declspec(dllexport) unsigned long NvOptimusEnablement = 0x00000001;
}
Possible gcc alt
extern "C" {
__attribute__ ((dllexport)) unsigned long NvOptimusEnablement = 0x00000001;
}
What model is the GPU?
RTX 2060
although this shouldn't really affect shader compiler
I agree with this. I'll have a play around later and see if I can find a workaround.
I think this was resolved, as it trying to use iGPU.
Hi,
I'm having the same issue after the update of the system (I'm using Fedora 40).
Before the update it worked fine
The error is the same:
Shader compilation error (material_flat_Tcolor.frag) :
0:26(10): error: syntax error, unexpected '(', expecting ',' or ';'
I'm not able to solve it. How can I do?
Thanks
I think based on your error the shader compiler isn't happy with this line of code.
It's not clear to me how that could be resolved though, the syntax looks right.
The shader compiler is provided by the graphics driver, and I know NVIDIAs shader compiler to have some of the least strict syntax checking. It's possible your graphics driver's shader compiler doesn't support structs having member functions (e.g. if it's an Open Source NV graphics driver).
If that is the case, the solution would be to move the implementation of has()
to a standalone function that is instead passed the struct, and update the 3 associated calls.
This is rather speculative though.
FLAMEGPU extracts shaders to the temporary directory, and preferentially loads them from there if they already exist. So you will want to play around modifying the shader as it exists in that directory to test any fixes.
It worked! Thank you very much
Here you find the modified file:
#version 430
const uint B_NONE = 1<<0;
const uint B_AMBIENT = 1<<1;
const uint B_DIFFUSE = 1<<2;
const uint B_SPECULAR = 1<<3;
const uint B_EMISSIVE = 1<<4;
const uint B_HEIGHT = 1<<5;
const uint B_NORMAL = 1<<6;
const uint B_SHININESS = 1<<7;
const uint B_OPACITY = 1<<8;
const uint B_DISPLACEMENT = 1<<9;
const uint B_LIGHT = 1<<10;
const uint B_REFLECTION = 1<<11;
const uint B_UNKNOWN = 1<<12;
bool has(uint check, uint bitmask) { return (bitmask&check)!=0;}
struct MaterialProperties {
vec3 ambient; //Ambient color
float opacity;
vec3 diffuse; //Diffuse color
float shininess;
vec3 specular; //Specular color
float shininessStrength;
vec3 emissive; //Emissive color (light emitted)
float refractionIndex;
vec3 transparent; //Transparent color, multiplied with translucent light to construct final color
uint bitmask;
};
struct LightProperties {
vec3 ambient; // Aclarri
float spotExponent; // Srli
vec3 diffuse; // Dcli
float PADDING1; // Crli (ex spot cutoff, this value is nolonger set internally)
vec3 specular; // Scli
float spotCosCutoff; // Derived: cos(Crli) (Valid spotlight range: [1.0,0.0]), negative == pointlight, greater than 1.0 == directional light
vec3 position; // Ppli
float constantAttenuation; // K0
vec3 halfVector; // Derived: Hi (This is calculated as the vector half way between vector-light and vector-viewer)
float linearAttenuation; // K1
vec3 spotDirection; // Sdli
float quadraticAttenuation;// K2
};
const uint MAX_LIGHTS = 50;
const uint MAX_MATERIALS = 50;
uniform uint _materialID;
uniform _materials {
MaterialProperties material[MAX_MATERIALS];
};
uniform _lights {
uint lightsCount;
//<12 bytes of padding>
LightProperties light[MAX_LIGHTS];
};
uniform sampler2D t_ambient;
uniform sampler2D t_diffuse;
uniform sampler2D t_specular;
in vec3 eyeVertex;
in vec2 texCoords;
in vec4 colorOverride;
flat in int shaderColor;
out vec4 fragColor;
vec3 getAmbient() {
if (bool(shaderColor)) // _materialID >= MAX_MATERIALS
return colorOverride.rgb * 0.2f;
return has(B_AMBIENT, material[_materialID].bitmask) ? texture(t_ambient, texCoords).rgb : material[_materialID].ambient;
}
vec4 getDiffuse() {
if (bool(shaderColor)) // _materialID >= MAX_MATERIALS
return colorOverride;
return has(B_DIFFUSE, material[_materialID].bitmask) ? texture(t_diffuse, texCoords) : vec4(material[_materialID].diffuse, 1.0f);
}
vec3 getSpecular() {
if (bool(shaderColor)) // _materialID >= MAX_MATERIALS
return vec3(0.5f);
return has(B_SPECULAR, material[_materialID].bitmask) ? texture(t_specular, texCoords).rgb : material[_materialID].specular;
}
void main() {
//Calculate face normal
vec3 eyeNormal = normalize(cross(dFdx(eyeVertex), dFdy(eyeVertex)));
//Find material colours for each type of light
vec3 ambient = getAmbient();
vec4 diffuse = getDiffuse();
vec3 specular = getSpecular();
float shininess = (bool(shaderColor)) ? 1.0f : material[_materialID].shininess;
float shininessStrength = (bool(shaderColor)) ? 0.0f : material[_materialID].shininessStrength; // Currently unused anyway
float opacity = (_materialID >= MAX_MATERIALS) ? 1.0f : material[_materialID].opacity;
//No lights, so render full bright
if(lightsCount>0) {
//Init colours to build light values in
vec3 lightAmbient = vec3(0);
vec3 lightDiffuse = vec3(0);
vec3 lightSpecular = vec3(0);
//Init general values used in light computation
for(uint i = 0;i<lightsCount;i++) {
float attenuation;
float intensity = 1.0f;
vec3 surfaceToLight;
//Init light specific values
if(light[i].spotCosCutoff>1.0f) { // Light is directional
attenuation = light[i].constantAttenuation;
surfaceToLight = -light[i].spotDirection;
} else {
surfaceToLight = normalize(light[i].position.xyz - eyeVertex);
if(light[i].spotCosCutoff>=0.0f) { // Spotlight
float spotCos = dot(surfaceToLight,-light[i].spotDirection);
//Step works as (spotCos>light[i].spotCosCutoff?0:1)
//Handle spotExponent
intensity = step(light[i].spotCosCutoff, spotCos) * pow(spotCos, light[i].spotExponent);
}
//Pointlight(or in range spotlight)
float dist2 = dot(surfaceToLight, surfaceToLight);
float dist = sqrt(dist2);
attenuation = (light[i].constantAttenuation)+(light[i].linearAttenuation*dist)+(light[i].quadraticAttenuation*dist2);
}
attenuation = clamp(intensity/attenuation,0.0f,1.0f);
{ // Process Ambient
lightAmbient += light[i].ambient * attenuation;
}
{ // Process Diffuse
float lambertian = max(dot(surfaceToLight,eyeNormal),0.0f);//phong
lightDiffuse += light[i].diffuse.rgb * lambertian * attenuation;
}
// Process Specular
if (shininess == 0 || shininessStrength == 0)
continue; // Skip if no shiny
{
vec3 reflectDir = reflect(-surfaceToLight, eyeNormal);
float specAngle = max(dot(reflectDir, normalize(-eyeVertex)), 0.0);
float spec = clamp(pow(specAngle, material[_materialID].shininess/4.0), 0.0f, 1.0f);
lightSpecular += light[i].specular * spec * attenuation;
}
}
// Export lights
ambient *= lightAmbient;
diffuse *= vec4(lightDiffuse, 1.0f);
specular *= lightSpecular;
} else {
//No lights, so render full bright pretending eye is the light source
vec3 surfaceToLight = normalize(-eyeVertex);
// Process Ambient
{// Ambient component: 0.2f
ambient *= 0.2f;
}
// Process Diffuse
{// Diffuse component: 0.85f
float lambertian = max(dot(surfaceToLight,eyeNormal),0.0f);//phong
diffuse *= vec4(vec3(lambertian * 0.85f), 1.0f);
}
// Process Specular
vec3 reflectDir = reflect(-surfaceToLight, eyeNormal);
float specAngle = max(dot(reflectDir, surfaceToLight), 0.0);
float shininess = 1.0f;
float spec = clamp(pow(specAngle, shininess), 0.0f, 1.0f);
specular *= 0.2f * spec;
}
vec3 color = clamp(ambient + diffuse.rgb + specular,0,1);
fragColor = vec4(color, min(diffuse.a, opacity)); // What to do with opac?
// Discard full alpha fragments (partially removes requirement of back to front render/glblend)
if(fragColor.a<=0.0f)
discard;
}
Thanks, I expect this will work with other drivers too. I'll try and remember to create a PR when I have a spare hour to test it.