Is gl_FragDepth equal gl_FragCoord.z when msaa enable?

I know gl_FragDepth will take the value of gl_FragCoord.z from opengl wiki.
https://www.khronos.org/opengl/wiki/Fragment_Shader/Defined_Outputs

But I have a problem. If I enable MSAA and write gl_FragDepth = gl_FragCoord.z in fragment shader, the display will not work fine. You can see a black line on the white triangle.

(upload://91Fj0roZJOwpNzQiIlV58JI971Q.png)

If I don’t write gl_FragDepth in fragment shader, it will work fine.

If I disalbe MSAA, it also work fine no matter if I write gl_FragDepth.

The correct display image is no black line:

The render scene is easy, I just draw 2 white triangles and they are intersected on an edge.

I add a simple light in vertex shader. The codes show as below:

const char *vertexShaderSource[] = {
	"#version 120\n",
	"varying vec4 lightColor;\n",
	"void main()\n",
	"{\n",
	"   vec3 n = normalize(gl_NormalMatrix * gl_Normal);\n",
	"   vec3 l = normalize(vec3(0.0, 1.0, 1.0));\n",
	"   float NdotL = clamp(dot(n, l), 0.001, 1.0);\n",
	"   lightColor = vec4(1.0)*(NdotL + 0.2);\n",
	"   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n",
	"}\n"
};
const char *fragmentShaderSource[] = {
	"#version 120\n",
	"varying vec4 lightColor;\n",
	"void main(void)\n",
	"{\n",
	"   gl_FragColor = vec4(lightColor.rgb, 1.0);\n",
	"	gl_FragDepth = gl_FragCoord.z;\n"
	"}\n"
};

I assume that what’s happening is that you’re effectively replacing multi-sample depth testing with per-fragment depth testing. Unless the fragment shader has input variables with the sample qualifier (or uses variables which are implicitly per-sample, such as gl_SampleID or gl_SamplePosition), the fragment shader is only evaluated once for each fragment and the outputs are used for all fragments. The built-in depth calculation is performed per sample, so each sample gets a different depth value. Setting gl_FragDepth in a fragment shader which is executed per-fragment will result in a single depth value for the whole fragment.

So at a minimum you would need to force the fragment shader to be executed per-sample (which will result in a significant increase in processing cost). You also need to figure out how to get the correct depth value for each fragment. gl_FragCoord is per-fragment even when multi-sampling. From my reading of the GLSL specification, you can’t just redeclare it with the sample qualifier. The interpolateAtSample or interpolateAtOffset functions might work on it, or they might not. If not, you’d need to calculate the depth in the vertex shader, store it in a user-defined output variable and use the interpolateAt* functions on that to get the per-sample depth.

I don’t agree with this reading of the spec. When doing per-sample shading, the fragment shader is supposed to generate one fragment per sample:

When the sample shading fraction is 1.0, a separate set of colors and other associated data are evaluated for each sample, and each set of values is evaluated at the sample location.

Note that the Vulkan specification explicitly states that FragCoord is affected by sample shading and maps to one of the samples (though it only specifies this for X and Y, and it’s underspecified for Z and W, so I think it’s a spec bug).

So it seems to me that the intent is that gl_FragCoord under sample shading ought to produce the values for a particular sample.

As for whether you can apply sample to it, the GLSL spec clearly implies that you can apply centroid to it. I say that because it says:

The use of centroid does not further restrict this value to be inside the current primitive.

If you couldn’t apply any interpolation qualifier to it, then it wouldn’t need to say that, since such a declaration would be forbidden. And I don’t see anywhere that it forbids the use of the sample qualifier.

So I see no reason why you can’t.

Yes, you are right. This output depth of my fragment shader overrides the multisample-generated depth values.
Thank you very much for your answers.