Questアプリ、着脱でGPUメモリ630MB増|被らず再現

週末起業ラボのアイキャッチ画像:Quest 3の自作アプリでヘッドセットの着け外しごとに増えるGPUメモリを追った記録 プログラミング

自作のQuest 3アプリで、ヘッドセットを外して着け直すたびに、GPUのメモリが約630MB増えていた。4回着け外しすると、起動直後に790MBだったものが4.58GBになる。

原因はUnityのOpenXR設定「Optimize Buffer Discards (Vulkan)」が無効になっていたことだと見ている。有効にしたあとは、同じ4回で160MBから171MBまでしか増えなくなった。

切り分けで効いたのは、ヘッドセットを被らずに「外した」「着けた」をPCから起こす手順だった。最初は別の操作が原因だと取り違えていたので、その経緯も含めて書く。

TL;DR / 三行要約 6分 MIN READ · UPDATED 2026-10-23
  1. ヘッドセットを外して着け直すたびに、GPUメモリが約630MB増えていた。
  2. adbで近接センサーの状態を送り、被らずに着け外しを再現して測った。
  3. OpenXRの「Optimize Buffer Discards (Vulkan)」を有効にして、増加がほぼ止まった。
RESULT — 着け外し4回で4.58GB→171MB TOOL — Unity / Claude Code / adb

外して着け直すたびに、630MB増えていた

Claude Codeで4週間作っているQuest 3アプリ

2026年9月26日から、Quest 3で動く自作アプリをClaude Codeと作っている。10月23日時点でコミットは297、コミットがあった日は19日だ。コードもコミットもほぼClaude Codeに任せていて、筆者が決めているのは作る方針と動作の良し悪し、それにQuestの実機で動きを確かめることだ。

使っている本体は、2年前に中古で買ったQuest 3だ。週1回か隔週1回しか被らなくなっていたが、開発を始めてからはほぼ毎日、動作確認で被っている。

環境はUnity 6000.6.3f1、Meta XR Core SDK 207.0.0、OpenXR 1.18.0。ビルドには8〜25分かかり、できたAPKをadbでQuestに入れて確かめる。1回の確認に時間がかかるので、実機で起きる問題ほど追うのが重い。

測ったのはdumpsysのGL mtrack

GPUのメモリは、Androidのdumpsys meminfoで見た。Questの中身はAndroidなので、PCからadbで次のように打てばアプリのメモリの内訳が出る。

adb shell dumpsys meminfo <パッケージ名>

見たのは内訳のうち「GL mtrack」の行だ。Androidの公式ドキュメントは、この行が何を表すかまでは説明していない。ここでは、グラフィックス用に確保されたメモリの目安として見ている。

2026年10月4日の記録では、ヘッドセットを外して着け直すたびに、この値が約630MB増えていた。ときには倍の約1.26GB増えることもあった。4回の着け外しで790MBから4.58GBになっている。

Androidは、メモリが足りなくなるとlmkd(low memory killer daemon)が優先度の低いプロセスから終了させる。着け外しのたびに数百MBずつ増える作りだと、使い続けるうちにアプリが落とされかねない。

最初は、別の操作のせいだと思っていた

2つのことが同時に起きていた

最初は、パススルー(周りの現実の映像を映す機能)の切り替えが原因だと見ていた。このアプリでは、パススルーの切り替えと、ヘッドセットの着け外しが同じタイミングで起きていた。増えた瞬間に起きていたことが2つあり、目立つほうを犯人にしてしまった。

ムラサキ
ムラサキ

同時に起きたことが2つあると、つい目立つほうを疑ってしまう。片方だけを起こして測れる手順があれば、最初から切り分けられた。

数字の読み違いで遠回りしたのは、これが初めてではない。ブログの自動リライトでも、Search Consoleの「CTR 0%」の正体が目次リンクだったことに気づくまで、別の原因を疑っていた。

被らずに「外した」「着けた」を起こす

着け外しのたびに実際に被っていると、測るたびに手間がかかるうえ、ほかの操作も混ざる。そこで、PCからadbで近接センサーの状態を送り、被らずに着け外しを起こすようにした。

筆者の環境で動作確認済み(Windows 11・Meta Quest 3・2026年10月)。Metaの公式ドキュメントで見つけた手順ではなく、手元で試して動いた方法だ。

# 外したことにする(約28秒待つ)
adb shell am broadcast -a com.oculus.vrpowermanager.prox_far

# 着けたことにする(約18秒待つ)
adb shell am broadcast -a com.oculus.vrpowermanager.prox_close

# 作業が終わったら必ず送る(センサーの上書きを解除する)
adb shell am broadcast -a com.oculus.vrpowermanager.automation_disable

外したことにすると、15秒ほどで画面が消え、そのあとアプリが一時停止の状態になる。着けたことにすると、アプリが再開し、装着状態が変わったという通知がアプリに届く。待ち時間は、この切り替わりが終わるのを待つためだ。

最後の1行は忘れやすい。送らないと、近接センサーの状態が上書きされたまま残る。2026年10月7日に実際にこれをやり、ヘッドセットを被っているのに約15秒でスリープするようになった。

設定1つで、増えなくなった

Optimize Buffer Discards (Vulkan) を有効にする

効いたのは、UnityのOpenXRの設定「Optimize Buffer Discards (Vulkan)」だった。ただ、Project Settingsの「XR Plug-in Management」→「OpenXR」→ Androidのタブを開いても、この項目のチェック欄は出てこなかった。

UnityのOpenXR設定のAndroidタブ。Render ModeからOffscreen Rendering Only (Vulkan)までが並び、Optimize Buffer Discards (Vulkan)の欄は無い

Unityの画面でこのチェック欄が出るのは、同じAndroidのタブの機能一覧で「Meta Quest Support」を有効にし、その歯車から設定を開いたときだけだ。筆者のプロジェクトではMeta Quest Supportを使っていない。そこで、設定ファイル Assets/XR/Settings/OpenXR Package Settings.asset のAndroid向けの設定にある m_optimizeBufferDiscards を 0 から 1 に書き換えた。変更はこの1行だけだ。

同じファイルの中で、Meta Quest Support側の同名の値は、書き換える前から 1 になっていた。それでも増え続けていたので、Meta Quest Supportを無効にしている構成では、そちらの値は効いていなかったと見ている。Meta Quest Supportを使っているなら、画面のチェック欄で済むはずだ。

Metaの開発者向けドキュメントによると、QuestのGPUでは、MSAA(アンチエイリアスの一種)用のバッファをメインメモリに置かずに済ませられる。この設定はその仕組みを使うもので、Quest 3の標準解像度で4x MSAAなら、片目あたり約90MB、両目で約180MBの節約になるとしている。

有効にしてから、同じ手順で測り直した。値はGPUメモリ(dumpsys meminfoのGL mtrack)で、2026年10月4日の実測だ。

計測した時点対策前対策後
起動直後790MB160MB
4回着け外し後4,580MB171MB

4回の着け外しで増えたのは約11MBで、1回あたりにすると2〜4MBだ。起動直後の値も790MBから160MBに下がった。

原因は「推定」のまま

このアプリの画質設定(Medium)ではMSAAが4xになっている。着け外しのたびに約630MBずつ増え、MSAA用のバッファを扱う設定を有効にしたら増えなくなった。ここから、着け直すたびにMSAA用の描画先が作り直され、古いものが解放されずに残っていたと見ている。

ただし、解放されていないことを直接確かめたログは無い。Metaのドキュメントにある節約量(両目で約180MB)と、1回あたり約630MBという増え方の大きさも、まだ結び付けて説明できていない。状況から一番筋が通る原因、というところまでだ。

有効にする前に知っておきたいこと

Metaのドキュメントは「ほぼすべてのMeta Questアプリで有効にすべき」としている。一方で、Unityには、この設定とフォービエイテッドレンダリングを両方オンにすると、描画を拡張する機能(Scriptable Renderer Feature)が崩れるという不具合報告がある。報告の対象はOpenXR 1.15.1〜1.16.0-pre.2で、状態は「Won’t Fix」で閉じられている。描画を自分で拡張しているなら、有効にしたあとに見た目が崩れていないかを実機で確かめたい。

Claude Codeに任せた部分、任せなかった部分

設定の変更も、測るためのadbの手順も、Claude Codeのセッションの中で進めた。筆者がやったのは、実機で被って動きを確かめることと、どの方向で直すかを決めることだ。

Claude Codeで個人サービスを作ったときは、バグを伝えれば原因まで特定してくれる場面が多かった。今回は事情が違った。原因はコードではなく、Unityの設定ファイルの1行だった。しかも症状は、実機でヘッドセットを着け外ししたときにしか出ない。

そういう問題で効いたのは、「被らずに再現する」「同じ値を同じ手順で測る」という土台を先に作ることだった。土台ができてしまえば、設定を変えて測り直すのは速い。

よくある質問

Q
Questアプリで、ヘッドセットを外すたびにメモリが増えるのはなぜ?
A

筆者の自作アプリでは、着け外しのたびにGPUメモリ(dumpsys meminfoのGL mtrack)が約630MB増えていた。UnityのOpenXR設定「Optimize Buffer Discards (Vulkan)」を有効にすると、4回の着け外しで増えたのは約11MBになった。Meta Quest Supportを使っていない構成では画面にチェック欄が出ないので、設定ファイルの値を書き換えた。MSAA用のバッファが着け直しのたびに作り直されていたと見ているが、直接確かめたログは無く、推定にとどまる。

Q
Questを被らずに、着けた・外した状態を再現できる?
A

筆者の環境(Windows 11・Quest 3)では、adbで「adb shell am broadcast -a com.oculus.vrpowermanager.prox_far」を送ると外した扱い、「prox_close」で着けた扱いになった。それぞれ約28秒・約18秒待つと切り替わりが終わる。公式ドキュメントで見つけた手順ではない。終わったら「automation_disable」を送らないと、被っていても約15秒でスリープする状態が残る。

Q
Optimize Buffer Discards (Vulkan) を有効にして困ることはある?
A

Metaの開発者向けドキュメントは、ほぼすべてのQuestアプリで有効にすべきとしている。一方、Unityの不具合報告では、フォービエイテッドレンダリングと併用するとScriptable Renderer Featureの描画が崩れる例がある(OpenXR 1.15.1〜1.16.0-pre.2、Won’t Fix)。筆者のアプリでは有効にしてGPUメモリが4回の着け外しで4.58GBから171MBに収まったが、描画を拡張している場合は実機で見た目を確かめたい。

着け外しは、被らずに再現して測る

ヘッドセットを外して着け直すだけで数百MBずつ増える問題は、設定ファイルの1行で止まった。ただ、そこに行き着けたのは、着け外しだけをPCから起こし、同じ値を同じ手順で測れるようにしてからだった。

Questのアプリで、実機でしか出ない症状を追うなら、まず被らずに再現できる手順を作る。終わったら automation_disable を送るのを忘れずに。

ムラサキ
ムラサキ
SE歴20年 · 金融系システム開発課長 · 週末起業1年目
システムエンジニア歴20年。金融系システム開発の課長として勤務する傍ら、AIと副業の最前線を実践レポート。Claude Code Max 5xプランを日常業務・副業開発に活用中。一次情報と実測値にこだわった記事を発信。
20 YRS SE
8 MOS 副業
56 ARTICLES
タイトルとURLをコピーしました