Closed dynamis closed 4 years ago
about:support の WebGL 1 Extensions において、Firefox 68 では EXT_frag_depth と WEBGL_draw_buffers が減っている。これは下記で修正されていて、意図したものである模様。
https://bugzilla.mozilla.org/show_bug.cgi?id=1524804
一応上記修正を外して Extension を有効に戻してみたが、Extensions の一覧には出るようになったもののパフォーマンス面では改善しなかった。
Firefox 60 ではビルド時に gl provider として EGL を明示的に指定していた。Firefox 68 では現状は指定なし(デフォルト)になっている。
gfx/gl/GLContextProvider.h の実装では、Firefox 68 では EGL ではなく Wayland が default provider として使用されるようになっている。これを試しに EGL に変更してみたが効果なし。
なお、Firefox のビルドオプションで Firefox 60 のときと同様に --with-gl-provider=EGL を指定すると、gfx/gl/moz.build の作りの都合で GLContextProviderGLX.cpp などがビルド対象から外されコンパイルに失敗するようになる。
Firefox 68 では、
gfx.blacklist.layers.opengl = 4
gfx.blacklist.layers.opengl.failureid = FEATURE_FAILURE_SOFTWARE_GL
が出ている。Firefox 60 から GfxInfoX11.cpp の実装の違いから出るようになっているようだが、ソフトウェア的にエラーが報告されないようにしても特に効果はなし。
現状で動作させている Firefox 60 と Firefox 68 では、Firefox のソースコードだけでなく、ビルド環境もかなり変わってしまっている。一旦「ビルド環境は関係ない」ことを確定させるために、Firefox 68 向けのビルド環境(rust や clang)などを使って、Firefox 60 をビルドし動作確認を行った。結論としてはビルド環境は特に関係なく、新しい rust や clang で構築した Firefox 60 で 60fps 出ることを確認した。
ただし、新しい環境で Firefox 60 のビルドのためにはいくつか調整が必要になる。
60 と 68 ではかなり差分も多く、現時点ではソースコード上のあたりはほぼついていない。
範囲を効率的に狭めるのであれば、61 〜 67 の動作確認を行って動作が遅くなってしまったバージョンを特定するのが部分的には良いと思うが、実際にコンパイルするための調整の手間がどれくらいかかるかが想定できておらず、本当にこれが効率的かどうかは不明(とはいえ rust, clang などの環境が Firefox 68 向けのままで良さそうではあるので、そんなに大変じゃないかもしれない)。
あまり意味の無い報告: バージョン二分探索チェックも大変そうだなと思って先日少し Bugzilla なんかも見てみた のですが
といったくらいでこれといって怪しい bug は見つけられませんでした。怪しい挙動が見つからないと影響範囲特定を進めるしかなさそうですね。
1010527 は私も先日見ていたのですが、60 では良かったのに 68 でダメになった話とは全然合致しないので関係なさそうだなと思っていました。
それはそれとして、よく考えると WebGL2 対応で glxtest を XWayland を入れて通してあげるという話が実はちょっと変じゃないかというか、glxtest はビルドの内部的には MOZ_GL_DEFAULT_PROVIDER が GLX のときにしかビルドされないのですが、Firefox 60 のときには MOZ_GL_DEFAULT_PROVIDER は EGL になっているはずなのですよね(configure で指定していたので)。
あまり細かくは調べられていないのですが、Firefox 60 は XWayland を有効にしても WebGL2 が有効にならず、これはそもそも glxtest とは全然違う問題でダメになっているからじゃないかと推測しています。
でも仮にこれが正しかったとすると、Firefox 68 で EGL に戻してパフォーマンスが回復したとして、WebGL2 対応は別の方法でやり直しになる可能性が高そうには思います。
いやでも Firefox 68 までの間に GLX と EGL の両立ができるようになったから、と思えば変ではないですか。いずれにせよ現時点ではあまり状況を捉えきれてないですね。
https://github.com/mozilla/gecko-dev/commit/704838e243a064a008f10baddd5d0115cf95e492
関係ないかもしれませんが、63辺りからVSyncの実装が入ってるのがちょっと気になってます。
あと、こちらも関係ないかもしれませんが、昨日似たような?バグが立ってました
あと、これもたぶん関係ないと思うんですが、すぐに試せることとしてはe10sを切った場合どうなるかもちょっと気になります。68ではprefでは切れなくなっていて、環境変数MOZ_FORCE_DISABLE_E10S=1
が必要です(レシピ作ったときにはそのことに気がついてなかったのでdisable-e10s
というPACKAGECONFIG
入れちゃってますけど)。
VSync の方については frame_callback_handler() で
gfxPlatformGtk::GetPlatform()->SetWaylandLastVsync(time);
としているのをやめれば mWaylandFrameDelay = 1000/60 で確実に描画が入るだろう…ということでやってみましたが効果なし。さらに mWaylandFrameDelay 自体を 1000/100 で 100fps 相当にしてみたりしても変化なしですね。
MOZ_FORCE_DISABLE_E10S=1 の方も有意な変化は見られずでした。
一応ウインドウサイズを狭めれば fps が上がってくることはわかっているので、描画のタイミング制御がおかしいわけではなく、ただ単に描画そのものが遅いから全体が遅いのかな、という気はします。
あと全然別の話なのですが、私の Thinkpad X1 Yoga 4th (ArchLinux, Firefox 70, X11) でも https://threejs.org/examples/#webgl_geometry_normals は 2560x1440 のフルスクリーンだと 30fps くらいしか出ず。Wayland で起動しようとすると画面がちらついてしまって操作できない感じです。Chromium は何ということなく安定して 60fps なのですが。
別のデスクトップ機では Firefox 70 で 60fps 出ていたりするので、何か相性的なものもありそうなような…。
apitrace 8.0 を入れてログを取ってみた。
GDK_BACKEND=wayland apitrace --api=egl --output=/tmp/firefox-dump.trace firefox https://threejs.org/examples/webgl_geometry_normals.html
ちなみに Firefox 68 で --api=gl であれば解析可能なログが取れるが、おそらくは glxtest の実行を行っただけの短いものしか取れていない。
Firefox 68 で apitrace がおかしいのは e10s が有効だと複数プロセスからログを書きに行って潰してしまうからのようで、MOZ_FORCE_DISABLE_E10S=1 だと dump 可能だった。
ただし Firefox 60 だと Wayland で描画しているウインドウが replay 可能な感じになるが、Firefox 68 だとほとんど何も replay できない。
Firefox 67, 66 でそれぞれ動作確認を行ったが、どちらも FPS は 35 前後で遅い。
https://github.com/webdino/meta-browser/tree/anyakichi/firefox-67-rzg2 https://github.com/webdino/meta-browser/tree/anyakichi/firefox-66-rzg2
手作業の手順については MEMO ファイルを参照のこと。
ということで遅くなったバージョンは Firefox 62 で確定。変更量はそれなりに多い。
$ hg diff -r FIREFOX_61_0_2_RELEASE -r FIREFOX_62_0_3_RELEASE | wc -l
3267154
$ hg diff -r FIREFOX_61_0_2_RELEASE -r FIREFOX_62_0_3_RELEASE gfx | wc -l
146173
このバージョンから GLContextProviderWayland が導入されるなど、gfx/gl 以下の構成にいろいろと変更がある。また、これまで #ifdef GL_PROVIDER_GLX
だったところが #ifdef MOZ_X11
に変更、もしくは #ifdef
そのものが削除されている箇所も多数あり、EGL と GLX が共存するような形式に変更されている。
感覚的にはこのあたりが怪しいような気はするが…あまり確証はない。
暫定的に MOZ_X11 を無効にしてビルドするのは試してみたが、cairo 周りの依存関係でビルドを通すまでの調整が難しそうだった。
関係ないだろう話が発端ですがこちらに共有:
別件で GDK_BACKEND 指定ミスったら WebGL1 は動くが WebGL2 だけ動かずに
WebGL creation failed:
tryNativeGL
Exhausted GL driver options
というメッセージがコンソールや about:support の WebGL2 欄に出ていた。 https://dxr.mozilla.org/mozilla-central/source/dom/canvas/WebGLContext.cpp#627 https://dxr.mozilla.org/mozilla-central/source/dom/canvas/WebGLContext.cpp#642
それで回り少し見たら
https://dxr.mozilla.org/mozilla-central/source/dom/canvas/WebGLContext.cpp#570
const bool useEGL = PR_GetEnv("MOZ_WEBGL_FORCE_EGL");
が false になっていて GLContextProviderEGL ではなく GLContextProvider を使っているケースは WebGL1 だけ動く状態になっていた様子。
GLContextProvider が一杯ある&変わってるけど Gecko ~61 と 62〜 で実際どれを使って描画しているのか (同じなのか違うのか)、ビルド設定や環境変数などに依存して切り替わる感じがするけど適切な GLContextProvider が使われているのか、強制的に切り替えてみたらどう変わるのかとか気になりました。
GLContextProvider が一杯ある&変わってるけど Gecko ~61 と 62〜 で実際どれを使って描画しているのか (同じなのか違うのか)、ビルド設定や環境変数などに依存して切り替わる感じがするけど適切な GLContextProvider が使われているのか、強制的に切り替えてみたらどう変わるのかとか気になりました。
最近自分ではあまり実機を触ってないので未だに本issueの現象自体確認できていないのですが、
GDK_BACKEND
の指定を間違っていなければそこは大丈夫じゃないかなと思ってます。
GLContextProviderWayland
は
GLContext* GLContextProviderWayland::GetGlobalContext() {
if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
return sGLContextProviderGLX.GetGlobalContext();
} else {
return sGLContextProviderEGL.GetGlobalContext();
}
}
こういうベタな方法でGLContextProvider
をランタイムで切り替えるだけの存在なので、GDK_BACKEND
の指定を間違えて無ければ、Wayland上でGLContextProviderGLX
が使われることはまず無いはずです(といううかGDK_BACKEND
を間違えてたらX11バックエンドでGLContextProviderGLXが動く)し、使われたとしてもWaylandバックエンドでは動かないと思います。
る。また、これまで #ifdef GL_PROVIDER_GLX だったところが #ifdef MOZ_X11 に変更、もしくは #ifdef そのものが削除されている箇所も多数あり、EGL と GLX が共存するような形式に変更されている。
感覚的にはこのあたりが怪しいような気はするが…あまり確証はない。
X11のコードが中途半端に動いて変なことになっていたのは今までにもよくあったので、たしかに怪しいなぁと思ってちょっと差分を眺めてみてます。
この辺とか怪しいです。
https://searchfox.org/mozilla-esr68/source/gfx/gl/GLScreenBuffer.cpp#84
もともとdefined(GL_PROVIDER_GLX)
の条件でしかビルドされなかったのが、defined(MOZ_X11)
に変わってビルドされるようになっています。一方で、その下のEGL用のコードがビルドされなくなっちゃってるように見えます(従来は上記の条件に引っかからなくてここがビルドされていたはず)。
https://searchfox.org/mozilla-esr68/source/gfx/gl/GLScreenBuffer.cpp#97
#else
if (gl->GetContextType() == GLContextType::EGL) {
if (XRE_IsParentProcess()) {
factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags);
}
}
#endif
もともと
defined(GL_PROVIDER_GLX)
の条件でしかビルドされなかったのが、defined(MOZ_X11)
に変わってビルドされるようになっています。一方で、その下のEGL用のコードがビルドされなくなっちゃってるように見えます(従来は上記の条件に引っかからなくてここがビルドされていたはず)。
おおおお、なるほど。手元に残っていた Firefox 62 のビルド環境でビルドしてみたところ、FPS 60 出るようになりました!どうやらこれでビンゴっぽいですね…。素晴らしい…。
また後日 Firefox 68 でも同様に改善するかは確認してみます。
あとは直し方として、if 文を MOZ_X11 の中に入れてしまうのが良いのか、違う条件で切るのかは考えないといけませんが(現在の #else
で EGL というのもなんか違和感はありますが)。
一番簡単な直し方としてはMOZ_X11
のところをそのまま#else
の中に移動してしまえば良さそうです。
Waylandの場合にはたぶんsGLXLibrary.UseTextureFromPixmap() == false
になると思うので。
もちろん、さらにGDK_IS_X11_DISPLAY(gdk_display_get_default())
のチェックを入れた方がより確実だとは思います。
あと、この関数の最後の#ifdef MOZ_X11
は不要そうなので削除しておいた方が良さそうです。
(現在の #else で EGL というのもなんか違和感はありますが)
昔は違ったような気がするのですが、今はGLContextProviderEGLが全てのプラットフォームでビルドされるようなので、そんなもんなのかなという気もします。
あと、この関数の最後の#ifdef MOZ_X11は不要そうなので削除しておいた方が良さそうです。
いや、必要らしい
PC上で以下のようなパッチを試してみたが、XRE_IsParentProcess()
の条件があるので、e10sを無効化(環境変数MOZ_FORCE_DISABLE_E10S=1
)しないとSharedSurface_EGLImage
が有効にならない。
e10を切ると、e10s有効の場合より速くなった。この条件を外してe10s有効の場合は画面が真っ黒。
diff --git a/gfx/gl/GLScreenBuffer.cpp b/gfx/gl/GLScreenBuffer.cpp
--- a/gfx/gl/GLScreenBuffer.cpp
+++ b/gfx/gl/GLScreenBuffer.cpp
@@ -25,16 +25,17 @@
# include "mozilla/gfx/DeviceManagerDx.h"
#endif
#ifdef XP_MACOSX
# include "SharedSurfaceIO.h"
#endif
#ifdef MOZ_X11
+# include <gdk/gdkx.h>
# include "GLXLibrary.h"
# include "SharedSurfaceGLX.h"
#endif
namespace mozilla {
namespace gl {
using gfx::SurfaceFormat;
@@ -80,30 +81,32 @@ UniquePtr<SurfaceFactory> GLScreenBuffer
!StaticPrefs::webgl_force_layers_readback() &&
(backend == layers::LayersBackend::LAYERS_D3D11 ||
(backend == layers::LayersBackend::LAYERS_WR && useANGLE));
UniquePtr<SurfaceFactory> factory = nullptr;
if (useGl) {
#if defined(XP_MACOSX)
factory = SurfaceFactory_IOSurface::Create(gl, caps, ipcChannel, flags);
-#elif defined(MOZ_X11)
- if (sGLXLibrary.UseTextureFromPixmap())
- factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags);
#elif defined(MOZ_WIDGET_UIKIT)
factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, caps, ipcChannel,
mFlags);
#elif defined(MOZ_WIDGET_ANDROID)
if (XRE_IsParentProcess() && !StaticPrefs::webgl_enable_surface_texture()) {
factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags);
} else {
factory =
SurfaceFactory_SurfaceTexture::Create(gl, caps, ipcChannel, flags);
}
#else
+# if defined(MOZ_X11)
+ if (gl->GetContextType() == GLContextType::GLX &&
+ sGLXLibrary.UseTextureFromPixmap())
+ factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags);
+# endif
if (gl->GetContextType() == GLContextType::EGL) {
if (XRE_IsParentProcess()) {
factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags);
}
}
#endif
} else if (useD3D) {
#ifdef XP_WIN
@@ -127,17 +130,19 @@ UniquePtr<SurfaceFactory> GLScreenBuffer
if (!factory && StaticPrefs::webgl_dxgl_enabled()) {
factory =
SurfaceFactory_D3D11Interop::Create(gl, caps, ipcChannel, flags);
}
#endif
}
#ifdef MOZ_X11
- if (!factory && sGLXLibrary.UseTextureFromPixmap()) {
+ // Bug 1241486: Use SharedSurface_GLX with XRender
+ if (!factory && GDK_IS_X11_DISPLAY(gdk_display_get_default()) &&
+ sGLXLibrary.UseTextureFromPixmap()) {
factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags);
}
#endif
return factory;
}
GLScreenBuffer::GLScreenBuffer(GLContext* gl, const SurfaceCaps& caps,
上記パッチで RZ/G2M + Firefox 68 試してみました。
ということで e10s 無効であれば状況が改善しました。どちらも描画そのものは適切にできているように見えます。
ただ、若干気になる点として FPS が 60 「前後」なので、なんとなく 62 で安定しつつ 40〜50 くらいに急に落ちてまた 62 に戻る…ような数値の見え方になっています。Firefox 62 のときには 60 できれいに張り付いていたのですが…。
お二人とも調査・検証ありがとうございます。FPS 60 前後が (一応) 出るようになって良かったです! // 適切な条件分岐がされておらずテスト不足の環境では挙動が怪しいというのはなるほどというか確かに以前もそういう話をされていた気がしました。
e10s を有効化できないのは残念ですが仕方ない&Fx60 でも有効化できなかったので regression にはならないですし、今回も無効化を標準ビルドとする (WebGL 使わないから e10s 有効化するという選択は一応あり) のが妥当そうですね。
FPS 不安定になるというのはまだ何か問題が残っているので継続調査が必要そうですが...
68ではprefでのe10s無効化が出来なくなっているのでお気をつけ下さい。
PACKAGECONFIG
のdisable-e10s
が意味を成さなくなっているので、OSSystems/meta-browserの方では削除しました。
https://github.com/OSSystems/meta-browser/pull/343
実行時にMOZ_FORCE_DISABLE_E10S=1
を指定するか、新たなパッチが必要だと思います。
パッチについては後でBugzillaに報告しておきます。
ちなみにX11の場合はgfx.use-glx-texture-from-pixmap
というオプションがデフォルトoffでこれをonにしないとSharedSurfaceGLX
が使えないようです。また、こちらもe10sでは動作しないようです。
少し脱線になりますが:
68ではprefでのe10s無効化が出来なくなっているのでお気をつけ下さい。 PACKAGECONFIGのdisable-e10sが意味を成さなくなっているので、OSSystems/meta-browserの方では削除しました。
こちらでも検証をしてみたのですが現状の Fx68 ビルドはデフォルト e10s オンですが browser.tabs.remote.autostart=false
にすると ps コマンドと about:support いずれで見ても e10s 無効にちゃんと切り替わりました (MOZ_FORCE_DISABLE_E10S=1
で起動するときと同じ)。以前入れていた 4 設定
pref("browser.tabs.remote.force-enable", false);
pref("browser.tabs.remote.force-disable", true);
pref("browser.tabs.remote.autostart", false);
pref("browser.tabs.remote.autostart.2", false);
の一部は使えなくなっているが少なくとも browser.tabs.remote.autostart
はまだ e10s 無効化に使えるということはないでしょうか?
の一部は使えなくなっているが少なくとも browser.tabs.remote.autostart はまだ e10s 無効化に使えるということはないでしょうか?
もしかしたら、そういうことなのかもしれません。 (すみません、最近自分ではまったくいじれてないので、本件に関しては自分で確かめたことではなくて周りから聞いたことの受け売りに過ぎないです。)
Gecko 68 時点では e10s の有効化と WebGL のパフォーマンス確保は排他的な関係にあるという制約は残るが、Gecko 60 と比べて遅くなっていた問題は解消したためクローズします。
(Gecko 60 ではそもそも e10s 有効化できていなかったので regression ではない)
Gecko 68 では何らかの特別な事情で e10s/webgl 両方を使いたいケースがでてこない限り終了としてクローズ、次は Gecko 78 ベースでどうなるのかを確認・検討していくこととしましょう。
現状の Firefox 68 on RZ/G2M WIP ビルドで WebGL コンテンツを再生したときの FPS が (60 ではなく) 25 で頭打ちになってしまっている。2D Canvas などの処理は 60fps でているので、WebGL の場合のみの制限。BSP や OpenGL ドライバ周りか Gecko エンジン側かどちらの問題かなど未確認。
OpenGL ES3 周りで何か制約の生じるビルドになってしまっている?
FSP 表示のある軽量 WebGL サンプル: