优化:完善麒麟2K显示与逐主机视频范围协商

This commit is contained in:
songyiming committed 2026-11-04 19:12:52 +08:00
1 parent b1082f8465
commit e35abf6dc0
78 files changed
+2040

No files matched your search

@@ -0,0 +1,44 @@
import gi,time,json,math
gi.require_version('Gtk','3.0')
from gi.repository import Gtk,Gdk,GLib
started=time.monotonic(); draws=0; ticks=0
win=Gtk.Window(title='VDI Kylin quality benchmark')
win.connect('destroy',Gtk.main_quit)
area=Gtk.DrawingArea();win.add(area)
area.set_events(Gdk.EventMask.BUTTON_PRESS_MASK|Gdk.EventMask.KEY_PRESS_MASK)
area.set_can_focus(True)
def event(w,e):
print(json.dumps({'event':e.type.value_nick,'keyval':getattr(e,'keyval',None),'button':getattr(e,'button',None),'x':getattr(e,'x',None),'y':getattr(e,'y',None),'width':area.get_allocated_width(),'height':area.get_allocated_height(),'t':time.monotonic()}),flush=True)
return False
win.connect('key-press-event',event);area.connect('button-press-event',event)
def draw(w,cr):
global draws
draws+=1; width=w.get_allocated_width();height=w.get_allocated_height()
cr.set_source_rgb(.96,.97,.99);cr.paint()
cr.select_font_face('sans');cr.set_font_size(30);cr.set_source_rgb(.08,.12,.18)
cr.move_to(60,65);cr.show_text('VDI Kylin - resolution / text / motion / input verification')
cr.set_font_size(22);cr.move_to(60,105);cr.show_text(f'Native desktop: {width} x {height} Temporary test window')
for row,size in enumerate([12,14,16,18,20,24]):
cr.set_font_size(size);cr.move_to(60,155+row*45);cr.set_source_rgb(.1,.1,.1)
cr.show_text(f'{size}px Cloud desktop 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz')
for i in range(600):
cr.set_source_rgb(0,0,0) if i%2 else cr.set_source_rgb(1,1,1)
cr.rectangle(60+i,445,1,80);cr.fill()
for i,color in enumerate([(1,0,0),(0,.65,0),(0,.2,1),(.6,0,.6)]):
cr.set_source_rgb(*color);cr.set_font_size(18);cr.move_to(60,565+i*28);cr.show_text('Color text 0123456789 - desktop quality test')
elapsed=time.monotonic()-started
for i in range(5):
x=70+((elapsed*220+i*173)%(max(200,width-400)))
cr.set_source_rgb(.1+i*.14,.35,.8-i*.1);cr.rectangle(x,height-280+i*35,120,28);cr.fill()
cr.set_source_rgb(.1,.15,.2);cr.set_font_size(16);cr.move_to(60,height-30)
cr.show_text(f'Source draw rate: {draws/max(.1,elapsed):.2f} FPS; elapsed {elapsed:.1f}s. Close after testing.')
return False
def tick():
global ticks
ticks+=1;area.queue_draw_area(0,max(0,area.get_allocated_height()-300),area.get_allocated_width(),300);return True
def report():
elapsed=time.monotonic()-started
print(json.dumps({'event':'source-stats','seconds':elapsed,'draws':draws,'ticks':ticks,'draw_fps':draws/elapsed}),flush=True);return True
area.connect('draw',draw);win.fullscreen();win.show_all();area.grab_focus()
GLib.timeout_add(16,tick);GLib.timeout_add_seconds(5,report)
print('READY',flush=True);Gtk.main()
@@ -0,0 +1,3 @@
49316 00:00:10 31.4
49316 00:00:35 62.7
Binary file not shown.

After

Width:  |  Height:  |  Size: 364 KiB

@@ -0,0 +1,3 @@
48825 00:00:10 29.7
48825 00:00:35 62.4
Binary file not shown.

After

Width:  |  Height:  |  Size: 402 KiB

@@ -0,0 +1,3 @@
48246 00:01:04 66.2
48246 00:01:29 74.2
Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

@@ -0,0 +1,107 @@
{
"static-text": {
"mean_abs_rgb_difference": [
1.1931075392269421,
0.3489188672024493,
0.5770053578262534
],
"full_rgb_extrema": [
[
0,
255
],
[
0,
255
],
[
0,
255
]
],
"limited_rgb_extrema": [
[
0,
255
],
[
0,
255
],
[
0,
255
]
]
},
"background": {
"mean_abs_rgb_difference": [
1.25989,
0.3125,
0.5
],
"full_rgb_extrema": [
[
245,
246
],
[
247,
248
],
[
254,
255
]
],
"limited_rgb_extrema": [
[
244,
245
],
[
248,
249
],
[
253,
254
]
]
},
"stripes": {
"mean_abs_rgb_difference": [
0.8629375,
0.40147916666666666,
0.9251041666666666
],
"full_rgb_extrema": [
[
0,
255
],
[
0,
255
],
[
0,
255
]
],
"limited_rgb_extrema": [
[
0,
255
],
[
0,
255
],
[
0,
255
]
]
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,3 @@
49732 00:01:03 3.0
49732 00:01:15 3.5
@@ -0,0 +1 @@
{"method": "synthetic F9 injection to decoded video marker in X11 root; includes xdotool startup and polling, excludes physical USB and panel scanout", "samples_ms": [155.707363, 160.165062, 161.74993, 151.641546, 160.943381, 149.877411, 186.379217, 189.858565, 143.675298, 136.966855, 181.810169, 145.660997, 157.279633, 168.322978, 135.966703, 141.853499, 139.798088, 147.296667, 174.832486, 173.398907, 138.442264, 138.570433, 135.947427, 150.334109], "timeouts": [], "p50_ms": 150.9878275, "p95_ms": 186.379217}
Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

@@ -0,0 +1,11 @@
{
"pid": 135145,
"ppid": 92843,
"args": "/home/armbian/vdi-build/rkmpp-experiment/build/moonlight/app/moonlight stream 192.168.1.71 Desktop --resolution 2560x1440 --fps 30 --bitrate 30000 --display-mode fullscreen --video-codec H.264 --video-decoder hardware --absolute-mouse --keep-awake --no-vsync --no-frame-pacing --audio-on-host",
"color_range_override": "0",
"normal_kiosk_entry": true,
"hardware_decode_ready": true,
"egl_renderer": true,
"server_range": "MPEG",
"temporary_benchmark_stopped": true
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

@@ -0,0 +1,3 @@
49732 00:01:58 5.5
49732 00:02:09 6.0
@@ -0,0 +1 @@
{"method": "synthetic F9 injection to decoded video marker in X11 root; includes xdotool startup and polling, excludes physical USB and panel scanout", "samples_ms": [150.01172, 140.54207, 146.622806, 140.651155, 144.384812, 147.6731, 147.065551, 138.139572, 143.82567, 141.994567, 141.890732, 146.535279, 140.382497, 136.103407, 176.574946, 173.033478, 135.687185, 141.140538, 168.252132, 152.002315, 168.699252, 141.007818, 135.567293, 143.323084], "timeouts": [], "p50_ms": 143.574377, "p95_ms": 173.033478}
Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

@@ -0,0 +1,21 @@
[2026:11:04:18:47:42]: Info:
[2026:11:04:18:47:42]: Info: // Ignore any errors mentioned above, they are not relevant. //
[2026:11:04:18:47:42]: Info:
[2026:11:04:18:47:42]: Info: Found H.264 encoder: libx264 [software]
Source ID 249 was not found when attempting to remove it
Source ID 248 was not found when attempting to remove it
[2026:11:04:18:47:42]: Info: CLIENT CONNECTED
[2026:11:04:18:47:42]: Info: Detecting monitors
[2026:11:04:18:47:42]: Info: Detected monitor 0: Virtual-1, connected: true
[2026:11:04:18:47:42]: Info: Screencasting with X11
[2026:11:04:18:47:42]: Info: Configuring selected monitor (0) to stream
[2026:11:04:18:47:42]: Info: Streaming display: Virtual-1 with res 2560x1440 offset by 0x0
[2026:11:04:18:47:42]: Info: SDR color coding [Rec. 601]
[2026:11:04:18:47:42]: Info: Color depth: 8-bit
[2026:11:04:18:47:42]: Info: Color range: [MPEG]
[2026:11:04:18:47:42]: Info: [libx264 @ 0x7f5d64028940] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
[2026:11:04:18:47:42]: Info: [libx264 @ 0x7f5d64028940] profile Constrained Baseline, level 5.0, 4:2:0, 8-bit
[2026:11:04:18:47:43]: Info: Found default monitor by name: vdi_audio.monitor
MainPID=0
ActiveState=inactive
桌面
@@ -0,0 +1,71 @@
{
"final-full-2k30": {
"method": "synthetic F9 injection to decoded video marker in X11 root; includes xdotool startup and polling, excludes physical USB and panel scanout",
"samples_ms": [
155.707363,
160.165062,
161.74993,
151.641546,
160.943381,
149.877411,
186.379217,
189.858565,
143.675298,
136.966855,
181.810169,
145.660997,
157.279633,
168.322978,
135.966703,
141.853499,
139.798088,
147.296667,
174.832486,
173.398907,
138.442264,
138.570433,
135.947427,
150.334109
],
"timeouts": [],
"p50_ms": 150.9878275,
"p95_ms": 186.379217,
"render_fps": 23.35,
"decode_ms": 9.54
},
"final-limited-2k30": {
"method": "synthetic F9 injection to decoded video marker in X11 root; includes xdotool startup and polling, excludes physical USB and panel scanout",
"samples_ms": [
150.01172,
140.54207,
146.622806,
140.651155,
144.384812,
147.6731,
147.065551,
138.139572,
143.82567,
141.994567,
141.890732,
146.535279,
140.382497,
136.103407,
176.574946,
173.033478,
135.687185,
141.140538,
168.252132,
152.002315,
168.699252,
141.007818,
135.567293,
143.323084
],
"timeouts": [],
"p50_ms": 143.574377,
"p95_ms": 173.033478,
"render_fps": 27.25,
"decode_ms": 6.96
},
"interpretation": "Short sequential synthetic input-to-decoded-video proxy, not physical end-to-end latency. Similar ~140-150ms distributions and varying network; no demonstrated large latency improvement or Windows equivalence."
}
@@ -0,0 +1,3 @@
45143 00:19:31 99.0
45143 00:19:51 99.2
Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

@@ -0,0 +1 @@
{"method": "synthetic F9 injection to decoded video marker in X11 root; includes xdotool startup and polling, excludes physical USB and panel scanout", "samples_ms": [183.940229, 161.718547, 160.71209, 138.491578, 141.028294, 141.934718, 154.77252, 163.688624, 125.041352, 179.385106, 179.373316, 178.694809, 185.66681, 177.159603, 189.758573, 151.004259, 149.251196, 165.416771, 157.880119, 159.972861, 179.910412, 189.615124, 185.924098, 140.941751], "timeouts": [], "p50_ms": 162.7035855, "p95_ms": 189.615124}
Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

@@ -0,0 +1,32 @@
import ctypes,ctypes.util,subprocess,os,time,json,statistics
os.environ.update(DISPLAY=':0',XAUTHORITY='/home/armbian/.Xauthority')
x=ctypes.CDLL(ctypes.util.find_library('X11'));x.XOpenDisplay.argtypes=[ctypes.c_char_p];x.XOpenDisplay.restype=ctypes.c_void_p
x.XDefaultRootWindow.argtypes=[ctypes.c_void_p];x.XDefaultRootWindow.restype=ctypes.c_ulong
x.XGetImage.argtypes=[ctypes.c_void_p,ctypes.c_ulong,ctypes.c_int,ctypes.c_int,ctypes.c_uint,ctypes.c_uint,ctypes.c_ulong,ctypes.c_int];x.XGetImage.restype=ctypes.c_void_p
x.XGetPixel.argtypes=[ctypes.c_void_p,ctypes.c_int,ctypes.c_int];x.XGetPixel.restype=ctypes.c_ulong
x.XDestroyImage.argtypes=[ctypes.c_void_p];x.XCloseDisplay.argtypes=[ctypes.c_void_p]
d=x.XOpenDisplay(b':0');assert d;root=x.XDefaultRootWindow(d)
prefix='/home/armbian/vdi-build/rkmpp-experiment/build/moonlight/app/moonlight stream 192.168.1.71 '
items=[l.split(None,1) for l in subprocess.check_output(['ps','-eo','pid,args'],text=True).splitlines()[1:] if len(l.split(None,1))==2 and l.split(None,1)[1].startswith(prefix)]
assert len(items)==1
ids=subprocess.check_output(['xdotool','search','--onlyvisible','--pid',items[0][0],'--class','Moonlight'],text=True).split();assert ids
subprocess.run(['xdotool','windowactivate','--sync',ids[-1]],check=True)
def pixel():
im=x.XGetImage(d,root,2250,130,1,1,0xffffffff,2);assert im
v=x.XGetPixel(im,0,0);x.XDestroyImage(im)
return v&0xffffff
samples=[];errors=[]
for i in range(24):
v=pixel();assert v<0x202020 or v>0xe0e0e0,hex(v)
start=time.monotonic_ns()
subprocess.run(['xdotool','key','--clearmodifiers','--delay','0','F9'],check=True,stdout=subprocess.DEVNULL)
while time.monotonic_ns()-start<2000000000:
cur=pixel()
if (v<0x202020 and cur>0xe0e0e0) or (v>0xe0e0e0 and cur<0x202020):
samples.append((time.monotonic_ns()-start)/1e6);break
time.sleep(.002)
else:errors.append(i)
time.sleep(.12)
x.XCloseDisplay(d)
vals=sorted(samples)
print(json.dumps({'method':'synthetic F9 injection to decoded video marker in X11 root; includes xdotool startup and polling, excludes physical USB and panel scanout','samples_ms':samples,'timeouts':errors,'p50_ms':statistics.median(vals) if vals else None,'p95_ms':vals[min(len(vals)-1,int(len(vals)*.95))] if vals else None}))
@@ -0,0 +1,48 @@
import gi,time,json,math
gi.require_version('Gtk','3.0')
from gi.repository import Gtk,Gdk,GLib
started=time.monotonic(); draws=0; ticks=0; marker=False
win=Gtk.Window(title='VDI Kylin quality benchmark')
win.connect('destroy',Gtk.main_quit)
area=Gtk.DrawingArea();win.add(area)
area.set_events(Gdk.EventMask.BUTTON_PRESS_MASK|Gdk.EventMask.KEY_PRESS_MASK)
area.set_can_focus(True)
def event(w,e):
global marker
if e.type==Gdk.EventType.KEY_PRESS and getattr(e,'keyval',None)==Gdk.KEY_F9:
marker=not marker; area.queue_draw_area(2180,80,220,140)
print(json.dumps({'event':e.type.value_nick,'keyval':getattr(e,'keyval',None),'button':getattr(e,'button',None),'x':getattr(e,'x',None),'y':getattr(e,'y',None),'width':area.get_allocated_width(),'height':area.get_allocated_height(),'t':time.monotonic()}),flush=True)
return False
win.connect('key-press-event',event);area.connect('button-press-event',event)
def draw(w,cr):
global draws
draws+=1; width=w.get_allocated_width();height=w.get_allocated_height()
cr.set_source_rgb(.96,.97,.99);cr.paint()
cr.set_source_rgb(*( (1,1,1) if marker else (0,0,0)));cr.rectangle(2180,80,220,140);cr.fill()
cr.select_font_face('sans');cr.set_font_size(30);cr.set_source_rgb(.08,.12,.18)
cr.move_to(60,65);cr.show_text('VDI Kylin - resolution / text / motion / input verification')
cr.set_font_size(22);cr.move_to(60,105);cr.show_text(f'Native desktop: {width} x {height} Temporary test window')
for row,size in enumerate([12,14,16,18,20,24]):
cr.set_font_size(size);cr.move_to(60,155+row*45);cr.set_source_rgb(.1,.1,.1)
cr.show_text(f'{size}px Cloud desktop 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz')
for i in range(600):
cr.set_source_rgb(0,0,0) if i%2 else cr.set_source_rgb(1,1,1)
cr.rectangle(60+i,445,1,80);cr.fill()
for i,color in enumerate([(1,0,0),(0,.65,0),(0,.2,1),(.6,0,.6)]):
cr.set_source_rgb(*color);cr.set_font_size(18);cr.move_to(60,565+i*28);cr.show_text('Color text 0123456789 - desktop quality test')
elapsed=time.monotonic()-started
for i in range(5):
x=70+((elapsed*220+i*173)%(max(200,width-400)))
cr.set_source_rgb(.1+i*.14,.35,.8-i*.1);cr.rectangle(x,height-280+i*35,120,28);cr.fill()
cr.set_source_rgb(.1,.15,.2);cr.set_font_size(16);cr.move_to(60,height-30)
cr.show_text(f'Source draw rate: {draws/max(.1,elapsed):.2f} FPS; elapsed {elapsed:.1f}s. Close after testing.')
return False
def tick():
global ticks
ticks+=1;area.queue_draw_area(0,max(0,area.get_allocated_height()-300),area.get_allocated_width(),300);return True
def report():
elapsed=time.monotonic()-started
print(json.dumps({'event':'source-stats','seconds':elapsed,'draws':draws,'ticks':ticks,'draw_fps':draws/elapsed}),flush=True);return True
area.connect('draw',draw);win.fullscreen();win.show_all();area.grab_focus()
GLib.timeout_add(16,tick);GLib.timeout_add_seconds(5,report)
print('READY',flush=True);Gtk.main()
@@ -0,0 +1,3 @@
45143 00:20:22 97.2
45143 00:20:43 97.4
Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

@@ -0,0 +1,3 @@
47776 00:00:09 44.8
47776 00:00:28 70.9
Binary file not shown.

After

Width:  |  Height:  |  Size: 388 KiB

@@ -0,0 +1,19 @@
MainPID=49732
ActiveState=active
sunshine_name = VDI-Kylin
capture = x11
encoder = software
sw_preset = ultrafast
sw_tune = zerolatency
upnp = disabled
origin_web_ui_allowed = pc
hevc_mode = 1
audio_sink = vdi_audio
Screen 0: minimum 320 x 200, current 2560 x 1440, maximum 8192 x 8192
Virtual-1 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 325mm x 203mm
1280x800 74.99 +
3840x2160 60.00 50.00 59.94
1920x1440 60.00
2560x1080 50.00
1856x1392 60.00
(<false>,)
@@ -0,0 +1 @@
{"removed_unused_trials": ["sunshine-v0.21.0-vdi-bgra", "sunshine-v0.21.0-vdi-bgra-fullchroma", "sunshine-v0.21.0-vdi-bgra-bilinear"], "original_sha256": "1c3099bf924db3aee759b3d7c05e012569ef8650c400d1479144398795decc71"}
@@ -0,0 +1,10 @@
{
"source": "software CPU clock perf_event_open 10ms period, 4 seconds; top80 addresses only",
"build_sha256": "1c3099bf924db3aee759b3d7c05e012569ef8650c400d1479144398795decc71",
"top80_groups_approx": {
"static_ffmpeg_conversion_approx": 140,
"other": 36,
"static_x264_approx": 34
},
"warning": "Approximate stripped ELF ranges; not exact function timing. Scalar color-range loop disassembled at 0x8e8490 and RGB chroma loop at 0x8fb330."
}
@@ -0,0 +1,59 @@
{
"trials": [
{
"label": "fullrange-2k45",
"render_fps": 21.42,
"decode_ms": 7.48,
"queue_ms": 0.15,
"render_ms": 2.07,
"network_drop_pct": 0.0,
"jitter_drop_pct": 1.05
},
{
"label": "limitedrange-2k45",
"render_fps": 28.81,
"decode_ms": 6.9,
"queue_ms": 0.23,
"render_ms": 2.02,
"network_drop_pct": 0.0,
"jitter_drop_pct": 0.81
},
{
"label": "limitedrange-thread2-2k45",
"render_fps": 25.67,
"decode_ms": 7.09,
"queue_ms": 0.12,
"render_ms": 2.01,
"network_drop_pct": 0.0,
"jitter_drop_pct": 0.99
},
{
"label": "bgra-limited-2k45-valid",
"render_fps": 27.17,
"decode_ms": 6.85,
"queue_ms": 0.11,
"render_ms": 2.01,
"network_drop_pct": 0.0,
"jitter_drop_pct": 0.78
},
{
"label": "bgra-fullchroma-limited-2k45",
"render_fps": 25.61,
"decode_ms": 10.38,
"queue_ms": 0.13,
"render_ms": 2.03,
"network_drop_pct": 0.0,
"jitter_drop_pct": 1.72
},
{
"label": "bgra-bilinear-limited-2k45",
"render_fps": 30.79,
"decode_ms": 7.44,
"queue_ms": 0.13,
"render_ms": 1.93,
"network_drop_pct": 0.0,
"jitter_drop_pct": 1.12
}
],
"note": "2K45 request, 30Mbps H264, same partial-motion 60fps source. Short sequential tests, network variation. Only original binary + limited range retained; all binary experiments and 2 threads reverted. Inputecho baseline incomplete after stream deadline and subsequent Windows connection; exclude from paired latency claims."
}
@@ -0,0 +1 @@
{"192.168.1.71": "0", "192.168.1.70": "unset", "192.168.1.72": "unset", "explicit override": "1", "invalid rejected": 78}
@@ -0,0 +1,3 @@
169194 00:06:35 9.7
169194 00:06:59 10.3
Binary file not shown.

After

Width:  |  Height:  |  Size: 684 KiB

@@ -0,0 +1,3 @@
179730 00:00:09 8.7
179730 00:00:34 26.2
Binary file not shown.

After

Width:  |  Height:  |  Size: 686 KiB

@@ -0,0 +1,3 @@
180224 00:00:11 46.2
180224 00:00:36 74.1
Binary file not shown.

After

Width:  |  Height:  |  Size: 685 KiB

@@ -0,0 +1,3 @@
180438 00:00:09 42.7
180438 00:00:35 74.5
Binary file not shown.

After

Width:  |  Height:  |  Size: 771 KiB

@@ -0,0 +1,3 @@
180841 00:00:10 42.4
180841 00:00:37 74.1
Binary file not shown.

After

Width:  |  Height:  |  Size: 688 KiB

@@ -0,0 +1,23 @@
Screen 0: minimum 320 x 200, current 2560 x 1440, maximum 8192 x 8192
Virtual-1 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 325mm x 203mm
1280x800 74.99 +
3840x2160 60.00 50.00 59.94
1920x1440 60.00
2560x1080 50.00
1856x1392 60.00
1792x1344 60.00
2048x1152 60.00
1920x1200 59.88
1920x1080 60.00 50.00
1600x1200 60.00
1680x1050 59.95
1400x1050 59.98
1280x1024 60.02
1440x900 59.89
1280x960 60.00
1360x768 60.02
1280x768 59.87
1024x768 60.00
800x600 60.32
640x480 60.00 59.94
2560x1440_60.00 59.95*
@@ -0,0 +1,7 @@
{
"F8_received": 2,
"alternating_clicks_correct": 48,
"native_width": 2560,
"native_height": 1440,
"coordinate_error_bound_px": 1
}
@@ -0,0 +1,3 @@
16379 00:01:07 47.7
16379 00:01:35 57.3
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

@@ -0,0 +1,3 @@
25194 00:00:09 30.2
25194 00:00:34 58.6
Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

@@ -0,0 +1,3 @@
42266 00:00:59 35.0
42266 00:01:21 43.1
Binary file not shown.

After

Width:  |  Height:  |  Size: 376 KiB

@@ -0,0 +1,3 @@
42266 00:00:09 43.6
42266 00:00:30 73.2
Binary file not shown.

After

Width:  |  Height:  |  Size: 376 KiB

@@ -0,0 +1,3 @@
25194 00:01:01 0.8
25194 00:01:20 1.1
Binary file not shown.

After

Width:  |  Height:  |  Size: 378 KiB

@@ -0,0 +1,3 @@
16379 00:00:12 46.0
16379 00:00:37 71.3
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

@@ -0,0 +1,44 @@
import gi,time,json,math
gi.require_version('Gtk','3.0')
from gi.repository import Gtk,Gdk,GLib
started=time.monotonic(); draws=0; ticks=0
win=Gtk.Window(title='VDI Kylin quality benchmark')
win.connect('destroy',Gtk.main_quit)
area=Gtk.DrawingArea();win.add(area)
area.set_events(Gdk.EventMask.BUTTON_PRESS_MASK|Gdk.EventMask.KEY_PRESS_MASK)
area.set_can_focus(True)
def event(w,e):
print(json.dumps({'event':e.type.value_nick,'keyval':getattr(e,'keyval',None),'button':getattr(e,'button',None),'x':getattr(e,'x',None),'y':getattr(e,'y',None),'width':area.get_allocated_width(),'height':area.get_allocated_height(),'t':time.monotonic()}),flush=True)
return False
win.connect('key-press-event',event);area.connect('button-press-event',event)
def draw(w,cr):
global draws
draws+=1; width=w.get_allocated_width();height=w.get_allocated_height()
cr.set_source_rgb(.96,.97,.99);cr.paint()
cr.select_font_face('sans');cr.set_font_size(30);cr.set_source_rgb(.08,.12,.18)
cr.move_to(60,65);cr.show_text('VDI Kylin - resolution / text / motion / input verification')
cr.set_font_size(22);cr.move_to(60,105);cr.show_text(f'Native desktop: {width} x {height} Temporary test window')
for row,size in enumerate([12,14,16,18,20,24]):
cr.set_font_size(size);cr.move_to(60,155+row*45);cr.set_source_rgb(.1,.1,.1)
cr.show_text(f'{size}px Cloud desktop 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz')
for i in range(600):
cr.set_source_rgb(0,0,0) if i%2 else cr.set_source_rgb(1,1,1)
cr.rectangle(60+i,445,1,80);cr.fill()
for i,color in enumerate([(1,0,0),(0,.65,0),(0,.2,1),(.6,0,.6)]):
cr.set_source_rgb(*color);cr.set_font_size(18);cr.move_to(60,565+i*28);cr.show_text('Color text 0123456789 - desktop quality test')
elapsed=time.monotonic()-started
for i in range(5):
x=70+((elapsed*220+i*173)%(max(200,width-400)))
cr.set_source_rgb(.1+i*.14,.35,.8-i*.1);cr.rectangle(x,height-280+i*35,120,28);cr.fill()
cr.set_source_rgb(.1,.15,.2);cr.set_font_size(16);cr.move_to(60,height-30)
cr.show_text(f'Source draw rate: {draws/max(.1,elapsed):.2f} FPS; elapsed {elapsed:.1f}s. Close after testing.')
return False
def tick():
global ticks
ticks+=1;area.queue_draw_area(0,max(0,area.get_allocated_height()-300),area.get_allocated_width(),300);return True
def report():
elapsed=time.monotonic()-started
print(json.dumps({'event':'source-stats','seconds':elapsed,'draws':draws,'ticks':ticks,'draw_fps':draws/elapsed}),flush=True);return True
area.connect('draw',draw);win.fullscreen();win.show_all();area.grab_focus()
GLib.timeout_add(16,tick);GLib.timeout_add_seconds(5,report)
print('READY',flush=True);Gtk.main()
@@ -0,0 +1,44 @@
import gi,time,json,math
gi.require_version('Gtk','3.0')
from gi.repository import Gtk,Gdk,GLib
started=time.monotonic(); draws=0; ticks=0
win=Gtk.Window(title='VDI Kylin quality benchmark')
win.connect('destroy',Gtk.main_quit)
area=Gtk.DrawingArea();win.add(area)
area.set_events(Gdk.EventMask.BUTTON_PRESS_MASK|Gdk.EventMask.KEY_PRESS_MASK)
area.set_can_focus(True)
def event(w,e):
print(json.dumps({'event':e.type.value_nick,'keyval':getattr(e,'keyval',None),'button':getattr(e,'button',None),'x':getattr(e,'x',None),'y':getattr(e,'y',None),'width':area.get_allocated_width(),'height':area.get_allocated_height(),'t':time.monotonic()}),flush=True)
return False
win.connect('key-press-event',event);area.connect('button-press-event',event)
def draw(w,cr):
global draws
draws+=1; width=w.get_allocated_width();height=w.get_allocated_height()
cr.set_source_rgb(.96,.97,.99);cr.paint()
cr.select_font_face('sans');cr.set_font_size(30);cr.set_source_rgb(.08,.12,.18)
cr.move_to(60,65);cr.show_text('VDI Kylin - resolution / text / motion / input verification')
cr.set_font_size(22);cr.move_to(60,105);cr.show_text(f'Native desktop: {width} x {height} Temporary test window')
for row,size in enumerate([12,14,16,18,20,24]):
cr.set_font_size(size);cr.move_to(60,155+row*45);cr.set_source_rgb(.1,.1,.1)
cr.show_text(f'{size}px Cloud desktop 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz')
for i in range(600):
cr.set_source_rgb(0,0,0) if i%2 else cr.set_source_rgb(1,1,1)
cr.rectangle(60+i,445,1,80);cr.fill()
for i,color in enumerate([(1,0,0),(0,.65,0),(0,.2,1),(.6,0,.6)]):
cr.set_source_rgb(*color);cr.set_font_size(18);cr.move_to(60,565+i*28);cr.show_text('Color text 0123456789 - desktop quality test')
elapsed=time.monotonic()-started
for i in range(5):
x=70+((elapsed*220+i*173)%(max(200,width-400)))
cr.set_source_rgb(.1+i*.14,.35,.8-i*.1);cr.rectangle(x,height-280+i*35,120,28);cr.fill()
cr.set_source_rgb(.1,.15,.2);cr.set_font_size(16);cr.move_to(60,height-30)
cr.show_text(f'Source draw rate: {draws/max(.1,elapsed):.2f} FPS; elapsed {elapsed:.1f}s. Close after testing.')
return False
def tick():
global ticks
ticks+=1;area.queue_draw();return True
def report():
elapsed=time.monotonic()-started
print(json.dumps({'event':'source-stats','seconds':elapsed,'draws':draws,'ticks':ticks,'draw_fps':draws/elapsed}),flush=True);return True
area.connect('draw',draw);win.fullscreen();win.show_all();area.grab_focus()
GLib.timeout_add(16,tick);GLib.timeout_add_seconds(5,report)
print('READY',flush=True);Gtk.main()
@@ -0,0 +1 @@
{"updated": {"app": "Desktop", "endpoint": "192.168.1.71", "fps": 30, "height": 1440, "id": "desk-kylin-01", "name": "麒麟", "os": "银河麒麟桌面", "width": 2560}, "other_desktop_objects_unchanged": true}
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

@@ -0,0 +1,27 @@
active
enabled
inactive
Screen 0: minimum 320 x 200, current 2560 x 1440, maximum 8192 x 8192
Virtual-1 connected primary 2560x1440+0+0 (normal left inverted right x axis y axis) 325mm x 203mm
1280x800 74.99 +
3840x2160 60.00 50.00 59.94
1920x1440 60.00
(<false>,)
[2026:11:04:17:36:00]: Info: [libx264 @ 0x7fa2e81c4300] kb/s:3306.24
[2026:11:04:17:36:00]: Info: // Testing for available encoders, this may generate errors. You can safely ignore those errors. //
[2026:11:04:17:36:00]: Info:
[2026:11:04:17:36:00]: Info: // Ignore any errors mentioned above, they are not relevant. //
[2026:11:04:17:36:00]: Info:
[2026:11:04:17:36:00]: Info: Found H.264 encoder: libx264 [software]
[2026:11:04:17:36:00]: Info: CLIENT CONNECTED
[2026:11:04:17:36:00]: Info: Detecting monitors
[2026:11:04:17:36:00]: Info: Detected monitor 0: Virtual-1, connected: true
[2026:11:04:17:36:00]: Info: Screencasting with X11
[2026:11:04:17:36:00]: Info: Configuring selected monitor (0) to stream
[2026:11:04:17:36:00]: Info: Streaming display: Virtual-1 with res 2560x1440 offset by 0x0
[2026:11:04:17:36:00]: Info: SDR color coding [Rec. 601]
[2026:11:04:17:36:00]: Info: Color depth: 8-bit
[2026:11:04:17:36:00]: Info: Color range: [JPEG]
[2026:11:04:17:36:00]: Info: [libx264 @ 0x7fa2fc00e6c0] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
[2026:11:04:17:36:00]: Info: [libx264 @ 0x7fa2fc00e6c0] profile Constrained Baseline, level 5.0, 4:2:0, 8-bit
[2026:11:04:17:36:00]: Info: Found default monitor by name: vdi_audio.monitor
@@ -0,0 +1,20 @@
[
{
"attempt": 1,
"normal_kiosk": true,
"width": 2560,
"height": 1440,
"configured_fps": 30,
"bitrate_kbps": 30000,
"hardware_decode_ready": true
},
{
"attempt": 2,
"normal_kiosk": true,
"width": 2560,
"height": 1440,
"configured_fps": 30,
"bitrate_kbps": 30000,
"hardware_decode_ready": true
}
]
@@ -0,0 +1,9 @@
sunshine_name = VDI-Kylin
capture = x11
encoder = software
sw_preset = ultrafast
sw_tune = zerolatency
upnp = disabled
origin_web_ui_allowed = pc
hevc_mode = 1
audio_sink = vdi_audio
@@ -0,0 +1,20 @@
[Unit]
Description=VDI Linux desktop Sunshine host
PartOf=graphical-session.target
After=graphical-session.target
[Service]
Environment=DISPLAY=:0 XAUTHORITY=/home/test1/.Xauthority
ExecStartPre=/bin/sh -c '/usr/bin/xrandr --query | grep -q 2560x1440_60.00 || /usr/bin/xrandr --newmode 2560x1440_60.00 241.50 2560 2608 2640 2720 1440 1443 1448 1481 +hsync -vsync'
ExecStartPre=/usr/bin/xrandr --addmode Virtual-1 2560x1440_60.00
ExecStartPre=/usr/bin/xrandr --output Virtual-1 --mode 2560x1440_60.00
ExecStartPre=/bin/sh -c 'pactl list short sinks | grep -qw vdi_audio || pactl load-module module-null-sink sink_name=vdi_audio sink_properties=device.description=VDI-Audio'
ExecStartPre=/usr/bin/pactl set-default-sink vdi_audio
ExecStart=/opt/vdi-sunshine-0.21.0/usr/bin/sunshine /home/test1/.config/sunshine/sunshine.conf
ExecStartPost=-/usr/bin/gdbus call --session --dest org.ukui.KWin --object-path /Compositor --method org.ukui.kwin.Compositing.suspend
ExecStopPost=-/usr/bin/gdbus call --session --dest org.ukui.KWin --object-path /Compositor --method org.ukui.kwin.Compositing.resume
Restart=on-failure
RestartSec=5
[Install]
WantedBy=graphical-session.target
@@ -0,0 +1,9 @@
sunshine_name = VDI-Kylin
capture = x11
encoder = software
sw_preset = ultrafast
sw_tune = zerolatency
upnp = disabled
origin_web_ui_allowed = pc
hevc_mode = 1
audio_sink = vdi_audio
Whitespace-only changes.
@@ -0,0 +1,104 @@
[
{
"trial": "1080p30-baseline",
"valid_for_performance": true,
"Rendering frame rate": "28.63 FPS",
"Average decoding time": "4.95 ms",
"Average frame queue delay": "0.17 ms",
"Average rendering time (including monitor V-sync latency)": "1.69 ms",
"Average network latency": "24 ms (variance: 27 ms)"
},
{
"trial": "1080p45-compositor",
"valid_for_performance": true,
"Rendering frame rate": "29.56 FPS",
"Average decoding time": "5.10 ms",
"Average frame queue delay": "0.25 ms",
"Average rendering time (including monitor V-sync latency)": "1.68 ms",
"Average network latency": "11 ms (variance: 7 ms)"
},
{
"trial": "1080p45-no-compositor-retry",
"valid_for_performance": true,
"Rendering frame rate": "31.86 FPS",
"Average decoding time": "5.98 ms",
"Average frame queue delay": "0.16 ms",
"Average rendering time (including monitor V-sync latency)": "1.64 ms",
"Average network latency": "4 ms (variance: 4 ms)"
},
{
"trial": "1080p45-superfast-threads2",
"valid_for_performance": true,
"Rendering frame rate": "27.84 FPS",
"Average decoding time": "7.18 ms",
"Average frame queue delay": "0.18 ms",
"Average rendering time (including monitor V-sync latency)": "1.65 ms",
"Average network latency": "5 ms (variance: 2 ms)"
},
{
"trial": "1080p45-ultrafast-threads2",
"valid_for_performance": true,
"Rendering frame rate": "32.44 FPS",
"Average decoding time": "4.82 ms",
"Average frame queue delay": "0.23 ms",
"Average rendering time (including monitor V-sync latency)": "1.60 ms",
"Average network latency": "2 ms (variance: 1 ms)"
},
{
"trial": "2k30-damage-thread1",
"valid_for_performance": false,
"excluded_reason": "lock screen or interrupted/unverified scene",
"Rendering frame rate": "21.81 FPS",
"Average decoding time": "7.74 ms",
"Average frame queue delay": "0.21 ms",
"Average rendering time (including monitor V-sync latency)": "1.95 ms",
"Average network latency": "8 ms (variance: 1 ms)"
},
{
"trial": "2k30-damage-thread2",
"valid_for_performance": false,
"excluded_reason": "lock screen or interrupted/unverified scene",
"Rendering frame rate": "19.38 FPS",
"Average decoding time": "8.69 ms",
"Average frame queue delay": "0.21 ms",
"Average rendering time (including monitor V-sync latency)": "2.01 ms",
"Average network latency": "4 ms (variance: 1 ms)"
},
{
"trial": "2k30-desktop-no-compositor-valid",
"valid_for_performance": true,
"Rendering frame rate": "22.97 FPS",
"Average decoding time": "9.04 ms",
"Average frame queue delay": "0.12 ms",
"Average rendering time (including monitor V-sync latency)": "2.11 ms",
"Average network latency": "9 ms (variance: 6 ms)"
},
{
"trial": "2k30-desktop-thread1-valid",
"valid_for_performance": true,
"Rendering frame rate": "18.89 FPS",
"Average decoding time": "14.13 ms",
"Average frame queue delay": "0.09 ms",
"Average rendering time (including monitor V-sync latency)": "2.12 ms",
"Average network latency": "10 ms (variance: 8 ms)"
},
{
"trial": "2k30-desktop-thread2-valid",
"valid_for_performance": true,
"Rendering frame rate": "18.85 FPS",
"Average decoding time": "8.96 ms",
"Average frame queue delay": "0.29 ms",
"Average rendering time (including monitor V-sync latency)": "2.12 ms",
"Average network latency": "5 ms (variance: 1 ms)"
},
{
"trial": "2k30-ultrafast-thread1",
"valid_for_performance": false,
"excluded_reason": "lock screen or interrupted/unverified scene",
"Rendering frame rate": "14.12 FPS",
"Average decoding time": "12.11 ms",
"Average frame queue delay": "0.12 ms",
"Average rendering time (including monitor V-sync latency)": "2.10 ms",
"Average network latency": "4 ms (variance: 2 ms)"
}
]
@@ -0,0 +1,10 @@
{
"vmid": 101,
"name": "kylin-test",
"before_vga": null,
"apply_vga": "std,memory=64",
"requires": "graceful shutdown to stopped, then start",
"rollback_vga": "delete explicit vga field (restore default)",
"other_fields": "preserve",
"reboot_other_machines": false
}
@@ -0,0 +1,23 @@
{
"ostype": "l26",
"cores": 2,
"scsi0": "local-lvm:vm-101-disk-0,discard=on,iothread=1,size=50G",
"scsihw": "virtio-scsi-single",
"onboot": 1,
"sockets": 1,
"digest": "5e371a9964bee0ea2acf3265409281aae89c9ffc",
"memory": "4096",
"boot": "order=scsi0;ide2;net0",
"net0": "virtio=BC:24:11:25:29:40,bridge=vmbr0,firewall=1",
"vmgenid": "cc8ff198-c228-4ac6-8c37-918d4978b79b",
"balloon": 0,
"name": "kylin-test",
"cpu": "host",
"numa": 0,
"bios": "seabios",
"ide2": "none,media=cdrom",
"agent": "1",
"smbios1": "uuid=8ca270ad-7f1a-4da0-97f2-99a94eef9400",
"meta": "creation-qemu=11.0.3,ctime=1793090566",
"machine": "q35"
}
@@ -0,0 +1,6 @@
{
"vga": {
"before": null,
"after": "std,memory=64"
}
}
@@ -0,0 +1,22 @@
[
{
"phase": "precheck",
"status": "running",
"vga": null,
"digest": "5e371a9964bee0ea2acf3265409281aae89c9ffc"
},
{
"phase": "graceful_shutdown_requested"
},
{
"phase": "stopped"
},
{
"phase": "vram_configured",
"vga": "std,memory=64"
},
{
"phase": "started",
"vga": "std,memory=64"
}
]
@@ -0,0 +1,44 @@
use_type: 1
use_tt: 0
size: 4096
0x0000000000000000-0x000000000000012c: 300: free
0x000000000000012c-0x0000000000000915: 2025: used
0x0000000000000915-0x0000000000001000: 1771: free
total: 4096, used 2025 free 2071
framebuffer[39]:
allocated by = Xorg
refcount=2
format=XR24 little-endian (0x34325258)
modifier=0x0
size=1920x1080
layers:
size[0]=1920x1080
pitch[0]=7680
offset[0]=0
obj[0]:
name=0
refcount=2
start=001007d4
size=8294400
imported=no
placement=(none)
bus.offset=fc12c000
framebuffer[36]:
allocated by = [fbcon]
refcount=1
format=XR24 little-endian (0x34325258)
modifier=0x0
size=1280x800
layers:
size[0]=1280x800
pitch[0]=5120
offset[0]=0
obj[0]:
name=0
refcount=3
start=00100000
size=4096000
imported=no
placement=(none)
name size handles refcount
Y