protonscr

[D3D11] `reproducibleCommandStream` breaks apps that depend on query loops

dxvkclosed
doitsujin/dxvk#5522 · opened 2026-02-21 by PixelyIon · updated 2026-02-23 · 2 comments · github
PPixelyIon 2026-02-21 github

While replaying a D3D11 apitrace that calls GetData, it does so in a loop until the query succeeds. DXVK normally handles this case fine as it does a ConsiderFlush(GpuFlushType::ImplicitSynchronization) inside GetData but when reproducibleCommandStream is set then all ImplicitSynchronization flushes are dropped as the maxType is ExplicitFlush which causes the loop to never end while no GPU work is submitted.

Replacing the ImplicitSynchronization with an ExplicitFlush there does result in the application working again, but I'm not sure if this is the best approach. I was thinking perhaps if there's multiple calls to the same D3D11Query object in a short timespan then an explicit flush could be done as a stop gap?

Ddoitsujin maintainer 2026-02-21 github

Is this a problem in practice for the intended use case of reproducibleCommandStream?

This type of breakage is not unexpected with the option, and I really want to avoid adding any sort of complexity just for this. Adding heuristics like detecting multiple calls also defeats the entire purpose of reproducibleCommandStream since we want to, well, get consistent command streams.

I guess another option would be to enable tiler mode (i.e. dxvk.tilerMode=True) and deprecate reproducibleCommandStream, the former already adjusts flush heuristics and should hopefully work well w.r.t. render pass behaviour.

PPixelyIon 2026-02-23 github

Is this a problem in practice for the intended use case of reproducibleCommandStream?

Yeah, we intend to use it for having consistent performance characteristics while replaying traces for guiding some design decisions in Turnip where inconsistent playback could lead to incorrect conclusions. In this case, we already have tilerMode enabled (as it's running on Turnip, with the auto tristate) - but that doesn't seem to be good enough for proper reproducibility as dropping the flush threshold down to ImplicitStrongHint causes a lot more of them.

I think that realistically given the constraints we have three options:

  1. reproducibleCommandStream can have a variant where it drops down to ImplicitSynchronization instead of ExplicitFlush.
  2. GetData could do an ExplicitFlush instead.
  3. Just modify apitrace itself to call Flush() for these infloops.

After some internal discussion, I think that it's likely the best to go for (3) for now as the other options will lead to reproducibleCommandStream doing more flushes where they might not really be necessary. I'll be closing the issue for now, if we see this issue in more than just apitrace, then it's likely worth dealing with it on the DXVK level and I'll reopen it if/when that happens.

Nothing extracted yet.