DIS: warp-based interpolation with source-point flow lookup - #775
Merged
Merged
Conversation
…ts on vsync - Cap dialog widths to the window instead of fixed minimums, weight labels against value chips - Stack footers, storage info, glasses settings and HUD toggles at compact widths - Align store grid columns with libraryColumns for controller focus - Add IME padding to dialogs with text input - Coalesce guest presents onto the Choreographer callback in VulkanRenderer - Give Fast-tier DIS flow the Balance refinement budget
dis_interpolate.comp - Replace the photometric-only occlusion test. It compared full-resolution colour against a flow solved at 180-360 px on the short side, so on textured motion it saturated and snapped whole regions to the nearest source frame, which reads as motion stalling for a frame and then jumping. - Occlusion now requires both a discontinuous flow field and a genuine mismatch between the warped samples. The discontinuity is measured over a 4 flow-texel window: around a screen-locked object the field ramps over a band tens of texels wide rather than stepping, so a per-texel slope never clears a useful threshold. The mismatch is measured at the flow scale and normalised by local contrast, so a slightly misaligned texture edge does not count as occlusion. - Pick the valid side from the sign of the flow divergence rather than the nearest frame in time: a diverging field is area opening up, which exists only in the next frame; a converging one is area being covered. - Flow debug view: log magnitude scale in source pixels. The old scale saturated at 16 px, which pegged the whole frame during a camera orbit and hid both the magnitude and any parallax. - OCCLUSION_STRENGTH and DEBUG_OCCLUSION are compile-time switches for A/B. dis_vr_add.comp - Bound the absolute flow magnitude. Nothing upstream did: the block search only limits displacement from the coarse estimate, the refinement only limits its own update, and the existing guard allowed four frame widths and then fell back to a value that was itself already huge. On a scene cut the flow reached hundreds of pixels and the warp smeared the frame edge across the picture. Clamp the magnitude to a quarter of the frame, and clamp rather than revert. The variational solver was ported to NumPy and exercised on a synthetic cut to locate this: it does not diverge, it faithfully smooths whatever it is given, and the runaway comes from the missing absolute bound. With the clamp the output pins at the limit for any input, and correct small motion is unchanged. Both shaders verified to compile to SPIR-V. Not yet run on device.
DIS: divergence-gated occlusion mask; bound the absolute flow magnitude
- dis_interpolate.comp: pre-occlusion blending (photometric occlusion only) - dis_vr_add.comp: loose component guard, no absolute magnitude clamp - vkr_dis.c: original refinement ladder, no Fast-tier VR budget lift Brings DIS in line with WinNative-Emu/WinNative 68f678c.
- dis_hist.comp: half-resolution pass collecting the pass-through evidence (frame difference, plus edge agreement for translucent overlays) and keeping the maximum with a decay, so a per-frame decision hovering around the thresholds cannot flicker - dis_interpolate.comp: apply the stabilized mask on top of the per-frame test, suppressed on cuts by the current frame difference; pick the blend side from the flow divergence instead of t so the side stays the same for every generated frame of a pair - vkr_dis.c: history resources, pipeline, descriptor sets, dispatch and reset UI_HIST_ENABLE=0 falls back to the per-frame mask, DIS_OCCL_SIDED=0 to the t-based side.
- the variational refinement runs on the finest three levels only; levels without it skip prep/add entirely and the search reads the densified flow as its coarse estimate - dis_propagate ranks candidates on a 4x4 subsample of the patch instead of all 64 texels, with the score rescaled to the 64-sample units the densification compares against - dis_side.comp computes the occlusion side (flow divergence sign) once per flow texel; the interpolate stage reads one tap instead of four flow fetches - the inverse search caps at six Gauss-Newton iterations (the SSD break already ends most patches earlier) - VR descriptor sets and pool are sized to the refined levels; UI dilation taps 4 -> 2
The 8x8 luma/gradient patch is loaded as 4x4 quads, three gathers per quad instead of one fetch per texel - about three times fewer sample instructions in the setup, same texels. The gathered component order is documented in the shader; at clamped borders the edge texel repeats, as the per-texel clamp did before.
Under the same threshold the overlay pass-through already uses to skip its own fetches, the shifted samples cannot change an output pixel visibly, so the warped pair, the side map and the edge dilation are all dropped and the real pair is blended directly. Static scenery and HUD-heavy screens are mostly such pixels, and this pass is the most expensive one per output pixel.
- the variational refinement runs on all levels again: at 4x the fast motion needed the coarse levels, and the three-level scope showed up as objects that looked uninterpolated - source-rate estimate: longer smoothing window and sub-2ms bursts rejected, so a single startup burst no longer spikes it to hundreds of fps - ratio hysteresis widened so the planner stops oscillating between 2 and 3 generated frames while the source rate drifts
The two-tap dilation saved a few fetches but left antialiased overlay edges uncovered under scene motion - the edge pixel is a blend of glyph and moving background, so only its neighbours carry the pair agreement. Four taps over 1.5px is the point the original analysis measured as the useful limit, and refining every level stays as well: the alternatives either save a couple of dispatches or give back the fast-motion smoothness.
- blend pick: thresholds raised (0.02..0.12 -> 0.03..0.18) so a moderately wrong flow keeps the warped blend instead of snapping to one real frame, which is what read as fast objects not being interpolated - 4x generation gets a third fixed-point pass on the finest level, so the warped pair lines up more often and fewer pixels reach the pick at all
SPDX headers crediting qwertypower (DEVAR Entertainment LLC), same as the C sources.
- dis_temporal.comp: EMA over the level-0 field with an advection gate, ping-pong RGBA32F where xy is this pair's chord and zw the previous pair's for the same content; jitter on long runs roughly halves - dis_interpolate.comp: follow a parabola through three consecutive real frames instead of the straight chord, falling back to the chord by construction where the gate found no usable history - dis_vr_add.comp: clamp the absolute flow magnitude to a quarter of the frame instead of the never-firing four-width component guard - vkr_dis.c / CMakeLists: pipeline, ping-pong images, descriptor sets and dispatch for the temporal pass
Replace the freeze/crossfade fallbacks with a motion-preserving warp: flow read at the source point, static overlays kept by static-vs-motion residual, divergence-sided occlusion, Catmull-Rom fetch. Drop temporal EMA and the parabolic path.
… hint The generator now lives in app/src/main/cpp/dis as the wndis static library (public header and GLSL shaders under include/), linked by libwinlator and libwnwayland instead of being compiled into each. On Adreno the GLES motion estimator can seed the level-2 search as a second candidate; it is off by default (debug.winnative.dis.hwme=1 enables it) since it measured quality-neutral at ~2.5 ms per frame.
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.
No description provided.