[Bug 60409] New: mfplat: dxgi_surface_buffer_Lock always does a GPU readback (ReadWrite), stalling decoder output ~29 ms per frame
http://bugs.winehq.org/show_bug.cgi?id=60409 Bug ID: 60409 Summary: mfplat: dxgi_surface_buffer_Lock always does a GPU readback (ReadWrite), stalling decoder output ~29 ms per frame Product: Wine Version: unspecified Hardware: x86-64 OS: Linux Status: UNCONFIRMED Severity: normal Priority: P2 Component: mfplat Assignee: wine-bugs@list.winehq.org Reporter: ndqh12679@gmail.com Target Milestone: --- Distribution: --- Filed together with the bug "mfplat: MFCreateDXGISurfaceBuffer fails silently for DXGI_FORMAT_R8_UINT textures, so UE4 ElectraPlayer shows no video"; this only shows up once that one is worked around. With the format bug worked around, the 30 fps clip played at about half speed: about 46 ms per frame, of which about 29 ms was spent inside `dxgi_surface_buffer_Lock`. The decoder writes its output through `sample_ConvertToContiguousBuffer` and then `IMFMediaBuffer::Lock()`. `dxgi_surface_buffer_Lock()` always calls `dxgi_surface_buffer_map(buffer, MF2DBuffer_LockFlags_ReadWrite)`. That queues a `CopySubresourceRegion` from the texture into the staging texture, then does a `Map()` that waits for it. The copy sits behind the game's whole queued frame, and every byte it reads back is overwritten by the decoder immediately afterwards. Proof of concept, not a proposed fix. I binary-patched the `mov edx,3` before `call dxgi_surface_buffer_map` in `dxgi_surface_buffer_Lock` to pass `MF2DBuffer_LockFlags_Write` (2). `map` then skips the readback but still maps, and `Unlock` still uploads. Measured with `+mfplat` tracing on, over steady-state frames: | Before | After (clip 1 / clip 2) Time per frame | 45.7 ms | 33.7 / 37.2 ms (30 fps needs 33.3 ms) Time stalled in `Lock` | 29.1 ms | 11.2 / 3.0 ms There were no mfplat errors, and the video plays visibly smoother. This hack changes `Lock()` semantics for every caller, so anything that reads a DXGI buffer through `Lock()` would get stale data. Suggested fix: have Wine's decoder transforms (winegstreamer and winedmo) write their output through `IMF2DBuffer2::Lock2DSize(MF2DBuffer_LockFlags_Write, ...)` when the output buffer is 2D/DXGI, instead of going through `ConvertToContiguousBuffer` + `Lock()`. That path already skips the readback, and it leaves `Lock()` correct for readers. == Affected == - Game: Wuthering Waves (Steam 3513350), v3.7, UE 4.26.2, D3D11 mode (`-dx11`). The ultimate of the new 3.7 character Hsin plays H.264 overlay videos (1920x2160 and 3840x2160) through ElectraPlayer. - Reproduced on: - GE-Proton11-7 (wine-staging 11.0; H.264 MFT from winedmo/FFmpeg) - Proton-CachyOS cachyos-11.0-20260703 (H.264 MFT from winegstreamer) Both fail at the same step, so it isn't decoder-backend specific. - System: Nobara 44, kernel 7.2.6, NVIDIA RTX 5060 Ti, driver 595.99.02, DXVK. - Also running: 3DMigoto (WWMI) was injected. Toggling its mods off made no difference, and the failure is fully explained by the mfplat path below. I have not tested without the injection. -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=60409 --- Comment #1 from Nikolay Sivov <bunglehead@gmail.com> --- There is a lot of noise here, e.g. I don't quite get what the proposed workaround is, hopefully somebody does. I think ultimately hw decoding that avoids sysmem copies is the solution. -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
http://bugs.winehq.org/show_bug.cgi?id=60409 --- Comment #2 from Ken Sharp <imwellcushtymelike@gmail.com> --- Did you actually test this on Wine and not Proton? -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.
participants (1)
-
WineHQ Bugzilla