Cannot get depth prepass to work as calculated depth values occasionally differ. Depth test fails in draw pass sporadically (sometimes for some view angles all depth values pass equality check in draw pass, sometimes nearly half will fail).
- changing depth near and far from 0.1-1000.0 to 0.5-100.0 makes no perceivable difference in amount of z fighting (besides visibly cutting off some of the scene).
- depth buffer format: float32
- validation layer has nothing to complain about (LunarG from VulkanSDK 1.1.73.0).
- pipelines are nearly identical (differences: color attachments, descriptor sets for textures, depth write, depth compare op - LESS for prepass and EQUAL later).
- no cache used for pipeline nor shader compilation (shaders always recompiled via shaderc from VulkanSDK 1.1.73.0).
- shaders compiled with target environment vulkan and set warnings as errors.
- gl_Position is decorated with âinvariantâ for both and both have the exact same code calculating it.
- depth prepass has no fragment shader (having a dummy one that has nothing todo, but has âlayout(early_fragment_tests) in;â - makes no difference).
- draw pass has fragment shader with âlayout(early_fragment_tests) in;â and never does anything with depth.
- did not notice anything weird with the draw calls and associated state with NSight - except:
- glsl decompilation in it has different code appended to gl_Position calculation (both: âgl_Position.y = -gl_Position.y;â and only one has âgï»żl_Position.z = 2.0 * gl_Positioï»żn.z - gl_Position.wï»ż;â)
I suspect the discrepancy in the decompile to be NSight specific as SPIR-V does not seem to have any of that extra code for either shader (also, see the opening statement). But it is suspicious - something must look different to NSight for it to trigger only for one.
I am out of ideas how to proceed. Ideas?
Minimal shaders that cause problems (slight deviations in the calculated result with identical input [same vertex buffer is sent to both]). Code is captured as shaderc receives it (to be sure i donât send some wrong code and NSight also agrees - with the discrepancy as described earlier):
// depth prepass
#version 450
#pragma shader_stage(vertex)
#extension GL_ARB_separate_shader_objects : enable
layout(location=0) in vec3 inPos;
invariant gl_Position;
layout(push_constant) uniform Push { vec4 proj, pos, rot; } par;
vec4 projection(vec3 v) { return vec4(v.xy * par.proj.xy, v.z * par.proj.z + par.proj.w, -v.z); }
vec3 qrot(vec4 q, vec3 v) { return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v); }
vec4 qinv(vec4 q) { return vec4(-q.xyz, q.w); }
vec3 transInv(vec3 v, vec4 pos, vec4 rot) { return qrot(qinv(rot), (v - pos.xyz) / pos.w); }
vec3 projAndGetPos() {
vec3 pos = inPos * (32767.0 / 1024.0);
gl_Position = projection(transInv(pos, par.pos, par.rot));
return pos;
}
void main() {
projAndGetPos();
}
// draw pass
#version 450
#pragma shader_stage(vertex)
#extension GL_ARB_separate_shader_objects : enable
layout(location=0) in vec3 inPos;
layout(location=1) in vec2 inSelColorTex;
layout(location=2) in vec4 inNormSelCover;
layout(location=3) in vec4 inTexSet;
invariant gl_Position;
layout(push_constant) uniform Push { vec4 proj, pos, rot; } par;
layout(location=0) out Frag { vec3 pos; float selTex; vec4 color; vec3 normal; float selCover; vec3 tocam; flat vec4 texSet; } sOut;
vec4 projection(vec3 v) { return vec4(v.xy * par.proj.xy, v.z * par.proj.z + par.proj.w, -v.z); }
vec3 qrot(vec4 q, vec3 v) { return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + q.w * v); }
vec4 qinv(vec4 q) { return vec4(-q.xyz, q.w); }
vec3 transInv(vec3 v, vec4 pos, vec4 rot) { return qrot(qinv(rot), (v - pos.xyz) / pos.w); }
vec3 projAndGetPos() {
vec3 pos = inPos * (32767.0 / 1024.0);
gl_Position = projection(transInv(pos, par.pos, par.rot));
return pos;
}
void main() {
sOut.pos = projAndGetPos();
sOut.selTex = inSelColorTex.y;
sOut.color = vec4(0.0);
sOut.normal = inNormSelCover.xyz;
sOut.selCover = inNormSelCover.w;
sOut.tocam = par.pos.xyz - sOut.pos;
sOut.texSet = inTexSet * 255.0;
}