Please excuse the quality of my shader code, I'm just experimenting and cobbling stuff together, and came upon this issue that, aside from being annoying to debug, completely blindsided me.
It's fixed now, but I'd like to know why it happened and honestly, unlike lots of other issues I've dealt with while learning, I don't even know where to start looking.
void main(){ vec3 ambientSum = vec3(0); vec3 diffuseSum = vec3(0); vec3 specSum = vec3(0); vec3 ambient, diffuse, spec; // (A) - doesn't work when declared/set here <---------------------------------------- // Material thisMaterialsource = materialBanks[0].bank.materials[materialId]; if (gl_FrontFacing) { for (int i=0; i<light.activeLights; ++i) { calculateLight(i, inWorldPos.xyz, inNormal.xyz, ambient, diffuse, spec); ambientSum += ambient; diffuseSum += diffuse; specSum += spec; } } else { for (int i=0; i<light.activeLights; ++i) { calculateLight(i, inWorldPos.xyz, -inNormal.xyz, ambient, diffuse, spec); ambientSum += ambient; diffuseSum += diffuse; specSum += spec; } } ambientSum /= light.activeLights; // (B) - works when declared/set here <---------------------------------------- Material thisMaterialsource = materialBanks[0].bank.materials[materialId]; vec4 texColor = thisMaterialsource.baseColorFactor; if(thisMaterialsource.colorTextureIndex > -1){ texColor = texture(texSampler[thisMaterialsource.colorTextureIndex], inUV0) * thisMaterialsource.baseColorFactor; } vec4 emissive = thisMaterialsource.emissiveFactor; if (thisMaterialsource.unlitTextureIndex > -1) { emissive = texture(texSampler[thisMaterialsource.unlitTextureIndex], inUV0) * thisMaterialsource.emissiveFactor; } outColor = vec4(ambientSum + diffuseSum, 1) * texColor + vec4(specSum, 1) + emissive;}
Full shader code:
#version 450#extension GL_ARB_separate_shader_objects : enable#extension GL_EXT_nonuniform_qualifier : requirestruct LightInfo{ vec3 Position;//Light Position in eye-coords vec3 La;//Ambient light intensity vec3 Ld;//Diffuse light intensity vec3 Ls;//Specular light intensity};struct MaterialInfo{ vec3 Ka;//Ambient reflectivity vec3 Kd;//Diffuse reflectivity vec3 Ks;//Specular reflectivity float Shininess;//Specular shininess factor};struct Material{ vec4 baseColorFactor; vec4 emissiveFactor; float metallicFactor; float roughnessFactor; float normalScale; float occlusionStrength; int colorTextureIndex; int normalTextureIndex; int unlitTextureIndex; int ambientOcclusionTextureIndex; int metallicRoughnessTextureIndex; int isTwoSided; int alphaMode; float alphaCutoff;};struct MaterialBank{ Material materials[80];};struct LightData{ vec4 pos; vec4 color;};#define MAX_CAMERAS 16struct CameraData{ vec4 pos; mat4 mat; mat4 view; mat4 proj; mat4 clip;};layout(push_constant) uniform PushConsts { uint cameraIndex; uint time;} pushConsts;layout(binding = 0) uniform UniformBufferCamera { CameraData cameras[MAX_CAMERAS]; uint cameraCount; uint cameraMax;} cam;layout(binding = 1) uniform UniformBufferLight { LightData lights[16]; vec4 ambientColor; int activeLights;} light;layout(set=1, binding = 0) uniform sampler2D texSampler[32];layout(set=2, binding = 0) uniform UniformBufferMat { MaterialBank bank;} materialBanks[1];layout(location = 0) in vec4 inNormal;layout(location = 1) in vec2 inUV0;layout(location = 2) in vec2 inUV1;layout(location = 3) in vec4 inWorldPos;layout(location = 4) in flat uint materialId;layout(location = 0) out vec4 outColor;void calculateLight(int lightIndex, vec3 position, vec3 norm, out vec3 ambient, out vec3 diffuse, out vec3 spec){ LightData thisLightSource = light.lights[lightIndex]; Material thisMaterialsource = materialBanks[0].bank.materials[materialId]; LightInfo thisLight; thisLight.Position = thisLightSource.pos.xyz;//Light Position in eye-coords thisLight.La = light.ambientColor.rgb;//Ambient light intensity thisLight.Ld = thisLightSource.color.rgb;//Diffuse light intensity thisLight.Ls = thisLightSource.color.rgb;//Specular light intensity MaterialInfo thisMaterial; vec4 texColor = thisMaterialsource.baseColorFactor; if (thisMaterialsource.colorTextureIndex > -1){ texColor = texture(texSampler[thisMaterialsource.colorTextureIndex], inUV0) * thisMaterialsource.baseColorFactor; } vec4 mrSample = vec4(1); if (thisMaterialsource.metallicRoughnessTextureIndex > -1) { mrSample = texture(texSampler[thisMaterialsource.metallicRoughnessTextureIndex], inUV0); } float perceptualRoughness = mrSample.g * thisMaterialsource.roughnessFactor; float metallic = mrSample.b * thisMaterialsource.metallicFactor; thisMaterial.Ka= texColor.rgb * (metallic+perceptualRoughness)/2;//Ambient reflectivity thisMaterial.Kd= texColor.rgb * (perceptualRoughness);//Diffuse reflectivity thisMaterial.Ks= texColor.rgb * (metallic-perceptualRoughness);//Specular reflectivity thisMaterial.Shininess= (metallic);//Specular shininess factor vec3 n = normalize(norm); vec3 s = normalize(thisLight.Position - position); vec3 v = normalize(-position); vec3 r = reflect(-s, n); ambient = thisLight.La * thisMaterial.Ka; if (thisMaterialsource.ambientOcclusionTextureIndex > -1){ float ao = texture(texSampler[thisMaterialsource.ambientOcclusionTextureIndex], inUV0).r; ambient = ambient * ao; } float sDotN = max(dot(s, n), 0.0); diffuse = thisLight.Ld * thisMaterial.Kd * sDotN; spec = thisLight.Ls * thisMaterial.Ks * pow(max(dot(r, v), 0.0), thisMaterial.Shininess);}void main(){ vec3 ambientSum = vec3(0); vec3 diffuseSum = vec3(0); vec3 specSum = vec3(0); vec3 ambient, diffuse, spec; // (A) - doesn't work when declared/set here <---------------------------------------- // Material thisMaterialsource = materialBanks[0].bank.materials[materialId]; if (gl_FrontFacing) { for (int i=0; i<light.activeLights; ++i) { calculateLight(i, inWorldPos.xyz, inNormal.xyz, ambient, diffuse, spec); ambientSum += ambient; diffuseSum += diffuse; specSum += spec; } } else { for (int i=0; i<light.activeLights; ++i) { calculateLight(i, inWorldPos.xyz, -inNormal.xyz, ambient, diffuse, spec); ambientSum += ambient; diffuseSum += diffuse; specSum += spec; } } ambientSum /= light.activeLights; // (B) - works when declared/set here <---------------------------------------- Material thisMaterialsource = materialBanks[0].bank.materials[materialId]; vec4 texColor = thisMaterialsource.baseColorFactor; if(thisMaterialsource.colorTextureIndex > -1){ texColor = texture(texSampler[thisMaterialsource.colorTextureIndex], inUV0) * thisMaterialsource.baseColorFactor; } vec4 emissive = thisMaterialsource.emissiveFactor; if (thisMaterialsource.unlitTextureIndex > -1) { emissive = texture(texSampler[thisMaterialsource.unlitTextureIndex], inUV0) * thisMaterialsource.emissiveFactor; } outColor = vec4(ambientSum + diffuseSum, 1) * texColor + vec4(specSum, 1) + emissive;}
When running on a Radeon HD 7750 and declaring thisMaterialsource
at (A)
, the program either crashes or freezes the PC to the point I have to power cycle the machine. It works fine when it's declared at position (B)
. When running on a Geforce GTX 1070, it works fine in both cases.
Is this simply a bug in GPU/drivers or a manifestation of some profound and arcane machinations that dictate how shaders work? How can I debug this sort of issues? Is there a way to see this is going to fail, other than running it? I'd really like to know, I care much more about learning from this than just getting it to run.