fix(d3d11): allocate the per-eye bridge as TYPELESS so Linear projects present - #327
Merged
dfattal merged 1 commit intoSep 15, 2026
Merged
Conversation
…s present
A Linear project asks for an sRGB swapchain on the present path
(dxr_prov_set_color_space_linear -> want_srgb), and the D3D11 zero-copy
MultiPass path then allocated its per-eye bridge textures with that same
concrete format — DXGI_FORMAT_R8G8B8A8_UNORM_SRGB.
The runtime hands its swapchain images back as R8G8B8A8_TYPELESS, so submit
ended up calling CopySubresourceRegion with an _UNORM_SRGB source against a
TYPELESS destination. That faults inside the NVIDIA D3D11 UMD
(nvwgf2umx!SetDependencyInfo, null dereference under
d3d11!CContext::TID3D11DeviceContext_CopySubresourceRegion_), taking the
player down, and the frames before it goes show a black panel because the
eye content never reaches the swapchain. Gamma projects were unaffected:
their bridge is _UNORM, which copies into the TYPELESS image fine. D3D12 was
unaffected too — it uses the own-device shared bridge, not this copy.
Allocate the per-eye bridge as the TYPELESS parent of the swapchain format
instead. It is the same format family, so the copy is trivially legal, and
TYPELESS is also what D3D11 requires of a resource that has to carry an sRGB
render-target view — which is exactly what Unity builds for an eye texture
declared with kUnityXRRenderTextureFlagsSRGB. Gamma keeps working unchanged
because 28 and 29 share that TYPELESS parent.
Scoped to the eye targets: ps_sc_dxgi_format() is untouched, so the
swapchain itself, wsui, Local2D and the zone layers keep the concrete
formats they have always used.
Verified on Windows 11, Unity 6000.3.14f1, BiRP + MultiPass, RTX 4090 Laptop
(driver 32.0.15.8180), Leia SR display, built player:
- Linear + D3D11: 3D scene renders, correct brightness, no crash (was a
black screen followed by a crash on the 1-view -> 2-view transition)
- Gamma + D3D11: unchanged from before the patch
- Linear + D3D12: unchanged from before the patch
Signed-off-by: byungjul <byungju.lee@leiainc.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #326.
A Linear project takes the sRGB swapchain path on present (
dxr_prov_set_color_space_linear->want_srgb), and the D3D11 zero-copy MultiPass path then allocated its per-eye bridge textures with that same concrete format,R8G8B8A8_UNORM_SRGB.The runtime hands its swapchain images back as
R8G8B8A8_TYPELESS, so submit ended up doingCopySubresourceRegionfrom an_UNORM_SRGBsource into a TYPELESS destination. That faults inside the NVIDIA D3D11 UMD:and the frames before it goes down show a black panel, because the eye content never reaches the swapchain image.
Gamma projects were unaffected — their bridge is
_UNORM, which copies into the TYPELESS image fine. D3D12 was unaffected too: it uses the own-device shared bridge rather than this same-device copy. Dumping both ends of the copy makes the difference a single field:fmt=27TYPELESSfmt=29UNORM_SRGBfmt=27TYPELESSfmt=28UNORMChange
Allocate the per-eye bridge as the TYPELESS parent of the swapchain format instead of the concrete format. It is the same format family, so the copy is trivially legal, and TYPELESS is also what D3D11 requires of a resource that has to carry an sRGB render-target view — which is exactly what Unity builds for an eye texture declared with
kUnityXRRenderTextureFlagsSRGB. Gamma keeps working unchanged because 28 and 29 share that TYPELESS parent.Scoped to the eye targets:
ps_sc_dxgi_format()is untouched, so the swapchain itself, wsui, Local2D and the zone layers keep the concrete formats they have always used. The newtypelessparameter onps_alloc_unity_tex()defaults to 0, so every existing call site is unchanged.Verification
Windows 11, Unity 6000.3.14f1, BiRP + MultiPass, RTX 4090 Laptop (driver 32.0.15.8180), Leia SR display (ACR0001), built player. Each config was run through the 2D home screen and into a 3D scene, i.e. across the 1-view -> 2-view layout renegotiation:
After the fix,
WITNESSreports a steadypresents/s=60.0 weaves/s=60.0 mode=3dwith no crash dumps. Correct brightness on Linear also confirms Unity does build the sRGB RTV over the TYPELESS resource, which is the assumption the change rests on.Notes
ps_alloc_shared_tex_d3d11, own-device NT-handle bridge) is left alone. It may have the same exposure, but I could not verify whether a shared NT-handle texture accepts a TYPELESS format here, so I did not want to change it blind.Runtime/Plugins/Windows/x64/displayxr_unity.dllis deliberately not included, since binaries look like they are refreshed in release commits.