From 3c3af6c7ec59e640bdd82d5233511968e79f0396 Mon Sep 17 00:00:00 2001 From: qwertypower <1qwertypower1@gmail.com> Date: Tue, 29 Sep 2026 23:23:27 +0300 Subject: [PATCH] OpenFlow: rename the DIS frame generator, follow fast and small motion, fix edge ghosting - The engine is called OpenFlow in the UI, logs (tag "OpenFlow") and docs; the module moves to cpp/openflow and the library to "openflow". DIS stays the name of the algorithm. - Search: the coarsest level is block-matched before Gauss-Newton, so fast camera turns keep their motion; the previous pair's flow is scored as another start on every level, which follows small fast objects and periodic textures the pyramid loses. - Interpolation: the edge guard grows with the motion; an off-frame sample no longer triggers the occlusion path or the overlay history, and the off-frame feather lies inside the frame. This removes the doubled band along the screen edge on camera turns. Bench (1280x720, 180p, x4 from 30 fps): mean PSNR 21.02 -> 22.64 dB, small fast objects 25.2 -> 29.9, hard camera turn 13.3 -> 18.2. Adreno 750: flow and generate times unchanged. --- CREDITS.md | 4 +- README.md | 4 +- app/src/main/cpp/CMakeLists.txt | 6 +- .../main/cpp/{dis => openflow}/CMakeLists.txt | 26 ++-- .../include/shaders/dis_densify.comp | 2 +- .../include/shaders/dis_flow_pack.comp | 2 +- .../include/shaders/dis_gradient.comp | 2 +- .../include/shaders/dis_hist.comp | 2 +- .../include/shaders/dis_interpolate.comp | 35 ++++-- .../include/shaders/dis_inverse_search.comp | 113 ++++++++++++++---- .../include/shaders/dis_luma.comp | 2 +- .../include/shaders/dis_luma_r16.comp | 2 +- .../include/shaders/dis_luma_r32.comp | 2 +- .../include/shaders/dis_me_luma.comp | 2 +- .../include/shaders/dis_propagate.comp | 2 +- .../include/shaders/dis_side.comp | 2 +- .../include/shaders/dis_vr_add.comp | 2 +- .../include/shaders/dis_vr_coef.comp | 2 +- .../include/shaders/dis_vr_d1.comp | 2 +- .../include/shaders/dis_vr_d2.comp | 2 +- .../include/shaders/dis_vr_prep.comp | 2 +- .../include/shaders/dis_vr_sor.comp | 2 +- .../include/shaders/dis_vr_w.comp | 2 +- .../cpp/{dis => openflow}/include/vkr_dis.h | 2 +- .../cpp/{dis => openflow}/src/dis_qcom_me.c | 4 +- .../cpp/{dis => openflow}/src/dis_qcom_me.h | 0 .../main/cpp/{dis => openflow}/src/vkr_dis.c | 68 ++++++----- app/src/main/cpp/waylandcomp/CMakeLists.txt | 6 +- .../cpp/waylandcomp/src/framegen_bridge.c | 2 +- .../cpp/waylandcomp/src/framegen_engine.c | 2 +- .../waylandcomp/src/framegen_engine_stub.c | 2 +- app/src/main/cpp/waylandcomp/src/vk_present.c | 2 +- .../cpp/winlator/vk/framegen/fg_present.c | 6 +- app/src/main/cpp/winlator/vk/vk_renderer.c | 6 +- app/src/main/res/values-b+es+419/strings.xml | 6 +- app/src/main/res/values-da/strings.xml | 6 +- app/src/main/res/values-de/strings.xml | 6 +- app/src/main/res/values-es/strings.xml | 6 +- app/src/main/res/values-fi/strings.xml | 6 +- app/src/main/res/values-fr/strings.xml | 6 +- app/src/main/res/values-hi/strings.xml | 6 +- app/src/main/res/values-it/strings.xml | 6 +- app/src/main/res/values-ja/strings.xml | 6 +- app/src/main/res/values-ko/strings.xml | 6 +- app/src/main/res/values-no/strings.xml | 6 +- app/src/main/res/values-pl/strings.xml | 6 +- app/src/main/res/values-pt-rBR/strings.xml | 6 +- app/src/main/res/values-pt/strings.xml | 6 +- app/src/main/res/values-ro/strings.xml | 6 +- app/src/main/res/values-ru/strings.xml | 6 +- app/src/main/res/values-sv/strings.xml | 6 +- app/src/main/res/values-th/strings.xml | 6 +- app/src/main/res/values-tr/strings.xml | 6 +- app/src/main/res/values-uk/strings.xml | 6 +- app/src/main/res/values-zh-rCN/strings.xml | 6 +- app/src/main/res/values-zh-rTW/strings.xml | 6 +- app/src/main/res/values/strings.xml | 6 +- docs/FRAME-GENERATION.md | 16 +-- 58 files changed, 284 insertions(+), 192 deletions(-) rename app/src/main/cpp/{dis => openflow}/CMakeLists.txt (67%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_densify.comp (97%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_flow_pack.comp (95%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_gradient.comp (95%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_hist.comp (97%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_interpolate.comp (82%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_inverse_search.comp (69%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_luma.comp (91%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_luma_r16.comp (91%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_luma_r32.comp (91%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_me_luma.comp (95%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_propagate.comp (97%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_side.comp (96%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_vr_add.comp (96%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_vr_coef.comp (97%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_vr_d1.comp (93%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_vr_d2.comp (92%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_vr_prep.comp (93%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_vr_sor.comp (96%) rename app/src/main/cpp/{dis => openflow}/include/shaders/dis_vr_w.comp (94%) rename app/src/main/cpp/{dis => openflow}/include/vkr_dis.h (97%) rename app/src/main/cpp/{dis => openflow}/src/dis_qcom_me.c (98%) rename app/src/main/cpp/{dis => openflow}/src/dis_qcom_me.h (100%) rename app/src/main/cpp/{dis => openflow}/src/vkr_dis.c (97%) diff --git a/CREDITS.md b/CREDITS.md index cb33ddff9..728818df6 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -57,7 +57,7 @@ corresponding source for every copyleft component is available from the projects [Eden Emulator Project](https://git.eden-emu.dev/eden-emu/eden) (GPL-3.0-or-later) — the Vulkan port of that chain that WinNative's frame generation is derived from. See [what came from Camille LaVey's Eden port](#frame-generation--what-came-from-camille-laveys-eden-port) -- **DIS optical flow frame generation** by **qwertypower** +- **OpenFlow frame generation** (DIS optical flow) by **qwertypower** ([DEVAR Entertainment LLC](https://devar.ai/)) (GPL-3.0) — a complete open-source implementation of a Dense Inverse Search frame generator, the second frame generation engine in WinNative and the one that needs no shaders from anywhere else. @@ -119,7 +119,7 @@ of a user's own Lossless Scaling install (`lsfg_dll.*`), translating them when o available (`lsfg_dxbc.*`), the JNI surface (`lsfg_jni.*`), driver probing (`lsfg_probe.*`), and wiring the chain into WinNative's compositor and swapchain (`vkr_lsfg.*`). -## DIS frame generation — the fully open-source engine +## OpenFlow frame generation — the fully open-source engine WinNative's second frame generator is a complete open-source implementation of **Dense Inverse Search** optical flow, contributed by **qwertypower** (DEVAR Entertainment LLC) under GPL-3.0. diff --git a/README.md b/README.md index f0790694f..7a1cf622f 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ alongside them. | --- | --- | | 📦 **Install** | [Releases](https://github.com/WinNative-Emu/WinNative/releases) | | 🎮 **Retro consoles** | [docs/RETRO-CONSOLES.md](docs/RETRO-CONSOLES.md) — NES through PlayStation 2 | -| 🎞️ **Frame generation** | [docs/FRAME-GENERATION.md](docs/FRAME-GENERATION.md) — LSFG and DIS | +| 🎞️ **Frame generation** | [docs/FRAME-GENERATION.md](docs/FRAME-GENERATION.md) — LSFG and OpenFlow | | 🖥️ **Wayland display server** | [docs/WAYLAND-DISPLAY.md](docs/WAYLAND-DISPLAY.md) — winewayland sessions on the embedded compositor | | 🔨 **Build from source** | [docs/BUILDING.md](docs/BUILDING.md) | | 🙏 **Credits & licenses** | [CREDITS.md](CREDITS.md) · [EMULATOR_CREDITS.md](EMULATOR_CREDITS.md) | @@ -60,7 +60,7 @@ WinNative stands on work by **brunodev85** (Winlator), **Pipetto-crypto** (Winla (Goldberg Steam Emulator), **Filippo Scognamiglio** (LibretroDroid) and the **libretro** core authors, the **ARMSX2**, **PCSX2** and **Dolphin** teams, **PancakeTAS** (lsfg-vk), **Camille LaVey** of the **Eden Emulator Project** (the Vulkan LSFG port this one derives from), -**qwertypower** of **DEVAR Entertainment LLC** (the open-source DIS engine), **OpenCV** and +**qwertypower** of **DEVAR Entertainment LLC** (the open-source OpenFlow engine), **OpenCV** and Till Kroeger (the DIS algorithm), **DXVK** (the `dxbc` translator), and **The412Banner** (DirectAudio and Steam Controller support), and the **SDL** contributors. diff --git a/app/src/main/cpp/CMakeLists.txt b/app/src/main/cpp/CMakeLists.txt index 4e68047e8..52c3caef9 100644 --- a/app/src/main/cpp/CMakeLists.txt +++ b/app/src/main/cpp/CMakeLists.txt @@ -133,8 +133,8 @@ endforeach() add_custom_target(winlator_shaders DEPENDS ${SHADER_HEADERS}) -# DIS frame generator (optical flow + interpolation), linked by libwinlator and libwnwayland. -add_subdirectory(dis) +# OpenFlow frame generator (DIS optical flow + interpolation), linked by libwinlator and libwnwayland. +add_subdirectory(openflow) # ---------------------------------------------------------------------------- # Winlator native library (X-server, AHB, Vulkan compositor, helpers) @@ -187,7 +187,7 @@ target_include_directories(winlator PRIVATE target_compile_features(winlator PRIVATE cxx_std_17) target_link_libraries(winlator - wndis + openflow log android mediandk diff --git a/app/src/main/cpp/dis/CMakeLists.txt b/app/src/main/cpp/openflow/CMakeLists.txt similarity index 67% rename from app/src/main/cpp/dis/CMakeLists.txt rename to app/src/main/cpp/openflow/CMakeLists.txt index d13b69cd2..e873a4042 100644 --- a/app/src/main/cpp/dis/CMakeLists.txt +++ b/app/src/main/cpp/openflow/CMakeLists.txt @@ -1,7 +1,7 @@ -# DIS frame generator: Dense Inverse Search optical flow and the frame interpolator built on it, -# as one static library. libwinlator (X11 compositor, standalone presenter) and libwnwayland -# (Wayland compositor) both link it; each keeps its own VkDispatch, which the objects here -# resolve against at link time. +# OpenFlow frame generator: Dense Inverse Search (DIS) optical flow and the frame interpolator +# built on it, as one static library. libwinlator (X11 compositor, standalone presenter) and +# libwnwayland (Wayland compositor) both link it; each keeps its own VkDispatch, which the objects +# here resolve against at link time. # # Layout: # include/vkr_dis.h public API @@ -50,24 +50,24 @@ foreach(base ${DIS_SHADERS}) -DVAR_NAME=${var} -P "${BIN2C_SCRIPT}" DEPENDS "${input}" "${BIN2C_SCRIPT}" - COMMENT "Compiling DIS shader ${base}.comp -> ${var}.spv.h" + COMMENT "Compiling OpenFlow shader ${base}.comp -> ${var}.spv.h" VERBATIM ) list(APPEND DIS_SHADER_HEADERS "${hdr}") endforeach() -add_custom_target(wndis_shaders DEPENDS ${DIS_SHADER_HEADERS}) +add_custom_target(openflow_shaders DEPENDS ${DIS_SHADER_HEADERS}) -add_library(wndis STATIC +add_library(openflow STATIC src/vkr_dis.c src/dis_qcom_me.c ) -add_dependencies(wndis wndis_shaders) +add_dependencies(openflow openflow_shaders) -set_target_properties(wndis PROPERTIES POSITION_INDEPENDENT_CODE ON) -target_compile_options(wndis PRIVATE -Wall -Wextra -fvisibility=hidden) -target_compile_definitions(wndis PUBLIC VK_USE_PLATFORM_ANDROID_KHR) -target_include_directories(wndis +set_target_properties(openflow PROPERTIES POSITION_INDEPENDENT_CODE ON) +target_compile_options(openflow PRIVATE -Wall -Wextra -fvisibility=hidden) +target_compile_definitions(openflow PUBLIC VK_USE_PLATFORM_ANDROID_KHR) +target_include_directories(openflow PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include # vk_dispatch.h: the public header takes its Vulkan types from there. @@ -76,4 +76,4 @@ target_include_directories(wndis ${CMAKE_CURRENT_BINARY_DIR} ) # EGL/GLES are opened with dlopen by dis_qcom_me.c, so nothing links them here. -target_link_libraries(wndis PRIVATE log dl) +target_link_libraries(openflow PRIVATE log dl) diff --git a/app/src/main/cpp/dis/include/shaders/dis_densify.comp b/app/src/main/cpp/openflow/include/shaders/dis_densify.comp similarity index 97% rename from app/src/main/cpp/dis/include/shaders/dis_densify.comp rename to app/src/main/cpp/openflow/include/shaders/dis_densify.comp index ca16f1624..a817d2f67 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_densify.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_densify.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/shaders/dis_flow_pack.comp b/app/src/main/cpp/openflow/include/shaders/dis_flow_pack.comp similarity index 95% rename from app/src/main/cpp/dis/include/shaders/dis_flow_pack.comp rename to app/src/main/cpp/openflow/include/shaders/dis_flow_pack.comp index 3922790e3..e898f8084 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_flow_pack.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_flow_pack.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/shaders/dis_gradient.comp b/app/src/main/cpp/openflow/include/shaders/dis_gradient.comp similarity index 95% rename from app/src/main/cpp/dis/include/shaders/dis_gradient.comp rename to app/src/main/cpp/openflow/include/shaders/dis_gradient.comp index 1f54ddd55..ccb332152 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_gradient.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_gradient.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/shaders/dis_hist.comp b/app/src/main/cpp/openflow/include/shaders/dis_hist.comp similarity index 97% rename from app/src/main/cpp/dis/include/shaders/dis_hist.comp rename to app/src/main/cpp/openflow/include/shaders/dis_hist.comp index 9848c0edc..b3d9c8611 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_hist.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_hist.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/shaders/dis_interpolate.comp b/app/src/main/cpp/openflow/include/shaders/dis_interpolate.comp similarity index 82% rename from app/src/main/cpp/dis/include/shaders/dis_interpolate.comp rename to app/src/main/cpp/openflow/include/shaders/dis_interpolate.comp index 717496ace..acf180fda 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_interpolate.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_interpolate.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. @@ -132,7 +132,13 @@ void main() { vec2 texel = 1.0 / vec2(size); const float GUARD_PX = 20.0; - vec2 guard = GUARD_PX * texel; + // Where content leaves the frame between the pair, its patches have nothing to match, so + // the field is unreliable in a band as wide as the motion itself - on a fast camera turn + // far wider than the fixed guard. The band grows by the motion measured well inside the + // frame, and across it the field is taken from its inner edge. + vec2 fDeep = sampleFlow(clamp(uv, vec2(0.15), vec2(0.85))); + if (any(isnan(fDeep)) || any(isinf(fDeep))) fDeep = vec2(0.0); + vec2 guard = GUARD_PX * texel + min(abs(fDeep), vec2(0.25)); vec2 dEdge = min(uv, 1.0 - uv); vec2 ramp = clamp((dEdge - guard) / max(guard, texel), 0.0, 1.0); vec2 eased = ramp * ramp * (3.0 - 2.0 * ramp); @@ -193,12 +199,15 @@ void main() { vec3 c1 = warpSample(nextColor, uv1, vec2(size)); + // How far each sample is from being inside its frame. The feather lies inside the frame: a + // sample past the edge has nothing (the fetch is clamped to the edge column), so it gets no + // weight at all, and one just inside it gives way gradually. const float FEATHER_PX = 8.0; vec2 feather = FEATHER_PX / vec2(size); - vec2 e0 = max(max(-uv0, uv0 - vec2(1.0)), vec2(0.0)) / feather; - vec2 e1 = max(max(-uv1, uv1 - vec2(1.0)), vec2(0.0)) / feather; - float out0 = clamp(max(e0.x, e0.y), 0.0, 1.0); - float out1 = clamp(max(e1.x, e1.y), 0.0, 1.0); + vec2 d0 = min(uv0, vec2(1.0) - uv0) / feather; + vec2 d1 = min(uv1, vec2(1.0) - uv1) / feather; + float out0 = 1.0 - clamp(min(d0.x, d0.y), 0.0, 1.0); + float out1 = 1.0 - clamp(min(d1.x, d1.y), 0.0, 1.0); float w0 = (1.0 - pc.t) * (1.0 - out0); float w1 = pc.t * (1.0 - out1); @@ -209,9 +218,13 @@ void main() { : (out0 <= out1 ? c0 : c1); // Where the two warped samples agree, occl is exactly zero and so is its effect on the result; - // the side map is only fetched where it can matter. + // the side map is only fetched where it can matter. A sample from outside its frame is not + // evidence of an occlusion: comparing against it would call the frame edge one and hand the + // pixel to exactly the sample that is off-frame. There the in-frame sample above already + // stands alone. + float bothIn = (1.0 - out0) * (1.0 - out1); float rMotion = dot(abs(c0 - c1), vec3(1.0)); - float occl = smoothstep(OCCL_LO, OCCL_HI, rMotion); + float occl = smoothstep(OCCL_LO, OCCL_HI, rMotion * bothIn); if (occl > 0.0) { vec3 single = pc.t < 0.5 ? c0 : c1; #if DIS_OCCL_SIDED @@ -238,8 +251,12 @@ void main() { if (stillWins > 0.0) { float keep = (1.0 - smoothstep(0.03, 0.12, rStatic)) * stillWins; #if DIS_USE_HIST + // Not where a sample is off-frame: there rMotion measures the frame edge, not the + // pixel, so stillWins says nothing, and the history would pin moving scenery along the + // edge as a blend of the pair - the doubled band on a camera turn. An overlay there is + // still kept by the per-pixel test above. float histStatic = textureLod(histTex, uv, 0.0).r; - keep = max(keep, histStatic * stillWins); + keep = max(keep, histStatic * stillWins * bothIn); #endif result = mix(result, mix(s0, s1, pc.t), keep); } diff --git a/app/src/main/cpp/dis/include/shaders/dis_inverse_search.comp b/app/src/main/cpp/openflow/include/shaders/dis_inverse_search.comp similarity index 69% rename from app/src/main/cpp/dis/include/shaders/dis_inverse_search.comp rename to app/src/main/cpp/openflow/include/shaders/dis_inverse_search.comp index ef47be259..c4e364fe3 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_inverse_search.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_inverse_search.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. @@ -55,6 +55,21 @@ precision highp int; // there is nothing for the test to change; skip its 64 samples. #define DIS_ZERO_TEST_MIN_PX 0.5 +// Gauss-Newton only converges within a few texels of where it starts, and a move of more than a +// patch is thrown out, so starting the coarsest level from zero caps the motion the whole +// pyramid can follow - at 180p flow, somewhere between 100 and 190 px per frame at 1280x720, +// which a fast camera turn exceeds. The coarsest level is tiny (40x22 texels at 180p), so there +// the displacements within the radius are block-matched first, every second one and on every +// second texel of the patch, and Gauss-Newton refines the best from there. The bias, per sample +// and squared texel of displacement, makes a flat block that matches anywhere keep the smallest +// move. +#define DIS_COARSE_SEARCH_RADIUS 12 +#define DIS_COARSE_SEARCH_BIAS 1.0 + +// Below this distance, in texels, from the vector a level would start from, the previous pair's +// vector is the same start and is not scored again. +#define DIS_PRIOR_MIN_PX 0.5 + layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; layout(set = 0, binding = 0) uniform sampler2D lastLumaMap; @@ -66,11 +81,15 @@ layout(set = 0, binding = 3) uniform sampler2D flowMap; // marks a block the estimator had nothing for. layout(set = 0, binding = 4) uniform sampler2D hintFlowMap; layout(set = 0, binding = 5, rgba32f) uniform image2D sparseFlowMap; +// The previous pair's final flow, in normalised uv units, indexed by position in its first frame; +// read on the levels whose bit is set in priorLevels. +layout(set = 0, binding = 6) uniform sampler2D priorFlowMap; layout(push_constant) uniform PC { int level; int coarseLevel; int hintLevel; + int priorLevels; } pc; #define HINT_INVALID 1.0e6 @@ -102,6 +121,23 @@ shared vec2 sGrad[TILE * TILE]; #define REF(i, j) sLuma[(lp.y + (j)) * TILE + lp.x + (i)] #define GRAD(i, j) sGrad[(lp.y + (j)) * TILE + lp.x + (i)] +// Mean-normalised SSD of the patch at pix displaced by f (texels), the metric the search minimises. +float patchSSD(vec2 f, ivec2 pix, ivec2 lp, ivec2 denseSize) { + vec2 invImageSize = 1.0 / vec2(denseSize); + vec2 o = clamp(vec2(pix) + f, vec2(0.0), vec2(denseSize) - 8.0); + float s = 0.0; + float s2 = 0.0; + for (int i = 0; i < 8; i++) { + for (int j = 0; j < 8; j++) { + vec2 tc = (o + vec2(i, j) + 0.5) * invImageSize; + float diff = textureLod(nextLumaMap, tc, 0.0).x - REF(i, j); + s += diff; + s2 += diff * diff; + } + } + return s2 - s * s / 64.0; +} + void main() { const float patchSize = 8.0; @@ -146,6 +182,28 @@ void main() { vec2 flow; if (pc.level == pc.coarseLevel) { flow = vec2(0.0); + float bestCost = 1e30; + ivec2 maxOrigin = denseSize - ivec2(8); + for (int dy = -DIS_COARSE_SEARCH_RADIUS; dy <= DIS_COARSE_SEARCH_RADIUS; dy += 2) { + for (int dx = -DIS_COARSE_SEARCH_RADIUS; dx <= DIS_COARSE_SEARCH_RADIUS; dx += 2) { + ivec2 o = pix + ivec2(dx, dy); + if (any(lessThan(o, ivec2(0))) || any(greaterThan(o, maxOrigin))) continue; + float s = 0.0; + float s2 = 0.0; + for (int i = 0; i < 8; i += 2) { + for (int j = 0; j < 8; j += 2) { + float diff = texelFetch(nextLumaMap, o + ivec2(i, j), 0).x - REF(i, j); + s += diff; + s2 += diff * diff; + } + } + float cost = s2 - s * s / 16.0 + DIS_COARSE_SEARCH_BIAS * 16.0 * float(dx * dx + dy * dy); + if (cost < bestCost) { + bestCost = cost; + flow = vec2(dx, dy); + } + } + } } else { ivec2 fmMax = textureSize(flowMap, 0) - 1; vec4 cf = texelFetch(flowMap, clamp(ivec2(pix / 2) + 2, ivec2(0), fmMax), 0); @@ -155,10 +213,12 @@ void main() { vec2 invImageSize = 1.0 / vec2(denseSize); const float N = 64.0; - // A second starting point from the hardware estimator. Both candidates are scored on the - // patch with the same mean-normalised SSD the search minimises, and the search starts from - // the better one. The coarse level still covers what the estimator cannot: its search range - // is a few dozen pixels, and past that its vector is garbage that simply loses here. + // Further starting points, each scored on the patch with the same mean-normalised SSD the + // search minimises; the search starts from the best. A wrong candidate simply loses here. + float startSSD = -1.0; + + // The hardware estimator's vector. The coarse level still covers what the estimator cannot: + // its search range is a few dozen pixels, and past that its vector is garbage. if (pc.level == pc.hintLevel) { vec2 hintSize = vec2(textureSize(hintFlowMap, 0)); ivec2 hp = clamp(ivec2((vec2(pix) + 4.0) * hintSize / vec2(denseSize)), @@ -166,25 +226,30 @@ void main() { vec2 hint = texelFetch(hintFlowMap, hp, 0).xy; if (all(lessThan(abs(hint), vec2(HINT_INVALID * 0.5)))) { hint *= vec2(denseSize); - vec2 cand[2] = vec2[2](flow, hint); - float best = 1e30; - for (int c = 0; c < 2; c++) { - vec2 o = clamp(vec2(pix) + cand[c], vec2(0.0), vec2(denseSize) - patchSize); - float s = 0.0; - float s2 = 0.0; - for (int i = 0; i < 8; i++) { - for (int j = 0; j < 8; j++) { - vec2 tc = (o + vec2(i, j) + 0.5) * invImageSize; - float diff = textureLod(nextLumaMap, tc, 0.0).x - REF(i, j); - s += diff; - s2 += diff * diff; - } - } - float ssd = s2 - s * s / N; - if (ssd < best) { - best = ssd; - flow = cand[c]; - } + startSSD = patchSSD(flow, pix, lp, denseSize); + float hintSSD = patchSSD(hint, pix, lp, denseSize); + if (hintSSD < startSSD) { + startSSD = hintSSD; + flow = hint; + } + } + } + + // The previous pair's vector: motion goes on. It is what follows an object too small or too + // fast for the coarse levels to see - there it is lost in the background - and a periodic + // texture that the refinement from the coarse vector would lock onto a period off. The field + // is indexed by position in the previous pair's first frame, where this patch's content was + // one vector ago, so it is looked up there (one fixed-point step from the patch centre). + if ((pc.priorLevels & (1 << pc.level)) != 0) { + vec2 c = (vec2(pix) + 4.0) * invImageSize; + vec2 p = textureLod(priorFlowMap, c, 0.0).xy; + p = textureLod(priorFlowMap, c - p, 0.0).xy * vec2(denseSize); + if (!any(isnan(p)) && !any(isinf(p)) && distance(p, flow) > DIS_PRIOR_MIN_PX) { + if (startSSD < 0.0) startSSD = patchSSD(flow, pix, lp, denseSize); + float priorSSD = patchSSD(p, pix, lp, denseSize); + if (priorSSD < startSSD) { + startSSD = priorSSD; + flow = p; } } } diff --git a/app/src/main/cpp/dis/include/shaders/dis_luma.comp b/app/src/main/cpp/openflow/include/shaders/dis_luma.comp similarity index 91% rename from app/src/main/cpp/dis/include/shaders/dis_luma.comp rename to app/src/main/cpp/openflow/include/shaders/dis_luma.comp index e3d7b9487..eaa8a7a82 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_luma.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_luma.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/shaders/dis_luma_r16.comp b/app/src/main/cpp/openflow/include/shaders/dis_luma_r16.comp similarity index 91% rename from app/src/main/cpp/dis/include/shaders/dis_luma_r16.comp rename to app/src/main/cpp/openflow/include/shaders/dis_luma_r16.comp index c268438d0..b7cf1171b 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_luma_r16.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_luma_r16.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/shaders/dis_luma_r32.comp b/app/src/main/cpp/openflow/include/shaders/dis_luma_r32.comp similarity index 91% rename from app/src/main/cpp/dis/include/shaders/dis_luma_r32.comp rename to app/src/main/cpp/openflow/include/shaders/dis_luma_r32.comp index f8bc8c3b9..99a4e99ed 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_luma_r32.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_luma_r32.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/shaders/dis_me_luma.comp b/app/src/main/cpp/openflow/include/shaders/dis_me_luma.comp similarity index 95% rename from app/src/main/cpp/dis/include/shaders/dis_me_luma.comp rename to app/src/main/cpp/openflow/include/shaders/dis_me_luma.comp index 72d0dd1be..bde5d953b 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_me_luma.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_me_luma.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/shaders/dis_propagate.comp b/app/src/main/cpp/openflow/include/shaders/dis_propagate.comp similarity index 97% rename from app/src/main/cpp/dis/include/shaders/dis_propagate.comp rename to app/src/main/cpp/openflow/include/shaders/dis_propagate.comp index 9b79bfdba..61afb39e6 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_propagate.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_propagate.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/shaders/dis_side.comp b/app/src/main/cpp/openflow/include/shaders/dis_side.comp similarity index 96% rename from app/src/main/cpp/dis/include/shaders/dis_side.comp rename to app/src/main/cpp/openflow/include/shaders/dis_side.comp index 455447ebd..7ceda0613 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_side.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_side.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/shaders/dis_vr_add.comp b/app/src/main/cpp/openflow/include/shaders/dis_vr_add.comp similarity index 96% rename from app/src/main/cpp/dis/include/shaders/dis_vr_add.comp rename to app/src/main/cpp/openflow/include/shaders/dis_vr_add.comp index 91baecf4f..7d61aa97a 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_vr_add.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_vr_add.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/shaders/dis_vr_coef.comp b/app/src/main/cpp/openflow/include/shaders/dis_vr_coef.comp similarity index 97% rename from app/src/main/cpp/dis/include/shaders/dis_vr_coef.comp rename to app/src/main/cpp/openflow/include/shaders/dis_vr_coef.comp index f1aa63f57..0d9ff74fe 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_vr_coef.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_vr_coef.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/shaders/dis_vr_d1.comp b/app/src/main/cpp/openflow/include/shaders/dis_vr_d1.comp similarity index 93% rename from app/src/main/cpp/dis/include/shaders/dis_vr_d1.comp rename to app/src/main/cpp/openflow/include/shaders/dis_vr_d1.comp index 3031b5ded..2ee2cce31 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_vr_d1.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_vr_d1.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/shaders/dis_vr_d2.comp b/app/src/main/cpp/openflow/include/shaders/dis_vr_d2.comp similarity index 92% rename from app/src/main/cpp/dis/include/shaders/dis_vr_d2.comp rename to app/src/main/cpp/openflow/include/shaders/dis_vr_d2.comp index 45d7804b2..81ea494e8 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_vr_d2.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_vr_d2.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/shaders/dis_vr_prep.comp b/app/src/main/cpp/openflow/include/shaders/dis_vr_prep.comp similarity index 93% rename from app/src/main/cpp/dis/include/shaders/dis_vr_prep.comp rename to app/src/main/cpp/openflow/include/shaders/dis_vr_prep.comp index 7d64a0885..b1d424963 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_vr_prep.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_vr_prep.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/shaders/dis_vr_sor.comp b/app/src/main/cpp/openflow/include/shaders/dis_vr_sor.comp similarity index 96% rename from app/src/main/cpp/dis/include/shaders/dis_vr_sor.comp rename to app/src/main/cpp/openflow/include/shaders/dis_vr_sor.comp index d17ccd509..a892c059a 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_vr_sor.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_vr_sor.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/shaders/dis_vr_w.comp b/app/src/main/cpp/openflow/include/shaders/dis_vr_w.comp similarity index 94% rename from app/src/main/cpp/dis/include/shaders/dis_vr_w.comp rename to app/src/main/cpp/openflow/include/shaders/dis_vr_w.comp index b0536292e..a8a9744a3 100644 --- a/app/src/main/cpp/dis/include/shaders/dis_vr_w.comp +++ b/app/src/main/cpp/openflow/include/shaders/dis_vr_w.comp @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/include/vkr_dis.h b/app/src/main/cpp/openflow/include/vkr_dis.h similarity index 97% rename from app/src/main/cpp/dis/include/vkr_dis.h rename to app/src/main/cpp/openflow/include/vkr_dis.h index 3434aab7f..074763034 100644 --- a/app/src/main/cpp/dis/include/vkr_dis.h +++ b/app/src/main/cpp/openflow/include/vkr_dis.h @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. diff --git a/app/src/main/cpp/dis/src/dis_qcom_me.c b/app/src/main/cpp/openflow/src/dis_qcom_me.c similarity index 98% rename from app/src/main/cpp/dis/src/dis_qcom_me.c rename to app/src/main/cpp/openflow/src/dis_qcom_me.c index 51d9bc803..e7c0b31bb 100644 --- a/app/src/main/cpp/dis/src/dis_qcom_me.c +++ b/app/src/main/cpp/openflow/src/dis_qcom_me.c @@ -24,8 +24,8 @@ #include #include -#define ME_LOGI(...) __android_log_print(ANDROID_LOG_INFO, "VkrDis", __VA_ARGS__) -#define ME_LOGW(...) __android_log_print(ANDROID_LOG_WARN, "VkrDis", __VA_ARGS__) +#define ME_LOGI(...) __android_log_print(ANDROID_LOG_INFO, "OpenFlow", __VA_ARGS__) +#define ME_LOGW(...) __android_log_print(ANDROID_LOG_WARN, "OpenFlow", __VA_ARGS__) #define GL_MOTION_ESTIMATION_SEARCH_BLOCK_X_QCOM 0x8C90 #define GL_MOTION_ESTIMATION_SEARCH_BLOCK_Y_QCOM 0x8C91 diff --git a/app/src/main/cpp/dis/src/dis_qcom_me.h b/app/src/main/cpp/openflow/src/dis_qcom_me.h similarity index 100% rename from app/src/main/cpp/dis/src/dis_qcom_me.h rename to app/src/main/cpp/openflow/src/dis_qcom_me.h diff --git a/app/src/main/cpp/dis/src/vkr_dis.c b/app/src/main/cpp/openflow/src/vkr_dis.c similarity index 97% rename from app/src/main/cpp/dis/src/vkr_dis.c rename to app/src/main/cpp/openflow/src/vkr_dis.c index b745bf8e4..b2e3088c0 100644 --- a/app/src/main/cpp/dis/src/vkr_dis.c +++ b/app/src/main/cpp/openflow/src/vkr_dis.c @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2026 qwertypower (DEVAR Entertainment LLC) // SPDX-License-Identifier: GPL-3.0-or-later // -// DIS frame generation: a Vulkan compute realisation of Dense Inverse Search +// OpenFlow frame generation: a Vulkan compute realisation of Dense Inverse Search // optical flow. The algorithm and its reference implementation come from // OpenCV's DISOpticalFlow, which adopted Till Kroeger's original OF_DIS. // See CREDITS.md for the full attribution. @@ -40,8 +40,8 @@ #include #endif -#define DIS_LOGI(...) __android_log_print(ANDROID_LOG_INFO, "VkrDis", __VA_ARGS__) -#define DIS_LOGW(...) __android_log_print(ANDROID_LOG_WARN, "VkrDis", __VA_ARGS__) +#define DIS_LOGI(...) __android_log_print(ANDROID_LOG_INFO, "OpenFlow", __VA_ARGS__) +#define DIS_LOGW(...) __android_log_print(ANDROID_LOG_WARN, "OpenFlow", __VA_ARGS__) #define DIS_LOCAL_SIZE 8u #define DIS_PATCH_STRIDE 3u @@ -97,7 +97,7 @@ #define DIS_VR_LEVELS 8u -#define DIS_SET_SAMPLERS 5u +#define DIS_SET_SAMPLERS 6u #define DIS_SET_STORAGE 1u #define DIS_SHARED_SETS_PER_LEVEL 6u #define DIS_VR_SHARED_SETS 7u @@ -258,6 +258,9 @@ struct VkrDis { uint32_t hist_parity; bool hist_valid; + // flow_out holds the flow of the pair just before the one being computed, so the search can + // start from it; false after a reset, a rebuild or a frame whose flow was not computed. + bool prior_valid; // Hardware motion hint (GL_QCOM_motion_estimation). me is NULL whenever the hint is off: // disabled, unsupported, or the pyramid too shallow for the level it seeds. @@ -295,6 +298,7 @@ typedef struct { int level; int coarseLevel; int hintLevel; + int priorLevels; } DisInversePC; typedef struct { @@ -642,23 +646,21 @@ static VkPipeline dis_create_compute_pipeline(VkrDis* d, const uint32_t* code, s } static bool dis_create_pipelines(VkrDis* d) { - VkDescriptorSetLayoutBinding bindings[6]; + // Samplers at 0-4 and 6 (6 is only the search's previous-pair flow), the storage image at 5. + VkDescriptorSetLayoutBinding bindings[7]; memset(bindings, 0, sizeof(bindings)); - for (uint32_t i = 0; i < 5; i++) { + for (uint32_t i = 0; i < 7; i++) { bindings[i].binding = i; - bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bindings[i].descriptorType = i == 5 ? VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + : VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; bindings[i].descriptorCount = 1; bindings[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; } - bindings[5].binding = 5; - bindings[5].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - bindings[5].descriptorCount = 1; - bindings[5].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT; VkDescriptorSetLayoutCreateInfo li; memset(&li, 0, sizeof(li)); li.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - li.bindingCount = 6; + li.bindingCount = 7; li.pBindings = bindings; if (vkd.CreateDescriptorSetLayout(d->device, &li, NULL, &d->set_layout) != VK_SUCCESS) { return false; @@ -992,6 +994,7 @@ static void dis_write_all_descriptors(VkrDis* d) { dis_batch_sampled(d, &b, d->inverse_sets[s][l], 3, coarse_view, d->sampler); dis_batch_sampled(d, &b, d->inverse_sets[s][l], 4, d->view_me_field, d->sampler); dis_batch_storage(d, &b, d->inverse_sets[s][l], 5, d->view_sparse[l]); + dis_batch_sampled(d, &b, d->inverse_sets[s][l], 6, d->view_flow_out, d->sampler); dis_batch_sampled(d, &b, d->prop_ab_sets[s][l], 0, d->view_flow_luma[prev][l], d->sampler); dis_batch_sampled(d, &b, d->prop_ab_sets[s][l], 1, d->view_flow_luma[next][l], d->sampler); @@ -1219,7 +1222,7 @@ static void dis_create_me(VkrDis* d, uint32_t w, uint32_t h) { !dis_create_host_buffer(d, field_bytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, false, &d->me_field_buf, &d->me_field_mem, &d->me_field_map, &d->me_field_coherent)) { - DIS_LOGW("DIS hardware motion: host buffers unavailable; using DIS alone"); + DIS_LOGW("OpenFlow hardware motion: host buffers unavailable; using OpenFlow alone"); dis_destroy_me(d); return; } @@ -1256,7 +1259,7 @@ static void dis_create_me(VkrDis* d, uint32_t w, uint32_t h) { w2[1].pBufferInfo = &bi; vkd.UpdateDescriptorSets(d->device, 2, w2, 0, NULL); } - DIS_LOGI("DIS hardware motion hint: GL_QCOM_motion_estimation on %ux%u seeds level %u (%ux%u)", + DIS_LOGI("OpenFlow hardware motion hint: GL_QCOM_motion_estimation on %ux%u seeds level %u (%ux%u)", d->me_w, d->me_h, d->me_level, d->me_field_w, d->me_field_h); } @@ -1383,7 +1386,7 @@ static bool dis_alloc(VkrDis* d, VkDescriptorSetLayout layout, uint32_t count, ai.pSetLayouts = layouts; const VkResult res = vkd.AllocateDescriptorSets(d->device, &ai, out); if (res != VK_SUCCESS) { - DIS_LOGW("DIS descriptor allocation failed (%d) asking for %u sets", (int)res, count); + DIS_LOGW("OpenFlow descriptor allocation failed (%d) asking for %u sets", (int)res, count); return false; } return true; @@ -1526,7 +1529,7 @@ static bool dis_audit_formats(VkrDis* d) { const VkFormatFeatureFlags FILTER = VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT; if (d->luma_format == VK_FORMAT_UNDEFINED) { - DIS_LOGW("DIS needs a single-channel float plane it can both write and filter; " + DIS_LOGW("OpenFlow needs a single-channel float plane it can both write and filter; " "neither R16_SFLOAT nor R32_SFLOAT qualifies on this device"); return false; } @@ -1563,7 +1566,7 @@ static bool dis_audit_formats(VkrDis* d) { if (missing) { char names[256]; dis_missing_features(missing, names, sizeof(names)); - DIS_LOGW("DIS needs %s on %s for %s, and this device does not report it", + DIS_LOGW("OpenFlow needs %s on %s for %s, and this device does not report it", names, dis_format_name(reqs[i].format), reqs[i].purpose); ok = false; } @@ -1574,7 +1577,7 @@ static bool dis_audit_formats(VkrDis* d) { vkd.GetPhysicalDeviceFormatProperties(d->physical_device, VK_FORMAT_R16G16_SFLOAT, &flow_fp); d->manual_flow_filter = (flow_fp.optimalTilingFeatures & FILTER) == 0; - DIS_LOGI("DIS format support: %s | flow filtering: %s", line, + DIS_LOGI("OpenFlow format support: %s | flow filtering: %s", line, d->manual_flow_filter ? "in shader (driver cannot filter R16G16_SFLOAT)" : "sampler"); return ok; @@ -1598,29 +1601,29 @@ VkrDis* vkr_dis_create(VkDevice device, VkPhysicalDevice physical_device) { char prop[PROP_VALUE_MAX] = {0}; if (__system_property_get("debug.winnative.dis.hwme", prop) > 0 && prop[0] == '1') { d->hw_motion = true; - DIS_LOGI("DIS hardware motion hint enabled by debug.winnative.dis.hwme"); + DIS_LOGI("OpenFlow hardware motion hint enabled by debug.winnative.dis.hwme"); } #endif d->hint_level = -1; vkd.GetPhysicalDeviceMemoryProperties(physical_device, &d->mem_props); d->luma_format = dis_pick_luma_format(d); if (!dis_audit_formats(d)) { - DIS_LOGW("DIS cannot run on this device's format support; frame generation stays off"); + DIS_LOGW("OpenFlow cannot run on this device's format support; frame generation stays off"); vkr_dis_destroy(d); return NULL; } if (!dis_create_sampler(d) || !dis_create_pipelines(d)) { - DIS_LOGW("DIS shaders could not be built; frame generation stays off"); + DIS_LOGW("OpenFlow shaders could not be built; frame generation stays off"); vkr_dis_destroy(d); return NULL; } if (!dis_allocate_sets(d)) { - DIS_LOGW("DIS descriptor sets could not be allocated; frame generation stays off"); + DIS_LOGW("OpenFlow descriptor sets could not be allocated; frame generation stays off"); vkr_dis_destroy(d); return NULL; } - DIS_LOGI("DIS frame generation ready"); + DIS_LOGI("OpenFlow frame generation ready"); return d; } @@ -1725,7 +1728,7 @@ bool vkr_dis_prepare(VkrDis* d, uint32_t width, uint32_t height, VkFormat format if (missing) { char names[256]; dis_missing_features(missing, names, sizeof(names)); - DIS_LOGW("DIS needs %s on the guest frame format (%d) and this device does not " + DIS_LOGW("OpenFlow needs %s on the guest frame format (%d) and this device does not " "report it; frame generation stays off", names, (int)format); d->unavailable = true; return false; @@ -1735,7 +1738,7 @@ bool vkr_dis_prepare(VkrDis* d, uint32_t width, uint32_t height, VkFormat format d->levels = levels; if (!dis_create_resources(d, w, h, content.width, content.height, format)) { - DIS_LOGW("DIS resource build failed at %ux%u; frame generation unavailable", w, h); + DIS_LOGW("OpenFlow resource build failed at %ux%u; frame generation unavailable", w, h); dis_destroy_images(d); d->unavailable = true; return false; @@ -1749,11 +1752,12 @@ bool vkr_dis_prepare(VkrDis* d, uint32_t width, uint32_t height, VkFormat format d->built_min_side = d->flow_min_side; d->built = true; d->frame_count = 0; + d->prior_valid = false; d->prev_idx = 0; d->next_idx = 0; d->active_slot = 0; d->last_generations = 0; - DIS_LOGI("DIS resources built at %ux%u (flow min side %u, %u levels); content rect " + DIS_LOGI("OpenFlow resources built at %ux%u (flow min side %u, %u levels); content rect " "%dx%d+%d+%d inside a %ux%u composite", w, h, d->flow_min_side, levels, (int)content.width, (int)content.height, (int)content.x, (int)content.y, width, height); @@ -1810,7 +1814,7 @@ static void dis_log_plan(VkrDis* d, uint64_t now, float source_rate, float desir if (d->planned_gen == d->plan_log_gen && now - d->plan_log_ns < DIS_PLAN_LOG_NS) return; d->plan_log_gen = d->planned_gen; d->plan_log_ns = now; - DIS_LOGI("DIS plan: source %.1f fps, target %.1f fps, ratio %.2f -> %d generated " + DIS_LOGI("OpenFlow plan: source %.1f fps, target %.1f fps, ratio %.2f -> %d generated " "(capacity %u, output %.1f fps)", (double)source_rate, (double)desired, (double)ratio, d->planned_gen, capacity, (double)(source_rate * (float)(d->planned_gen + 1))); @@ -2133,7 +2137,7 @@ static VkCommandBuffer dis_hardware_motion(VkrDis* d, VkCommandBuffer cmd, uint3 } d->me_hinted++; if ((d->me_hinted % 600u) == 1u) { - DIS_LOGI("DIS hardware motion hint: %llu of %llu pairs seeded", + DIS_LOGI("OpenFlow hardware motion hint: %llu of %llu pairs seeded", (unsigned long long)d->me_hinted, (unsigned long long)d->me_pairs); } return cmd; @@ -2216,7 +2220,10 @@ VkCommandBuffer vkr_dis_process_ex(VkrDis* d, VkCommandBuffer cmd, VkImage sourc dis_compute_barrier(cmd); DIS_PROF(cmd, "copy+luma"); - if (!wants_flow) return cmd; + if (!wants_flow) { + d->prior_valid = false; + return cmd; + } DisGradientPC gpc; gpc.lesser = 3.0f; gpc.upper = 10.0f; @@ -2254,6 +2261,7 @@ VkCommandBuffer vkr_dis_process_ex(VkrDis* d, VkCommandBuffer cmd, VkImage sourc ipc.level = (int)l; ipc.coarseLevel = (int)coarse; ipc.hintLevel = d->hint_level; + ipc.priorLevels = d->prior_valid ? (int)((1u << L) - 1u) : 0; vkd.CmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, d->pass_inverse.pipeline); vkd.CmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, d->pipeline_layout, 0, 1, &d->inverse_sets[slot][l], 0, NULL); @@ -2306,6 +2314,7 @@ VkCommandBuffer vkr_dis_process_ex(VkrDis* d, VkCommandBuffer cmd, VkImage sourc // other - the packed field and the side map read the refined field, the overlay // history reads the colour pair - so they share one barrier. dis_dispatch(d, cmd, d->pass_pack.pipeline, d->pack_set, w, h); + d->prior_valid = true; vkd.CmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, d->pass_hist.pipeline); vkd.CmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_COMPUTE, d->vr_pipeline_layout, 0, 1, @@ -2457,6 +2466,7 @@ void vkr_dis_reset(VkrDis* d) { d->plan_log_ns = 0; d->hist_parity = 0; d->hist_valid = false; + d->prior_valid = false; d->hint_level = -1; if (d->me) dis_qcom_me_invalidate(d->me); } diff --git a/app/src/main/cpp/waylandcomp/CMakeLists.txt b/app/src/main/cpp/waylandcomp/CMakeLists.txt index e6f1d691c..8d30d73b0 100644 --- a/app/src/main/cpp/waylandcomp/CMakeLists.txt +++ b/app/src/main/cpp/waylandcomp/CMakeLists.txt @@ -43,11 +43,11 @@ target_include_directories(wnwayland PRIVATE ) # The X11 renderer's frame-generation engines run here too, on the compositor's own Turnip -# device. LSFG is compiled in and DIS comes from the wndis static library rather than being linked +# device. LSFG is compiled in and OpenFlow comes from its static library rather than being linked # from libwinlator: both libraries keep a private VkDispatch, so the visibility below must stay for # the two copies not to merge. set(FRAMEGEN_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../winlator/vk) -if (TARGET dxbc AND TARGET wndis) +if (TARGET dxbc AND TARGET openflow) target_sources(wnwayland PRIVATE src/framegen_engine.c ${FRAMEGEN_DIR}/vk_dispatch.c @@ -69,7 +69,7 @@ if (TARGET dxbc AND TARGET wndis) target_compile_definitions(wnwayland PRIVATE VK_USE_PLATFORM_ANDROID_KHR) target_compile_options(wnwayland PRIVATE -fvisibility=hidden) target_compile_features(wnwayland PRIVATE cxx_std_17) - target_link_libraries(wnwayland dxbc wndis) + target_link_libraries(wnwayland dxbc openflow) add_dependencies(wnwayland winlator_shaders) else() target_sources(wnwayland PRIVATE src/framegen_engine_stub.c) diff --git a/app/src/main/cpp/waylandcomp/src/framegen_bridge.c b/app/src/main/cpp/waylandcomp/src/framegen_bridge.c index d8afb1fc3..0c3f967c4 100644 --- a/app/src/main/cpp/waylandcomp/src/framegen_bridge.c +++ b/app/src/main/cpp/waylandcomp/src/framegen_bridge.c @@ -192,7 +192,7 @@ void vkp_framegen_device_ready(VkDevice dev, VkQueue queue, uint32_t qfam, int f g_vk.GetPhysicalDeviceMemoryProperties(g_pd, &g_memprops); fge_device_ready(g_gipa, g_inst, g_pd, dev, queue, qfam, features_enabled); g_dev_ready = vk.CreateImage && vk.CreateImageView && vk.CmdPipelineBarrier; - FGLOG("engines ready on the compositor's device: LSFG Native %s (%s), DIS Native %s", + FGLOG("engines ready on the compositor's device: LSFG Native %s (%s), OpenFlow Native %s", fge_caps_ok(VKP_FG_ENGINE_LSFG) ? "available" : "unavailable", fge_caps_reason(), fge_caps_ok(VKP_FG_ENGINE_DIS) ? "available" : "unavailable"); } diff --git a/app/src/main/cpp/waylandcomp/src/framegen_engine.c b/app/src/main/cpp/waylandcomp/src/framegen_engine.c index 5573bf09c..325745953 100644 --- a/app/src/main/cpp/waylandcomp/src/framegen_engine.c +++ b/app/src/main/cpp/waylandcomp/src/framegen_engine.c @@ -214,7 +214,7 @@ void fge_telemetry(float *accepted, float *source_rate, float *thermal) { } const char *fge_engine_name(int kind) { - return kind == VKP_FG_ENGINE_DIS ? "DIS Native" : "LSFG Native"; + return kind == VKP_FG_ENGINE_DIS ? "OpenFlow Native" : "LSFG Native"; } const char *fge_build_info(void) { return "lsfg-native/dis-native"; } diff --git a/app/src/main/cpp/waylandcomp/src/framegen_engine_stub.c b/app/src/main/cpp/waylandcomp/src/framegen_engine_stub.c index 8a0074e8a..8c687a36a 100644 --- a/app/src/main/cpp/waylandcomp/src/framegen_engine_stub.c +++ b/app/src/main/cpp/waylandcomp/src/framegen_engine_stub.c @@ -36,5 +36,5 @@ void fge_forget_targets(void) {} void fge_telemetry(float *accepted, float *source_rate, float *thermal) { *accepted = 0.0f; *source_rate = 0.0f; *thermal = -1.0f; } -const char *fge_engine_name(int kind) { return kind == 1 ? "DIS Native" : "LSFG Native"; } +const char *fge_engine_name(int kind) { return kind == 1 ? "OpenFlow Native" : "LSFG Native"; } const char *fge_build_info(void) { return "stub"; } diff --git a/app/src/main/cpp/waylandcomp/src/vk_present.c b/app/src/main/cpp/waylandcomp/src/vk_present.c index be09b3ad6..98d910f2c 100644 --- a/app/src/main/cpp/waylandcomp/src/vk_present.c +++ b/app/src/main/cpp/waylandcomp/src/vk_present.c @@ -479,7 +479,7 @@ static int dev_init(void) { .queueFamilyIndex = g_qfam, .queueCount = 1, .pQueuePriorities = &prio}; /* Frame generation (framegen_bridge.c): the LSFG chain needs the memory-model and * storage-image features enabled at device creation; the probe hands back the pNext chain - * for them, or NULL on a device that cannot run it (then DIS Native alone is offered). A + * for them, or NULL on a device that cannot run it (then OpenFlow Native alone is offered). A * driver that rejects the chain costs nothing: retried once without it, exactly as before. */ const void *fg_features = vkp_framegen_device_features(g_inst, vk_loader_gipa(), g_pd); VkDeviceCreateInfo dci = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, .pNext = fg_features, diff --git a/app/src/main/cpp/winlator/vk/framegen/fg_present.c b/app/src/main/cpp/winlator/vk/framegen/fg_present.c index a563f00f5..1607c5d67 100644 --- a/app/src/main/cpp/winlator/vk/framegen/fg_present.c +++ b/app/src/main/cpp/winlator/vk/framegen/fg_present.c @@ -737,7 +737,7 @@ static bool fg_engine_acquire(FgPresenter* fg) { if (fg->dis) return true; fg->dis = vkr_dis_create(fg->device, fg->physical_device); if (!fg->dis) { - FG_LOGW("DIS optical flow is unavailable on this device"); + FG_LOGW("OpenFlow optical flow is unavailable on this device"); return false; } return true; @@ -756,7 +756,7 @@ static bool fg_engine_ready(const FgPresenter* fg) { } static const char* fg_engine_name(uint32_t engine) { - return engine == FG_ENGINE_DIS ? "DIS" : "LSFG"; + return engine == FG_ENGINE_DIS ? "OpenFlow" : "LSFG"; } static void fg_apply_config(FgPresenter* fg) { @@ -822,7 +822,7 @@ static VkCommandBuffer fg_dis_flush(void* user, VkCommandBuffer cmd) { if (vkQueueSubmit(fg->queue, 1, &si, fg->flush_fence) == VK_SUCCESS) { vkWaitForFences(fg->device, 1, &fg->flush_fence, VK_TRUE, UINT64_MAX); } else { - FG_LOGW("DIS mid-frame submit failed"); + FG_LOGW("OpenFlow mid-frame submit failed"); vkDeviceWaitIdle(fg->device); } vkResetCommandBuffer(cmd, 0); diff --git a/app/src/main/cpp/winlator/vk/vk_renderer.c b/app/src/main/cpp/winlator/vk/vk_renderer.c index 956c5a392..d1b79816f 100644 --- a/app/src/main/cpp/winlator/vk/vk_renderer.c +++ b/app/src/main/cpp/winlator/vk/vk_renderer.c @@ -1960,7 +1960,7 @@ static VkCommandBuffer dis_flush_frame(void* user, VkCommandBuffer cmd) { if (sr == VK_SUCCESS && r->dis_flush_fence) { vkWaitForFences(r->device, 1, &r->dis_flush_fence, VK_TRUE, UINT64_MAX); } else if (sr != VK_SUCCESS) { - VK_LOGW("DIS mid-frame submit -> %d", (int)sr); + VK_LOGW("OpenFlow mid-frame submit -> %d", (int)sr); } vkResetCommandBuffer(cmd, 0); VkCommandBufferBeginInfo bi = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO}; @@ -1974,7 +1974,7 @@ static void create_dis(VkRenderer* r) { r->dis = vkr_dis_create(r->device, r->physical_device); if (!r->dis) { - VK_LOGW("DIS shaders unavailable; frame generation stays off"); + VK_LOGW("OpenFlow shaders unavailable; frame generation stays off"); return; } vkr_dis_configure(r->dis, r->dis_scale ? r->dis_scale : 180u, r->dis_target_fps, @@ -3979,7 +3979,7 @@ JNIEXPORT void JNICALL JNI_FN(nativeSetDisFrameGenerationEnabled)(JNIEnv* env, j } framegen_rebuild_swapchain(r); pthread_mutex_unlock(&r->render_mutex); - VK_LOGI("DIS frame generation composite path %s (supported=%d)", + VK_LOGI("OpenFlow frame generation composite path %s (supported=%d)", want ? "enabled" : "disabled", (int)r->framegen_supported); } diff --git a/app/src/main/res/values-b+es+419/strings.xml b/app/src/main/res/values-b+es+419/strings.xml index c1962e622..45c5843df 100644 --- a/app/src/main/res/values-b+es+419/strings.xml +++ b/app/src/main/res/values-b+es+419/strings.xml @@ -2717,7 +2717,7 @@ Ruta instalada: Generar fotogramas Desactivado LSFG - DIS + OpenFlow Multiplicador %1$dx Objetivo adaptativo @@ -2725,7 +2725,7 @@ Ruta instalada: %1$d fps Interpola entre fotogramas renderizados con Lossless Scaling. Movimiento más fluido, pero un fotograma extra de latencia de entrada. Sube hacia el objetivo solo mientras ayude de forma medible, en lugar de mantener un multiplicador fijo. - Instala Lossless Scaling en los ajustes del contenedor para usar el motor LSFG. DIS no necesita nada más. + Instala Lossless Scaling en los ajustes del contenedor para usar el motor LSFG. OpenFlow no necesita nada más. Interpola entre fotogramas renderizados con Dense Inverse Search. Integrado; no requiere shaders externos. Escala de resolución Rápido @@ -2736,7 +2736,7 @@ Ruta instalada: Frecuencia máx. %1$d fps Mostrar flujo - Dibuja los vectores de movimiento que estima DIS en lugar del fotograma generado. Solo para diagnóstico. + Dibuja los vectores de movimiento que estima OpenFlow en lugar del fotograma generado. Solo para diagnóstico. Preajuste de calidad Ultra rendimiento Rendimiento diff --git a/app/src/main/res/values-da/strings.xml b/app/src/main/res/values-da/strings.xml index 2e2541794..22b886fdd 100644 --- a/app/src/main/res/values-da/strings.xml +++ b/app/src/main/res/values-da/strings.xml @@ -2729,7 +2729,7 @@ Installeret sti: Generér billeder Fra LSFG - DIS + OpenFlow Multiplikator %1$dx Adaptivt mål @@ -2737,7 +2737,7 @@ Installeret sti: %1$d fps Interpolerer mellem gengivne billeder med Lossless Scaling. Blødere bevægelse, men ét ekstra billede med inputforsinkelse. Stiger mod målet, kun mens det målbart hjælper, i stedet for at fastholde en fast multiplikator. - Installér Lossless Scaling i containerindstillingerne for at bruge LSFG-motoren. DIS kræver ikke noget ekstra. + Installér Lossless Scaling i containerindstillingerne for at bruge LSFG-motoren. OpenFlow kræver ikke noget ekstra. Interpolerer mellem gengivne billeder med Dense Inverse Search. Indbygget; ingen eksterne shaders kræves. Opløsningsskala Hurtig @@ -2748,7 +2748,7 @@ Installeret sti: Maks. opdateringshastighed %1$d fps Vis flow - Tegner de bevægelsesvektorer, DIS beregner, i stedet for det genererede billede. Kun til diagnostik. + Tegner de bevægelsesvektorer, OpenFlow beregner, i stedet for det genererede billede. Kun til diagnostik. Kvalitetsforudindstilling Ultra ydeevne Ydeevne diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 31ebf950f..4274ed102 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -2720,7 +2720,7 @@ Installierter Pfad: Frames generieren Aus LSFG - DIS + OpenFlow Multiplikator %1$dx Adaptives Ziel @@ -2728,7 +2728,7 @@ Installierter Pfad: %1$d fps Interpoliert zwischen gerenderten Frames mit Lossless Scaling. Flüssigere Bewegung, aber ein zusätzlicher Frame Eingabeverzögerung. Steigt nur dann in Richtung Ziel, wenn es messbar hilft, statt einen festen Multiplikator zu halten. - Installiere Lossless Scaling in den Container-Einstellungen, um die LSFG-Engine zu nutzen. DIS benötigt nichts Zusätzliches. + Installiere Lossless Scaling in den Container-Einstellungen, um die LSFG-Engine zu nutzen. OpenFlow benötigt nichts Zusätzliches. Interpoliert zwischen gerenderten Frames mit Dense Inverse Search. Eingebaut; keine externen Shader nötig. Auflösungsskalierung Schnell @@ -2739,7 +2739,7 @@ Installierter Pfad: Max. Bildwiederholrate %1$d fps Fluss anzeigen - Zeichnet die von DIS geschätzten Bewegungsvektoren statt des generierten Frames. Nur zur Diagnose. + Zeichnet die von OpenFlow geschätzten Bewegungsvektoren statt des generierten Frames. Nur zur Diagnose. Qualitätsvoreinstellung Ultra-Leistung Leistung diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index b9ce46b16..caf17402e 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -2720,7 +2720,7 @@ Ruta instalada: Generar fotogramas Desactivado LSFG - DIS + OpenFlow Multiplicador %1$dx Objetivo adaptativo @@ -2728,7 +2728,7 @@ Ruta instalada: %1$d fps Interpola entre fotogramas renderizados con Lossless Scaling. Movimiento más fluido, pero un fotograma extra de latencia de entrada. Sube hacia el objetivo solo mientras ayude de forma medible, en lugar de mantener un multiplicador fijo. - Instala Lossless Scaling en los ajustes del contenedor para usar el motor LSFG. DIS no necesita nada más. + Instala Lossless Scaling en los ajustes del contenedor para usar el motor LSFG. OpenFlow no necesita nada más. Interpola entre fotogramas renderizados con Dense Inverse Search. Integrado; no requiere shaders externos. Escala de resolución Rápido @@ -2739,7 +2739,7 @@ Ruta instalada: Frecuencia máx. %1$d fps Mostrar flujo - Dibuja los vectores de movimiento que estima DIS en lugar del fotograma generado. Solo para diagnóstico. + Dibuja los vectores de movimiento que estima OpenFlow en lugar del fotograma generado. Solo para diagnóstico. Preajuste de calidad Ultra rendimiento Rendimiento diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index c061ff497..699c077cc 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -2717,7 +2717,7 @@ Asennuspolku: Generoi ruutuja Pois LSFG - DIS + OpenFlow Kerroin %1$dx Mukautuva tavoite @@ -2725,7 +2725,7 @@ Asennuspolku: %1$d fps Interpoloi renderöityjen ruutujen välillä Lossless Scalingilla. Sulavampi liike, mutta yhden ruudun lisäviive syötteessä. Nousee kohti tavoitetta vain, kun siitä on mitattavaa hyötyä, sen sijaan että pitäisi kiinteän kertoimen. - Asenna Lossless Scaling säiliön asetuksista käyttääksesi LSFG-moottoria. DIS ei tarvitse mitään lisäksi. + Asenna Lossless Scaling säiliön asetuksista käyttääksesi LSFG-moottoria. OpenFlow ei tarvitse mitään lisäksi. Interpoloi renderöityjen ruutujen välillä Dense Inverse Searchilla. Sisäänrakennettu; ulkoisia varjostimia ei tarvita. Resoluutioskaala Nopea @@ -2736,7 +2736,7 @@ Asennuspolku: Maks. virkistystaajuus %1$d fps Näytä liikevuo - Piirtää DIS:n arvioimat liikevektorit generoidun ruudun sijaan. Vain diagnostiikkaan. + Piirtää OpenFlow:n arvioimat liikevektorit generoidun ruudun sijaan. Vain diagnostiikkaan. Laatuesiasetus Ultra-suorituskyky Suorituskyky diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index aa08dd23e..1c381e369 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -2720,7 +2720,7 @@ Chemin installé : Générer des images Désactivé LSFG - DIS + OpenFlow Multiplicateur %1$dx Cible adaptative @@ -2728,7 +2728,7 @@ Chemin installé : %1$d fps Interpole entre les images rendues avec Lossless Scaling. Mouvement plus fluide, mais une image supplémentaire de latence d\'entrée. Monte vers la cible uniquement tant que cela aide de façon mesurable, au lieu de conserver un multiplicateur fixe. - Installez Lossless Scaling dans les paramètres du conteneur pour utiliser le moteur LSFG. DIS ne nécessite rien de plus. + Installez Lossless Scaling dans les paramètres du conteneur pour utiliser le moteur LSFG. OpenFlow ne nécessite rien de plus. Interpole entre les images rendues avec Dense Inverse Search. Intégré ; aucun shader externe requis. Échelle de résolution Rapide @@ -2739,7 +2739,7 @@ Chemin installé : Fréquence max. %1$d fps Afficher le flux - Dessine les vecteurs de mouvement estimés par DIS au lieu de l\'image générée. Diagnostic uniquement. + Dessine les vecteurs de mouvement estimés par OpenFlow au lieu de l\'image générée. Diagnostic uniquement. Préréglage de qualité Ultra performance Performance diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index e1793752b..b896994b6 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -2614,7 +2614,7 @@ फ़्रेम जनरेट करें बंद LSFG - DIS + OpenFlow गुणक %1$dx अनुकूली लक्ष्य @@ -2622,7 +2622,7 @@ %1$d fps Lossless Scaling से रेंडर किए गए फ़्रेमों के बीच इंटरपोलेट करता है। गति अधिक सहज, लेकिन इनपुट में एक अतिरिक्त फ़्रेम की देरी। स्थिर गुणक बनाए रखने के बजाय, केवल तभी लक्ष्य की ओर बढ़ता है जब इससे मापने योग्य लाभ हो। - LSFG इंजन उपयोग करने के लिए कंटेनर सेटिंग्स में Lossless Scaling इंस्टॉल करें। DIS को कुछ अतिरिक्त नहीं चाहिए। + LSFG इंजन उपयोग करने के लिए कंटेनर सेटिंग्स में Lossless Scaling इंस्टॉल करें। OpenFlow को कुछ अतिरिक्त नहीं चाहिए। Dense Inverse Search से रेंडर किए गए फ़्रेम के बीच इंटरपोलेट करता है। ऐप में बिल्ट-इन; बाहरी शेडर की ज़रूरत नहीं। रिज़ॉल्यूशन स्केल तेज़ @@ -2633,7 +2633,7 @@ अधिकतम रिफ्रेश दर %1$d fps फ़्लो दिखाएँ - जनरेट किए गए फ़्रेम के बजाय DIS द्वारा अनुमानित मोशन वेक्टर दिखाता है। केवल निदान के लिए। + जनरेट किए गए फ़्रेम के बजाय OpenFlow द्वारा अनुमानित मोशन वेक्टर दिखाता है। केवल निदान के लिए। गुणवत्ता प्रीसेट अल्ट्रा प्रदर्शन प्रदर्शन diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 33a95a4fd..1d3bb4500 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -2720,7 +2720,7 @@ Percorso installato: Genera fotogrammi Disattivo LSFG - DIS + OpenFlow Moltiplicatore %1$dx Obiettivo adattivo @@ -2728,7 +2728,7 @@ Percorso installato: %1$d fps Interpola tra i fotogrammi renderizzati con Lossless Scaling. Movimento più fluido, ma un fotogramma in più di latenza di input. Sale verso l\'obiettivo solo finché aiuta in modo misurabile, invece di mantenere un moltiplicatore fisso. - Installa Lossless Scaling nelle impostazioni del contenitore per usare il motore LSFG. DIS non richiede nulla di aggiuntivo. + Installa Lossless Scaling nelle impostazioni del contenitore per usare il motore LSFG. OpenFlow non richiede nulla di aggiuntivo. Interpola tra i fotogrammi renderizzati con Dense Inverse Search. Integrato; nessuno shader esterno richiesto. Scala risoluzione Veloce @@ -2739,7 +2739,7 @@ Percorso installato: Freq. max %1$d fps Mostra flusso - Disegna i vettori di movimento stimati da DIS al posto del fotogramma generato. Solo a scopo diagnostico. + Disegna i vettori di movimento stimati da OpenFlow al posto del fotogramma generato. Solo a scopo diagnostico. Preset qualità Ultra prestazioni Prestazioni diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 18a4f80fe..f8357743b 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -2717,7 +2717,7 @@ フレームを生成 オフ LSFG - DIS + OpenFlow 倍率 %1$dx アダプティブ目標 @@ -2725,7 +2725,7 @@ %1$d fps Lossless Scaling でレンダリング済みフレーム間を補間します。動きは滑らかになりますが、入力遅延が 1 フレーム増えます。 固定倍率を保つのではなく、効果が測定できる間だけ目標に向けて上げていきます。 - LSFG エンジンを使用するには、コンテナ設定で Lossless Scaling をインストールしてください。DIS には追加のものは不要です。 + LSFG エンジンを使用するには、コンテナ設定で Lossless Scaling をインストールしてください。OpenFlow には追加のものは不要です。 Dense Inverse Search で描画フレーム間を補間します。アプリ内蔵で外部シェーダーは不要です。 解像度スケール 高速 @@ -2736,7 +2736,7 @@ 最大リフレッシュレート %1$d fps フローを表示 - 生成フレームの代わりに、DIS が推定した動きベクトルを描画します。診断専用です。 + 生成フレームの代わりに、OpenFlow が推定した動きベクトルを描画します。診断専用です。 画質プリセット ウルトラパフォーマンス パフォーマンス diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 0995b943d..c1cbab9f3 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -2719,7 +2719,7 @@ 프레임 생성 사용 끄기 LSFG - DIS + OpenFlow 배수 %1$dx 적응형 목표 @@ -2727,7 +2727,7 @@ %1$d fps Lossless Scaling으로 렌더링된 프레임 사이를 보간합니다. 움직임은 부드러워지지만 입력 지연이 한 프레임 늘어납니다. 고정 배수를 유지하는 대신, 측정 가능한 이득이 있을 때만 목표를 향해 올립니다. - LSFG 엔진을 사용하려면 컨테이너 설정에서 Lossless Scaling을 설치하세요. DIS는 추가 설치가 필요 없습니다. + LSFG 엔진을 사용하려면 컨테이너 설정에서 Lossless Scaling을 설치하세요. OpenFlow는 추가 설치가 필요 없습니다. Dense Inverse Search로 렌더링된 프레임 사이를 보간합니다. 내장 기능이며 외부 셰이더가 필요 없습니다. 해상도 배율 빠름 @@ -2738,7 +2738,7 @@ 최대 새로고침 빈도 %1$d fps 흐름 표시 - 생성된 프레임 대신 DIS가 추정한 모션 벡터를 그립니다. 진단용입니다. + 생성된 프레임 대신 OpenFlow가 추정한 모션 벡터를 그립니다. 진단용입니다. 품질 프리셋 울트라 성능 성능 diff --git a/app/src/main/res/values-no/strings.xml b/app/src/main/res/values-no/strings.xml index 4cb6a4e03..cef23b332 100644 --- a/app/src/main/res/values-no/strings.xml +++ b/app/src/main/res/values-no/strings.xml @@ -2717,7 +2717,7 @@ Installert bane: Generer bilder Av LSFG - DIS + OpenFlow Multiplikator %1$dx Adaptivt mål @@ -2725,7 +2725,7 @@ Installert bane: %1$d fps Interpolerer mellom gjengitte bilder med Lossless Scaling. Jevnere bevegelse, men ett ekstra bilde med inndataforsinkelse. Stiger mot målet bare så lenge det hjelper målbart, i stedet for å holde en fast multiplikator. - Installer Lossless Scaling i containerinnstillingene for å bruke LSFG-motoren. DIS trenger ikke noe ekstra. + Installer Lossless Scaling i containerinnstillingene for å bruke LSFG-motoren. OpenFlow trenger ikke noe ekstra. Interpolerer mellom gjengitte bilder med Dense Inverse Search. Innebygd; ingen eksterne shadere kreves. Oppløsningsskala Rask @@ -2736,7 +2736,7 @@ Installert bane: Maks. oppdateringsfrekvens %1$d fps Vis flyt - Tegner bevegelsesvektorene DIS beregner i stedet for det genererte bildet. Kun for diagnostikk. + Tegner bevegelsesvektorene OpenFlow beregner i stedet for det genererte bildet. Kun for diagnostikk. Kvalitetsforhåndsinnstilling Ultra ytelse Ytelse diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index c0dc3fbbc..b10028777 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -2724,7 +2724,7 @@ Zainstalowana ścieżka: Generuj klatki Wył. LSFG - DIS + OpenFlow Mnożnik %1$dx Cel adaptacyjny @@ -2732,7 +2732,7 @@ Zainstalowana ścieżka: %1$d fps Interpoluje między wyrenderowanymi klatkami przy użyciu Lossless Scaling. Płynniejszy ruch, ale jedna dodatkowa klatka opóźnienia sterowania. Zwiększa się w kierunku celu tylko wtedy, gdy przynosi to mierzalną korzyść, zamiast utrzymywać stały mnożnik. - Zainstaluj Lossless Scaling w ustawieniach kontenera, aby korzystać z silnika LSFG. DIS nie wymaga niczego dodatkowego. + Zainstaluj Lossless Scaling w ustawieniach kontenera, aby korzystać z silnika LSFG. OpenFlow nie wymaga niczego dodatkowego. Interpoluje między wyrenderowanymi klatkami przy użyciu Dense Inverse Search. Wbudowane; nie wymaga zewnętrznych shaderów. Skala rozdzielczości Szybko @@ -2743,7 +2743,7 @@ Zainstalowana ścieżka: Maks. częstotliwość odświeżania %1$d fps Pokaż przepływ - Rysuje wektory ruchu szacowane przez DIS zamiast wygenerowanej klatki. Tylko do diagnostyki. + Rysuje wektory ruchu szacowane przez OpenFlow zamiast wygenerowanej klatki. Tylko do diagnostyki. Ustawienie jakości Ultra wydajność Wydajność diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 2f3ab4ef3..fe38cd7f7 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -2718,7 +2718,7 @@ Caminho instalado: Gerar quadros Desligado LSFG - DIS + OpenFlow Multiplicador %1$dx Alvo adaptativo @@ -2726,7 +2726,7 @@ Caminho instalado: %1$d fps Interpola entre quadros renderizados com o Lossless Scaling. Movimento mais suave, mas um quadro extra de latência de entrada. Sobe em direção ao alvo apenas enquanto ajudar de forma mensurável, em vez de manter um multiplicador fixo. - Instale o Lossless Scaling nas configurações do contêiner para usar o motor LSFG. O DIS não precisa de nada extra. + Instale o Lossless Scaling nas configurações do contêiner para usar o motor LSFG. O OpenFlow não precisa de nada extra. Interpola entre quadros renderizados com Dense Inverse Search. Integrado; sem shaders externos. Escala de resolução Rápido @@ -2737,7 +2737,7 @@ Caminho instalado: Frequência máx. %1$d fps Mostrar fluxo - Desenha os vetores de movimento estimados pelo DIS em vez do quadro gerado. Apenas para diagnóstico. + Desenha os vetores de movimento estimados pelo OpenFlow em vez do quadro gerado. Apenas para diagnóstico. Predefinição de qualidade Ultra desempenho Desempenho diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 4e427485c..68208bf79 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -2717,7 +2717,7 @@ Caminho instalado: Gerar fotogramas Desligado LSFG - DIS + OpenFlow Multiplicador %1$dx Alvo adaptativo @@ -2725,7 +2725,7 @@ Caminho instalado: %1$d fps Interpola entre fotogramas renderizados com o Lossless Scaling. Movimento mais suave, mas um fotograma extra de latência de entrada. Sobe em direção ao alvo apenas enquanto ajudar de forma mensurável, em vez de manter um multiplicador fixo. - Instale o Lossless Scaling nas definições do contentor para usar o motor LSFG. O DIS não precisa de nada extra. + Instale o Lossless Scaling nas definições do contentor para usar o motor LSFG. O OpenFlow não precisa de nada extra. Interpola entre fotogramas renderizados com Dense Inverse Search. Integrado; sem shaders externos. Escala de resolução Rápido @@ -2736,7 +2736,7 @@ Caminho instalado: Frequência máx. %1$d fps Mostrar fluxo - Desenha os vetores de movimento estimados pelo DIS em vez do fotograma gerado. Apenas para diagnóstico. + Desenha os vetores de movimento estimados pelo OpenFlow em vez do fotograma gerado. Apenas para diagnóstico. Predefinição de qualidade Ultra desempenho Desempenho diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index e410c4e6e..36074a67f 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -2717,7 +2717,7 @@ Cale instalata: Generează cadre Oprit LSFG - DIS + OpenFlow Multiplicator %1$dx Țintă adaptivă @@ -2725,7 +2725,7 @@ Cale instalata: %1$d fps Interpolează între cadrele randate cu Lossless Scaling. Mișcare mai fluidă, dar un cadru suplimentar de latență la intrare. Urcă spre țintă doar cât timp ajută în mod măsurabil, în loc să păstreze un multiplicator fix. - Instalează Lossless Scaling din setările containerului pentru a folosi motorul LSFG. DIS nu necesită nimic în plus. + Instalează Lossless Scaling din setările containerului pentru a folosi motorul LSFG. OpenFlow nu necesită nimic în plus. Interpolează între cadrele randate cu Dense Inverse Search. Încorporat; fără shadere externe. Scală rezoluție Rapid @@ -2736,7 +2736,7 @@ Cale instalata: Rată de reîmprospătare max. %1$d fps Arată fluxul - Desenează vectorii de mișcare estimați de DIS în locul cadrului generat. Doar pentru diagnosticare. + Desenează vectorii de mișcare estimați de OpenFlow în locul cadrului generat. Doar pentru diagnosticare. Presetare de calitate Ultra performanță Performanță diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 8a1499bf1..8f04bdcda 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -2624,7 +2624,7 @@ Генерировать кадры Выкл. LSFG - DIS + OpenFlow Множитель %1$dx Адаптивная цель @@ -2632,7 +2632,7 @@ %1$d fps Интерполирует между отрисованными кадрами с помощью Lossless Scaling. Движение плавнее, но задержка ввода увеличивается на один кадр. Повышается к цели только пока это даёт измеримый выигрыш, вместо удержания фиксированного множителя. - Установите Lossless Scaling в настройках контейнера, чтобы использовать движок LSFG. Для DIS ничего дополнительно не нужно. + Установите Lossless Scaling в настройках контейнера, чтобы использовать движок LSFG. Для OpenFlow ничего дополнительно не нужно. Интерполирует между отрендеренными кадрами методом Dense Inverse Search. Встроено; внешние шейдеры не требуются. Масштаб разрешения Быстро @@ -2643,7 +2643,7 @@ Макс. частота обновления %1$d fps Показать поток - Рисует векторы движения, вычисленные DIS, вместо сгенерированного кадра. Только для диагностики. + Рисует векторы движения, вычисленные OpenFlow, вместо сгенерированного кадра. Только для диагностики. Пресет качества Ультрапроизводительность Производительность diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 2164b3a46..3a21ff555 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -2717,7 +2717,7 @@ Installerad sökväg: Generera bilder Av LSFG - DIS + OpenFlow Multiplikator %1$dx Adaptivt mål @@ -2725,7 +2725,7 @@ Installerad sökväg: %1$d fps Interpolerar mellan renderade bildrutor med Lossless Scaling. Mjukare rörelse, men en extra bildruta med inmatningsfördröjning. Stiger mot målet endast så länge det hjälper mätbart, i stället för att hålla en fast multiplikator. - Installera Lossless Scaling i containerinställningarna för att använda LSFG-motorn. DIS kräver inget extra. + Installera Lossless Scaling i containerinställningarna för att använda LSFG-motorn. OpenFlow kräver inget extra. Interpolerar mellan renderade bildrutor med Dense Inverse Search. Inbyggd; inga externa shaders krävs. Upplösningsskala Snabb @@ -2736,7 +2736,7 @@ Installerad sökväg: Max uppdateringsfrekvens %1$d fps Visa flöde - Ritar de rörelsevektorer som DIS beräknar i stället för den genererade bildrutan. Endast för diagnostik. + Ritar de rörelsevektorer som OpenFlow beräknar i stället för den genererade bildrutan. Endast för diagnostik. Kvalitetsförval Ultraprestanda Prestanda diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index 7fa83bc76..ca2f57340 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -2717,7 +2717,7 @@ สร้างเฟรม ปิด LSFG - DIS + OpenFlow ตัวคูณ %1$dx เป้าหมายแบบปรับอัตโนมัติ @@ -2725,7 +2725,7 @@ %1$d fps แทรกเฟรมระหว่างเฟรมที่เรนเดอร์ด้วย Lossless Scaling การเคลื่อนไหวลื่นขึ้น แต่มีความหน่วงของอินพุตเพิ่มขึ้นหนึ่งเฟรม จะไต่ขึ้นสู่เป้าหมายเฉพาะเมื่อวัดผลได้ว่าช่วยจริง แทนที่จะคงตัวคูณไว้คงที่ - ติดตั้ง Lossless Scaling ในการตั้งค่าคอนเทนเนอร์เพื่อใช้เอนจิน LSFG ส่วน DIS ไม่ต้องใช้อะไรเพิ่ม + ติดตั้ง Lossless Scaling ในการตั้งค่าคอนเทนเนอร์เพื่อใช้เอนจิน LSFG ส่วน OpenFlow ไม่ต้องใช้อะไรเพิ่ม แทรกเฟรมระหว่างเฟรมที่เรนเดอร์ด้วย Dense Inverse Search มีในตัว ไม่ต้องใช้เชเดอร์ภายนอก สเกลความละเอียด เร็ว @@ -2736,7 +2736,7 @@ อัตรารีเฟรชสูงสุด %1$d fps แสดงโฟลว์ - วาดเวกเตอร์การเคลื่อนไหวที่ DIS ประมาณไว้แทนเฟรมที่สร้างขึ้น ใช้เพื่อวินิจฉัยเท่านั้น + วาดเวกเตอร์การเคลื่อนไหวที่ OpenFlow ประมาณไว้แทนเฟรมที่สร้างขึ้น ใช้เพื่อวินิจฉัยเท่านั้น ค่าที่ตั้งไว้ของคุณภาพ ประสิทธิภาพสูงสุด ประสิทธิภาพ diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 78abffc96..364fa6654 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -2717,7 +2717,7 @@ Yüklü konum: Kare üret Kapalı LSFG - DIS + OpenFlow Çarpan %1$dx Uyarlanabilir hedef @@ -2725,7 +2725,7 @@ Yüklü konum: %1$d fps Lossless Scaling ile işlenmiş kareler arasında ara kare üretir. Daha akıcı hareket, ancak bir kare fazladan giriş gecikmesi. Sabit bir çarpanı korumak yerine, yalnızca ölçülebilir fayda sağladığı sürece hedefe doğru yükselir. - LSFG motorunu kullanmak için kapsayıcı ayarlarından Lossless Scaling\'i yükleyin. DIS için ek bir şey gerekmez. + LSFG motorunu kullanmak için kapsayıcı ayarlarından Lossless Scaling\'i yükleyin. OpenFlow için ek bir şey gerekmez. Dense Inverse Search ile işlenmiş kareler arasında ara kare oluşturur. Uygulamaya gömülü; harici shader gerekmez. Çözünürlük Ölçeği Hızlı @@ -2736,7 +2736,7 @@ Yüklü konum: Maks. yenileme hızı %1$d fps Akışı göster - Üretilen kare yerine DIS\'in tahmin ettiği hareket vektörlerini çizer. Yalnızca tanılama amaçlıdır. + Üretilen kare yerine OpenFlow\'un tahmin ettiği hareket vektörlerini çizer. Yalnızca tanılama amaçlıdır. Kalite ön ayarı Ultra performans Performans diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 1820f294e..0cc9cfdef 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -2724,7 +2724,7 @@ Генерувати кадри Вимк. LSFG - DIS + OpenFlow Множник %1$dx Адаптивна ціль @@ -2732,7 +2732,7 @@ %1$d fps Інтерполює між відрендереними кадрами за допомогою Lossless Scaling. Рух плавніший, але затримка вводу зростає на один кадр. Підвищується до цілі лише доки це дає вимірний виграш, замість утримання фіксованого множника. - Установіть Lossless Scaling у налаштуваннях контейнера, щоб використовувати рушій LSFG. DIS не потребує нічого додатково. + Установіть Lossless Scaling у налаштуваннях контейнера, щоб використовувати рушій LSFG. OpenFlow не потребує нічого додатково. Інтерполює між відрендереними кадрами методом Dense Inverse Search. Вбудовано; зовнішні шейдери не потрібні. Масштаб роздільної здатності Швидко @@ -2743,7 +2743,7 @@ Макс. частота оновлення %1$d fps Показати потік - Малює вектори руху, які оцінює DIS, замість згенерованого кадру. Лише для діагностики. + Малює вектори руху, які оцінює OpenFlow, замість згенерованого кадру. Лише для діагностики. Пресет якості Ультрапродуктивність Продуктивність diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index f167dd1a8..193e63bc5 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -2718,7 +2718,7 @@ 生成帧 关闭 LSFG - DIS + OpenFlow 倍数 %1$dx 自适应目标 @@ -2726,7 +2726,7 @@ %1$d fps 使用 Lossless Scaling 在已渲染的帧之间插帧。画面更流畅,但输入延迟会增加一帧。 仅在能带来可测量的提升时才向目标提升,而不是保持固定倍数。 - 请在容器设置中安装 Lossless Scaling 以使用 LSFG 引擎。DIS 无需任何额外内容。 + 请在容器设置中安装 Lossless Scaling 以使用 LSFG 引擎。OpenFlow 无需任何额外内容。 使用 Dense Inverse Search 在渲染帧之间插帧。内置功能,无需外部着色器。 分辨率缩放 快速 @@ -2737,7 +2737,7 @@ 最高刷新率 %1$d fps 显示光流 - 绘制 DIS 估算的运动矢量,而不是生成的帧。仅用于诊断。 + 绘制 OpenFlow 估算的运动矢量,而不是生成的帧。仅用于诊断。 画质预设 极致性能 性能 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 95ca4d9c4..061bd8523 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -2717,7 +2717,7 @@ 生成影格 關閉 LSFG - DIS + OpenFlow 倍數 %1$dx 自適應目標 @@ -2725,7 +2725,7 @@ %1$d fps 使用 Lossless Scaling 在已算繪的影格之間插補。畫面更流暢,但輸入延遲會增加一個影格。 僅在能帶來可測量的提升時才朝目標提升,而不是維持固定倍數。 - 請在容器設定中安裝 Lossless Scaling 以使用 LSFG 引擎。DIS 則不需要額外安裝任何東西。 + 請在容器設定中安裝 Lossless Scaling 以使用 LSFG 引擎。OpenFlow 則不需要額外安裝任何東西。 使用 Dense Inverse Search 在已算繪的影格之間插補。內建功能,無需外部著色器。 解析度縮放 快速 @@ -2736,7 +2736,7 @@ 最高更新率 %1$d fps 顯示光流 - 繪製 DIS 估算的動態向量,而非生成的影格。僅供診斷使用。 + 繪製 OpenFlow 估算的動態向量,而非生成的影格。僅供診斷使用。 畫質預設 極致效能 效能 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cb6b91956..ffaba78f7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -917,7 +917,7 @@ E.g. META for META key, \n Generate Frames Off LSFG - DIS + OpenFlow Multiplier %1$dx Adaptive Target @@ -938,7 +938,7 @@ E.g. META for META key, \n Motion estimated at full resolution. Highest cost; use it only when the game has GPU headroom to spare. Interpolates between rendered frames with Lossless Scaling. Smoother motion, but one extra frame of input latency. Climbs toward the target only while it measurably helps, instead of holding a fixed multiplier. - Install Lossless Scaling in container settings to use the LSFG engine. DIS needs nothing extra. + Install Lossless Scaling in container settings to use the LSFG engine. OpenFlow needs nothing extra. Interpolates between rendered frames with Dense Inverse Search. Built into the app; no external shaders required. Resolution Scale Fast @@ -949,7 +949,7 @@ E.g. META for META key, \n Max refresh rate %1$d fps Show flow - Draws the motion vectors DIS estimates instead of the generated frame. Diagnostic only. + Draws the motion vectors OpenFlow estimates instead of the generated frame. Diagnostic only. Frame Generation Looking for Lossless Scaling… Lossless Scaling shaders ready. diff --git a/docs/FRAME-GENERATION.md b/docs/FRAME-GENERATION.md index 8f375b5e4..94de4ef4f 100644 --- a/docs/FRAME-GENERATION.md +++ b/docs/FRAME-GENERATION.md @@ -12,7 +12,7 @@ its own settings so switching between them does not disturb the other. | Engine | Needs | Character | | --- | --- | --- | | **Lossless Scaling (LSFG)** | Your own copy of Lossless Scaling on Steam | The 25-shader chain from Lossless Scaling, ported to Vulkan | -| **DIS** | Nothing — ships with the APK | Dense Inverse Search optical flow, fully open source | +| **OpenFlow** | Nothing — ships with the APK | Dense Inverse Search optical flow, fully open source | ## Lossless Scaling (LSFG) @@ -26,9 +26,9 @@ Generation**. WinNative finds the DLL automatically from your Steam library; if **Select Lossless.dll…** to point at it. The LSFG half of the **FG** tab stays disabled until the shaders import successfully. -## DIS +## OpenFlow -**Nothing to buy, nothing to import.** DIS is a complete open-source Dense Inverse Search frame +**Nothing to buy, nothing to import.** OpenFlow is a complete open-source Dense Inverse Search frame generator built into WinNative — sixteen compute shaders that ship with the APK — so it works on a fresh install with no Steam account and no `Lossless.dll`. Turn it on in the **FG** tab and it runs. @@ -41,12 +41,12 @@ runs. | Multiplier | LSFG | 2× / 3× / 4× — generated frames per rendered frame | | Adaptive Target | LSFG | Aim for a specific output rate (60/90/120/144/165) instead of a fixed multiplier | | Flow Scale | LSFG | 25–100%, resolution of the optical-flow pyramid; lower is cheaper and softer | -| Resolution Scale | DIS | Fast / Balance / Quality — 180 / 252 / 360 pixels on the frame's **shorter** side | -| Target FPS | DIS | Max refresh rate, or a specific one (60/90/120/144/165) | -| Show flow | DIS | Debug view: renders the estimated motion field instead of the frame | +| Resolution Scale | OpenFlow | Fast / Balance / Quality — 180 / 252 / 360 pixels on the frame's **shorter** side | +| Target FPS | OpenFlow | Max refresh rate, or a specific one (60/90/120/144/165) | +| Show flow | OpenFlow | Debug view: renders the estimated motion field instead of the frame | | FPS Limiter | Both | Caps the game's own frame rate, from 15 fps upward | -DIS states its Resolution Scale in pixels rather than as a percentage on purpose: a fixed pixel +OpenFlow states its Resolution Scale in pixels rather than as a percentage on purpose: a fixed pixel budget costs the same on a 720p container and a 1440p one, whereas the same percentage would cost four times as much on the larger container without telling the search anything more about the motion. Lower is cheaper; higher tracks small or fast-moving detail better. @@ -64,6 +64,6 @@ gives the most even pacing. ## Credits Both engines are other people's work. The LSFG chain derives from **Camille LaVey**'s Vulkan port -in the Eden Emulator Project, which derives from **PancakeTAS**'s lsfg-vk; the DIS engine was +in the Eden Emulator Project, which derives from **PancakeTAS**'s lsfg-vk; the OpenFlow engine was contributed by **qwertypower** of DEVAR Entertainment LLC. See [CREDITS.md](../CREDITS.md) for the full attribution, including which source files came from where.