Closed glebov-andrey closed 1 year ago
Thank you. We will take a look at this issue. Currently, we use a generic output to export view index to fragment shader. This is unnecessary. View index could be obtained in fragment shader directly via system value input (a user data SGPR). We will rework this.
Currently, we use a generic output to export view index to fragment shader.
Ok, in that case the fragment shader assembly makes sense. But it would then suggest that the vertex shader is either writing the wrong values to that output, or writing them to the wrong location.
Is there any more information I could provide that would help?
Is there any more information I could provide that would help?
If you can attach a simplified pipeline (including your VS+GS+FS) in this ticket, that would be fine to us.
Do you mean the GLSL source or SPIR-V? And would a GFXReconstruct capture be better for completeness?
Do you mean the GLSL source or SPIR-V?
Yes, the simplified GLSL sources of VS+GS+FS would be enough for us to investigate it.
// .vert
layout(location = 0) in vec2 vertex;
void main() { gl_Position = vec4(vertex, 1.0, 1.0); }
//.frag
#extension GL_EXT_multiview : require
layout(location = 0) out vec4 normal;
void main() { normal.xyz = vec3(1.0, 0.0, float(gl_ViewIndex)); }
Shaders compiled with glslc v2022.3 with -O -std=460 --target-env=vulkan1.3
.
Rough pipeline state:
R16G16B16A16_SFLOAT
color attachment and a D32_SFLOAT_S8_UINT
depth/stencil attachmentGot it. Thank you.
Try to fix your problem: https://github.com/GPUOpen-Drivers/llpc/pull/2162
Thank you, that fixed it - the artifacts are gone.
Hi, I believe I've found a bug in the handling of the
ViewIndex
SPIR-V builtin when multiview is disabled.My application conditionally uses multiview rendering for VR. Shaders use
gl_ViewIndex
unconditionally, assuming that when multiview is disabled, its value is0
. This is guaranteed by the spec. just above here:When running the application, specifically with AMDVLK drivers on Linux, some render passes produce artifacts with multiview disabled, but not with it enabled (with single-layer framebuffers in both cases).
gl_ViewIndex
is used in vertex, geometry and fragment shaders to index into uniform buffers andsampler2DArray
s. When I replacegl_ViewIndex
with0
in the geometry and fragment shaders, the artifacts disappear. Note: Since AMDVLK does not supportmultiviewGeometryShader
, the pass which uses a geometry shader gets disabled when multiview is enabled.I've checked all of this with an up-to-date version of AMDVLK built from source (with assertions and ASAN). Validation layers don't complain about anything. RADV and the Windows driver with the same GPU are Ok, and so is NVIDIA. The artifacts look like random patches of geometry rendered across the viewport in random patterns or stripes. When viewing a frame capture in RenderDoc, the artifacts persist but are random from replay to replay. The artifacts appear over regions which failed the depth test.
My best guess, based on skimming over the driver sources, is that LLPC doesn't replace the
ViewIndex
builtin with0
for geometry and fragment shaders. I found the following code which does this for vertex and mesh shaders (in another file), but nothing similar for other stages: https://github.com/GPUOpen-Drivers/llpc/blob/4ec1290558efeb1c90bacc21c3b4ecd0cc8244ee/lgc/patch/PatchInOutImportExport.cpp#L2090-L2095 Of cource, this could be handled some other way which I haven't found.The other reason this seems like a reasonable explanation, is the assembly for one of the fragment shaders. Firstly, the assembly of the fragment shader with
gl_ViewIndex
is identical, whether or not multiview is enabled, while the vertex shader changes significantly (specifically around load offsets). Secondly, the assembly changes when I replacegl_ViewIndex
with0
.Here is the assembly output of one of the fragment shaders. The only thing it does, is loads a value from a uniform buffer at an offset based on
gl_ViewIndex
and writes that to an attachment. And this is enough to cause artifacts.For reference:
If the issue turns out to be more complicated, then I can prepare a simplified reproducer and a GFXReconstruct capture of it, or something.