I am observing what appears to be incorrect per-view primitive clipping behavior in Vulkan multiview on NVIDIA.
Hardware
| GPU | NVIDIA GeForce RTX 5070 Laptop GPU |
| OS / Driver Model | Windows, WDDM |
| NVIDIA Driver | 610.88 |
| CUDA UMD | 13.3 |
| VRAM | 8 GB (8151 MiB reported) |
| OS | Win11 - 10.0.26200 |
Setup
- Vulkan multiview rendering with two views
- Vertex shader uses BuiltIn ViewIndex
- Per-view user clip distances are written through BuiltIn ClipDistance
- The generated SPIR-V declares Capability MultiView and Capability ClipDistance
- The SPIR-V passes spirv-val
- The issue is reproducible on NVIDIA under Windows
- ANGLE is only the frontend used to generate the Vulkan/SPIR-V workload
The failure is asymmetric between view 0 and view 1.
Test 1:
ViewIndex == 0:
ClipDistance[0] = +1.0
ViewIndex == 1:
ClipDistance[0] = -1.0
Result:
- view 0 rasterizes the primitive
- view 1 rejects the primitive
This is the expected behavior.
Test 2:
ViewIndex == 0:
ClipDistance[0] = -1.0
ViewIndex == 1:
ClipDistance[0] = +1.0
Expected result:
- the primitive is clipped/rejected in view 0
- the same primitive is retained and rasterized in view 1
Actual result:
- the primitive is absent from both views
The other ClipDistance components are positive in these tests, so only one user clip plane is involved.
ViewIndex itself is behaving correctly. I verified per-view shader execution independently by producing different ordinary vertex outputs for the two ViewIndex values, and those results are correct.
The generated SPIR-V also shows the expected data flow:
BuiltIn ViewIndex
-> per-view clip-distance computation
-> BuiltIn ClipDistance
There is no shared clip-distance storage between the two view invocations, and the module validates successfully with spirv-val.
The observed behavior therefore appears to be that when a primitive is completely rejected by a user clip plane for view 0, that primitive is also removed from the multiview rendering operation before view 1 can independently retain it.
In other words, the observed behavior is effectively:
view 0 fully outside user clip plane
view 1 inside user clip plane
-> primitive rejected for both views
whereas I would expect clipping and primitive survival to be evaluated independently for each active view in the multiview render pass.
The opposite case works correctly:
view 0 inside
view 1 fully outside
-> view 0 rasterizes, view 1 rejects
As a workaround, I currently avoid BuiltIn ClipDistance for view 0 and mask the unused region using depth instead, while continuing to use normal user clipping for view 1.
Is this a known NVIDIA Vulkan multiview issue involving BuiltIn ClipDistance / per-view primitive clipping?