Skip to content

Vulkan: fix inert depth test on Intel Macs (see-through map/models)#1

Closed
Rakete175 wants to merge 19 commits into
Fran6nd:vulkan-2from
Rakete175:vulkan-2
Closed

Vulkan: fix inert depth test on Intel Macs (see-through map/models)#1
Rakete175 wants to merge 19 commits into
Fran6nd:vulkan-2from
Rakete175:vulkan-2

Conversation

@Rakete175

Copy link
Copy Markdown

On Intel Macs, MoltenVK encodes the offscreen scene pass with a nil Metal depth attachment whenever the depth texture is created as both a render attachment and a sampled texture. Every draw in that pass then runs with depth test/write enabled but no depth buffer, so visibility degenerates to draw order: far geometry shows through near geometry, and models are visible through walls. Apple Silicon tolerates the combination, which is why the bug was Intel-only. The Metal validation layer confirms the mechanism ("MTLDepthStencilDescriptor sets depth test but MTLRenderPassDescriptor has a nil depthAttachment texture", once per draw).

Fix: never put SAMPLED usage on the scene depth attachment at 1x. Instead, copy the depth into a new sampled image (sceneDepthSampleImage) right after the offscreen pass — depth is final there, since sprites are colour-only and water doesn't write depth — and point GetResolvedDepthImage() at the copy. All depth-reading consumers (soft particles, water refraction, fog, DoF, lens flare, cavity outline) already go through that accessor, so none of them change. The MSAA path is untouched: it must sample the multisampled attachment for the depth resolve, and already reuses the resolved image downstream (MSAA is unavailable on the affected GPUs anyway).

Also included, both required on the same hardware:

  • Depth format fallback is now depth-only D32_SFLOAT instead of D32_SFLOAT_S8_UINT (Intel supports neither D24_UNORM_S8_UINT nor a packed 24-bit depth); stencil is unused by this renderer.

  • Disable Metal argument buffers on x86_64 alongside the existing MTLHeap workaround. Intel Metal requires 256-byte constant-buffer offset alignment, but MoltenVK sub-allocates its descriptor argument buffers at 16-byte offsets, so descriptors are silently read from wrong offsets (asserts under MTL_DEBUG_LAYER=1). Descriptors are bound discretely instead.

Verified on Intel Iris Pro (Haswell, macOS 12.7, MoltenVK 1.4.1): correct occlusion in all view directions, no models visible through walls, and the Metal validation flood is gone. Reverting the split (sampling the depth attachment directly) reproduces the bug, confirming the trigger.

Fran6nd and others added 19 commits June 27, 2026 19:51
On Intel Macs, MoltenVK encodes the offscreen scene pass with a nil Metal
depth attachment whenever the depth texture is created as both a render
attachment and a sampled texture. Every draw in that pass then runs with
depth test/write enabled but no depth buffer, so visibility degenerates to
draw order: far geometry shows through near geometry, and models are
visible through walls. Apple Silicon tolerates the combination, which is
why the bug was Intel-only. The Metal validation layer confirms the
mechanism ("MTLDepthStencilDescriptor sets depth test but
MTLRenderPassDescriptor has a nil depthAttachment texture", once per draw).

Fix: never put SAMPLED usage on the scene depth attachment at 1x. Instead,
copy the depth into a new sampled image (sceneDepthSampleImage) right after
the offscreen pass — depth is final there, since sprites are colour-only
and water doesn't write depth — and point GetResolvedDepthImage() at the
copy. All depth-reading consumers (soft particles, water refraction, fog,
DoF, lens flare, cavity outline) already go through that accessor, so none
of them change. The MSAA path is untouched: it must sample the multisampled
attachment for the depth resolve, and already reuses the resolved image
downstream (MSAA is unavailable on the affected GPUs anyway).

Also included, both required on the same hardware:

- Depth format fallback is now depth-only D32_SFLOAT instead of
  D32_SFLOAT_S8_UINT (Intel supports neither D24_UNORM_S8_UINT nor a
  packed 24-bit depth); stencil is unused by this renderer.

- Disable Metal argument buffers on x86_64 alongside the existing MTLHeap
  workaround. Intel Metal requires 256-byte constant-buffer offset
  alignment, but MoltenVK sub-allocates its descriptor argument buffers at
  16-byte offsets, so descriptors are silently read from wrong offsets
  (asserts under MTL_DEBUG_LAYER=1). Descriptors are bound discretely
  instead.

Verified on Intel Iris Pro (Haswell, macOS 12.7, MoltenVK 1.4.1): correct
occlusion in all view directions, no models visible through walls, and the
Metal validation flood is gone. Reverting the split (sampling the depth
attachment directly) reproduces the bug, confirming the trigger.
@Fran6nd

Fran6nd commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Sooo awesome ! thanks @Rakete175

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants