在我的片段着色器中移动一个变量会导致它无法工作或使我的 PC 完全崩溃
Moving a variable in my fragment shader makes it either not work or completely crash my PC
当 运行 在 Radeon HD 7750 上运行并在 (A)
上声明 thisMaterialsource
时,程序要么崩溃,要么死机,以至于我不得不重启机器。当它在 (B)
位置声明时它工作正常。 运行在 Geforce GTX 1070 上运行时,两种情况下都可以正常工作。
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;
}
完整着色器代码:
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_EXT_nonuniform_qualifier : require
struct 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 16
struct 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;
}
请原谅我的着色器代码的质量问题,我只是在试验和拼凑东西,然后遇到了这个问题,除了烦人的调试之外,完全让我措手不及。
它现在已修复,但我想知道它为什么会发生,老实说,与我在学习过程中处理过的许多其他问题不同,我什至不知道从哪里开始寻找。
这仅仅是 GPU/drivers 中的一个错误,还是决定着色器如何工作的一些深刻而神秘的阴谋的表现?我该如何调试这类问题?除了 运行ning 之外,有没有办法看出这会失败?我真的很想知道,我更关心从中学习,而不是仅仅达到 运行。
如果您不介意再经历一两个 power-off-on 周期,请尝试对着色器进行以下简化:
void main()
{
... variables
// (A) - doesn't work when declared/set here <----------------------------------------
// Material thisMaterialsource = materialBanks[0].bank.materials[materialId];
/// Instead of doing two almost identical loops, extract the normal inversion
vec3 normal = (gl_FrontFacing ? inNormal : -inNormal).xyz;
for (int i=0; i<light.activeLights; ++i)
{
calculateLight(i, inWorldPos.xyz, normal, 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];
... all the rest
}
一个疯狂的猜测可能如下:HD7750 相对较旧,如果 GLSL 编译器做了一些奇怪的事情,活动灯的两个循环(动态数量)会生成过多的着色器字节码。所以你会得到可用线程内存的溢出。 GTX 1070显然更强大,不会遭受这样的“虐待”。
除此之外,着色器应该没问题,上述更改仍然是一种解决方法,不是必须的。即使在较新的 Radeon 上,我们也遇到过 GLSL 的奇怪行为(即,有些事情不符合规范),但这与您的问题不相似。
当 运行 在 Radeon HD 7750 上运行并在 (A)
上声明 thisMaterialsource
时,程序要么崩溃,要么死机,以至于我不得不重启机器。当它在 (B)
位置声明时它工作正常。 运行在 Geforce GTX 1070 上运行时,两种情况下都可以正常工作。
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;
}
完整着色器代码:
#version 450
#extension GL_ARB_separate_shader_objects : enable
#extension GL_EXT_nonuniform_qualifier : require
struct 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 16
struct 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;
}
请原谅我的着色器代码的质量问题,我只是在试验和拼凑东西,然后遇到了这个问题,除了烦人的调试之外,完全让我措手不及。
它现在已修复,但我想知道它为什么会发生,老实说,与我在学习过程中处理过的许多其他问题不同,我什至不知道从哪里开始寻找。
这仅仅是 GPU/drivers 中的一个错误,还是决定着色器如何工作的一些深刻而神秘的阴谋的表现?我该如何调试这类问题?除了 运行ning 之外,有没有办法看出这会失败?我真的很想知道,我更关心从中学习,而不是仅仅达到 运行。
如果您不介意再经历一两个 power-off-on 周期,请尝试对着色器进行以下简化:
void main()
{
... variables
// (A) - doesn't work when declared/set here <----------------------------------------
// Material thisMaterialsource = materialBanks[0].bank.materials[materialId];
/// Instead of doing two almost identical loops, extract the normal inversion
vec3 normal = (gl_FrontFacing ? inNormal : -inNormal).xyz;
for (int i=0; i<light.activeLights; ++i)
{
calculateLight(i, inWorldPos.xyz, normal, 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];
... all the rest
}
一个疯狂的猜测可能如下:HD7750 相对较旧,如果 GLSL 编译器做了一些奇怪的事情,活动灯的两个循环(动态数量)会生成过多的着色器字节码。所以你会得到可用线程内存的溢出。 GTX 1070显然更强大,不会遭受这样的“虐待”。
除此之外,着色器应该没问题,上述更改仍然是一种解决方法,不是必须的。即使在较新的 Radeon 上,我们也遇到过 GLSL 的奇怪行为(即,有些事情不符合规范),但这与您的问题不相似。