Skip to content

HSVフィルタをアプリ層GPUシェーダへ移行(コア無改変で60fps維持)#14

Merged
bubio merged 1 commit into
mainfrom
hsv-gpu-filter
Jun 11, 2026
Merged

HSVフィルタをアプリ層GPUシェーダへ移行(コア無改変で60fps維持)#14
bubio merged 1 commit into
mainfrom
hsv-gpu-filter

Conversation

@bubio

@bubio bubio commented Jun 11, 2026

Copy link
Copy Markdown
Owner

概要

NP2kai コアの HSV-smooth ビデオフィルタは CPU でエミュフレームごとに実行されていた。catch-up / No-Wait スケジューラ下では生成フレーム全て(最大16x)に適用され、単一の全画面パスでも Ryzen 5 2600 で約27ms かかるため、HSV ON 時のフレームレートが Windows で一桁、macOS の No-Wait で一桁まで落ちていた。

このフィルタを GPU フラグメントシェーダのパスとして再実装し、ui.display_hsv で描画時に切り替える。NP2kai コアのフィルタは無効化し、コアのソースは無改変(upstream マージを楽に保つ)。HSV ON でも 60fps を完全維持できるようになった。

変更点

  • HSVフィルタのGPU化: src/platform/shaders/blit_hsv.fs.{hlsl,metal,glsl} を追加。最終フレームバッファに対し 3x3 近傍を HSV 空間で許容差(dH=30, dS=30, dV=90)平滑化(VideoFilter_HSVSmooth 相当, weight type 0 を移植)。platform.os.shader_fs_hsv_source を3OSで公開し、main.zig で2つ目のパイプライン pipeline_hsv を切替。
  • フレーム描画間引き: 1ホストフレームで描画(=フィルタ)するのは最後のエミュフレームだけに。中間フレームは表示されないため、重い描画パスが「提示フレームあたり1回」になる。
  • FPS表示のウィンドウ平均化: 瞬間値 1/Δt(〜60Hzの描画ゲートとビートして三桁に暴れる)を約0.5秒ウィンドウの平均に変更し、信頼できる表示に。

補足

  • 見た目は本家とわずかに異なる(パレット段でなく最終RGB段で平滑化するため)が、エッジがより自然。
  • 未使用になったコア連携関数(usa_setup_video_filter / usa_set_video_filter)は無害なため残置。

テスト

  • zig build -Doptimize=ReleaseFast 通過
  • zig build test 通過
  • 実機(Windows / Ryzen 5 2600 + GTX 1660)で HSV ON 時 60fps 維持を確認

既知の残課題(別件)

  • HSV ON→OFF 後に残るフレーム間隔ジッタ(59.94Hz スケジューラ vs 60Hz present の干渉)。frame_scheduler.zig へのヒステリシス追加で対応可能。本PRのスコープ外。

🤖 Generated with Claude Code

The NP2kai HSV-smooth video filter ran per emulated frame on the CPU. Under
the catch-up / No-Wait frame scheduler it was applied to every generated
frame (up to 16x), and even a single full-screen pass was ~27ms on a Ryzen 5
2600 — collapsing HSV-on frame rates to single digits on Windows and under
No-Wait on macOS.

Reimplement the filter as a GPU fragment-shader pass (blit_hsv.fs.{hlsl,metal,
glsl}), selected at draw time via ui.display_hsv. The NP2kai core video filter
is left disabled and the core source is unmodified, keeping upstream merges
clean. HSV-on now holds a solid 60fps.

Also:
- frame(): only the last emulated frame of each host tick is drawn, so the
  expensive draw pass runs once per presented frame instead of once per
  emulated frame (the intermediate frames are never displayed).
- FPS readout: average presented frames over a ~0.5s window instead of an
  instantaneous 1/dt sample, which beat against the ~60Hz draw gate into
  misleading 3-digit spikes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@bubio bubio merged commit f16b138 into main Jun 11, 2026
3 checks passed
@bubio bubio deleted the hsv-gpu-filter branch June 11, 2026 05:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant