Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9072a97
Update DIS
qwertypower Sep 14, 2026
451e4f6
Merge branch 'main' into main
maxjivi05 Sep 14, 2026
03b2884
Merge branch 'WinNative-Emu:main' into main
qwertypower Sep 14, 2026
e3dd19b
Merge branch 'WinNative-Emu:main' into main
qwertypower Sep 15, 2026
b36b86a
Update DIS
qwertypower Sep 15, 2026
8d68524
Merge branch 'WinNative-Emu:main' into main
qwertypower Sep 19, 2026
493a46a
UI: fix layout overflow on portrait/compact widths; pace guest presen…
qwertypower Sep 19, 2026
4852c30
DIS: divergence-gated occlusion mask; bound the absolute flow magnitude
qwertypower Sep 19, 2026
89f5c52
Merge pull request #2 from qwertypower/dis-interpolation-occlusion
qwertypower Sep 19, 2026
44ee3de
DIS: roll the frame generator back to the upstream 68f678c1 state
qwertypower Sep 20, 2026
bec054b
DIS: stabilize the static-overlay mask across frames
qwertypower Sep 20, 2026
d13c628
DIS: cut the frame generator's pass count and sampling cost
qwertypower Sep 20, 2026
b9c53f5
DIS: load the search patch with textureGather quads
qwertypower Sep 20, 2026
87239ab
DIS: skip the warp path under a quarter-pixel of flow
qwertypower Sep 20, 2026
d110185
DIS: restore refinement on every level and steady the plan
qwertypower Sep 20, 2026
d5d18db
DIS: dilate the overlay mask over four taps again
qwertypower Sep 20, 2026
7f2a5c3
DIS: nudge the 4x path towards interpolation
qwertypower Sep 20, 2026
6ebe4fe
DIS: add GPL-3.0 license headers crediting qwertypower (DEVAR Enterta…
qwertypower Sep 20, 2026
86ed508
DIS: add GPL-3.0 license headers to the shaders
qwertypower Sep 20, 2026
186378e
Merge branch 'main' into main
maxjivi05 Sep 20, 2026
bb65c11
Merge branch 'WinNative-Emu:main' into main
qwertypower Sep 21, 2026
091b4e7
DIS: temporally smooth the flow and interpolate along a parabola
qwertypower Sep 21, 2026
ab6603b
Merge branch 'main' into main
maxjivi05 Sep 23, 2026
da488dc
Merge branch 'WinNative-Emu:main' into main
qwertypower Sep 25, 2026
c921823
DIS: warp-based interpolation with source-point flow lookup, RG16F flow
qwertypower Sep 25, 2026
c597619
DIS: move into its own module, add optional GL_QCOM_motion_estimation…
qwertypower Sep 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 4 additions & 18 deletions app/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -103,23 +103,6 @@ set(SHADER_LIST
"effect_colorblind:frag:effect_colorblind_frag"
"effect_pixelate:frag:effect_pixelate_frag"
"sgsr1:frag:sgsr1_frag"
"dis_luma_r16:comp:dis_luma_r16_comp"
"dis_luma_r32:comp:dis_luma_r32_comp"
"dis_gradient:comp:dis_gradient_comp"
"dis_inverse_search:comp:dis_inverse_search_comp"
"dis_propagate:comp:dis_propagate_comp"
"dis_densify:comp:dis_densify_comp"
"dis_interpolate:comp:dis_interpolate_comp"
"dis_hist:comp:dis_hist_comp"
"dis_side:comp:dis_side_comp"
"dis_temporal:comp:dis_temporal_comp"
"dis_vr_prep:comp:dis_vr_prep_comp"
"dis_vr_d1:comp:dis_vr_d1_comp"
"dis_vr_d2:comp:dis_vr_d2_comp"
"dis_vr_w:comp:dis_vr_w_comp"
"dis_vr_coef:comp:dis_vr_coef_comp"
"dis_vr_sor:comp:dis_vr_sor_comp"
"dis_vr_add:comp:dis_vr_add_comp"
)

set(SHADER_HEADERS "")
Expand Down Expand Up @@ -149,6 +132,9 @@ endforeach()

add_custom_target(winlator_shaders DEPENDS ${SHADER_HEADERS})

# DIS frame generator (optical flow + interpolation), linked by libwinlator and libwnwayland.
add_subdirectory(dis)

# ----------------------------------------------------------------------------
# Winlator native library (X-server, AHB, Vulkan compositor, helpers)
# ----------------------------------------------------------------------------
Expand Down Expand Up @@ -183,7 +169,6 @@ add_library(winlator SHARED
winlator/vk/lsfg/lsfg_jni.c
winlator/vk/framegen/fg_present.c
winlator/vk/framegen/fg_jni.c
winlator/vk/dis/vkr_dis.c
)

add_dependencies(winlator winlator_shaders)
Expand All @@ -201,6 +186,7 @@ target_include_directories(winlator PRIVATE
target_compile_features(winlator PRIVATE cxx_std_17)

target_link_libraries(winlator
wndis
log
android
mediandk
Expand Down
79 changes: 79 additions & 0 deletions app/src/main/cpp/dis/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# 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.
#
# Layout:
# include/vkr_dis.h public API
# include/shaders/*.comp GLSL compute shaders, compiled to SPIR-V headers at build time
# src/ implementation
#
# Uses GLSLC and BIN2C_SCRIPT from the parent CMakeLists.

set(DIS_SHADER_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/shaders")
set(DIS_SHADER_OUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/shaders")
file(MAKE_DIRECTORY "${DIS_SHADER_OUT_DIR}")

set(DIS_SHADERS
dis_luma_r16
dis_luma_r32
dis_gradient
dis_inverse_search
dis_propagate
dis_densify
dis_interpolate
dis_hist
dis_side
dis_flow_pack
dis_vr_prep
dis_vr_d1
dis_vr_d2
dis_vr_w
dis_vr_coef
dis_vr_sor
dis_vr_add
dis_me_luma
)

set(DIS_SHADER_HEADERS "")
foreach(base ${DIS_SHADERS})
set(var "${base}_comp")
set(input "${DIS_SHADER_SRC_DIR}/${base}.comp")
set(spv "${DIS_SHADER_OUT_DIR}/${var}.spv")
set(hdr "${DIS_SHADER_OUT_DIR}/${var}.spv.h")
add_custom_command(
OUTPUT "${hdr}"
COMMAND "${GLSLC}" --target-env=vulkan1.1 -O "${input}" -o "${spv}"
COMMAND "${CMAKE_COMMAND}"
-DINPUT_FILE=${spv}
-DOUTPUT_FILE=${hdr}
-DVAR_NAME=${var}
-P "${BIN2C_SCRIPT}"
DEPENDS "${input}" "${BIN2C_SCRIPT}"
COMMENT "Compiling DIS shader ${base}.comp -> ${var}.spv.h"
VERBATIM
)
list(APPEND DIS_SHADER_HEADERS "${hdr}")
endforeach()

add_custom_target(wndis_shaders DEPENDS ${DIS_SHADER_HEADERS})

add_library(wndis STATIC
src/vkr_dis.c
src/dis_qcom_me.c
)
add_dependencies(wndis wndis_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
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
# vk_dispatch.h: the public header takes its Vulkan types from there.
${CMAKE_CURRENT_SOURCE_DIR}/../winlator/vk
PRIVATE
${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)
39 changes: 39 additions & 0 deletions app/src/main/cpp/dis/include/shaders/dis_flow_pack.comp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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
// 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.

#version 450

precision highp float;
precision highp int;

// Hands the finished level-0 field to the interpolate pass as RG16F, once per source pair.
//
// The interpolate pass reads the field three times per output pixel (the lookup at the
// pixel plus the fixed-point steps towards its source) and it does so for every generated
// frame, at the full output resolution. RG32F is not filterable on every mobile driver,
// and without filtering each of those reads is four fetches and a manual lerp. RG16F is
// filterable everywhere and half the bandwidth; in uv units its precision is a few
// hundredths of a pixel at ordinary speeds and stays under a pixel even at the magnitude
// clamp in dis_vr_add, which is far below what a quarter-frame jump can show.

layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;

layout(set = 0, binding = 0) uniform sampler2D flowIn;
layout(set = 0, binding = 5, rg16f) uniform image2D flowOut;

void main() {
ivec2 p = ivec2(gl_GlobalInvocationID.xy);
ivec2 sz = imageSize(flowOut);
if (p.x >= sz.x || p.y >= sz.y) return;

vec2 f = texelFetch(flowIn, p, 0).xy;
// A zero field degrades to repeating the real frame, which is the right answer
// wherever the flow has nothing finite to say.
if (any(isnan(f)) || any(isinf(f))) f = vec2(0.0);
imageStore(flowOut, p, vec4(f, 0.0, 0.0));
}
Loading
Loading