版本比较

密钥

  • 该行被添加。
  • 该行被删除。
  • 格式已经改变。

...

...

背景

自从原神 4.3版本在2023年12月20日左右升级之后,对于amd gpu并没有专门的支持,amd gpu 运行时会崩溃在libgallium库(mesa提出的全新的3D引擎框架)中。

...


解决过程

查看waydroid上的issue,可以看到有很多大神尝试了不同的原神版本,都会崩溃。https://github.com/waydroid/waydroid/issues/1206

...

代码块
openfde/out/target/product/fde_arm64/symbols/vendor/lib64/dri$ addr2line  000000000099e844 -e  libgallium_dri.so 
openfde/external/mesa/src/mesa/main/texobj.c:639620
#打开该文件看到:
 609 /**
 610  * Reference (or unreference) a texture object.
 611  * If '*ptr', decrement *ptr's refcount (and delete if it becomes zero).
 612  * If 'tex' is non-null, increment its refcount.
 613  * This is normally only called from the _mesa_reference_texobj() macro
 614  * when there's a real pointer change.
 615  */
 616 void
 617 _mesa_reference_texobj_(struct gl_texture_object **ptr,
 618                         struct gl_texture_object *tex)
 619 {
 620    assert(ptr);
 621 
 622    if (*ptr) {
 623       /* Unreference the old texture */
 624       struct gl_texture_object *oldTex = *ptr;
 625 
 626       assert(valid_texture_object(oldTex));
 627       (void) valid_texture_object; /* silence warning in release builds */
 628 
 629       assert(oldTex->RefCount > 0);
 630 
 631       if (p_atomic_dec_zero(&oldTex->RefCount)) {

看倒620行是assert(ptr)。这是一个断言,说明ptr是不合法的指针。针对这个crash找不到更多线索。想着打开mesa的调试开关试试能不能找到其他有用的信息,打开调试开关,重新编译mesa,运行发现崩溃的地方变了,崩溃在external/mesa/src/mesa/main/uniforms.c的断言上,assert(unit < ARRAY_SIZE(prog->TexturesUsed)),发现ARRAY_SIZE(prog->TexturesUsed)为192,unit是由调用者设置,所以修改了设置的逻辑。为192,该值超过了最大下标,导致下标越界。

打开调试开关的具体位置修改如下:

代码块
diff --git a/src/compiler/nir/meson.build b/src/compiler/nir/meson.build
index 5ce85780cca..559ceb3aab4 100644
--- a/src/compiler/nir/meson.build
+++ b/src/compiler/nir/meson.build
@@ -322,7 +322,7 @@ _libnir = static_library(
    nir_opcodes_h, nir_constant_expressions_c, nir_builder_opcodes_h,
    nir_intrinsics_c, nir_intrinsics_h, nir_intrinsics_indices_h],
   include_directories : [inc_include, inc_src],
-  c_args : [c_msvc_compat_args, no_override_init_args, no_misleading_indentation],
+  c_args : [c_msvc_compat_args, no_override_init_args, no_misleading_indentation, '-UNDEBUG'],
   gnu_symbol_visibility : 'hidden',
   dependencies : [idep_compiler, dep_valgrind],
   build_by_default : false,

diff --git a/src/gallium/auxiliary/meson.build b/src/gallium/auxiliary/meson.build
index 96b0272c69b..1e6fabf3d70 100644
--- a/src/gallium/auxiliary/meson.build
+++ b/src/gallium/auxiliary/meson.build
@@ -525,7 +525,7 @@ libgallium = static_library(
   include_directories : [
     inc_loader, inc_gallium, inc_src, inc_include, include_directories('util')
   ],
-  c_args : [c_msvc_compat_args, libgallium_extra_c_args],
+  c_args : [c_msvc_compat_args, libgallium_extra_c_args, '-DDEBUG'],
   cpp_args : [cpp_msvc_compat_args],
   gnu_symbol_visibility : 'hidden',
   dependencies : [

diff --git a/src/gallium/drivers/llvmpipe/meson.build b/src/gallium/drivers/llvmpipe/meson.build
index 38ff88980f9..12d51733c1f 100644
--- a/src/gallium/drivers/llvmpipe/meson.build
+++ b/src/gallium/drivers/llvmpipe/meson.build
@@ -115,7 +115,7 @@ files_llvmpipe = files(
 libllvmpipe = static_library(
   'llvmpipe',
   [files_llvmpipe, sha1_h],
-  c_args : [c_msvc_compat_args],
+  c_args : [c_msvc_compat_args, '-DDEBUG'],
   cpp_args : [cpp_msvc_compat_args],
   gnu_symbol_visibility : 'hidden',
   include_directories : [inc_gallium, inc_gallium_aux, inc_include, inc_src],

diff --git a/src/mesa/main/debug.c b/src/mesa/main/debug.c
index 43a68d130e1..b5cbc360863 100644
--- a/src/mesa/main/debug.c
+++ b/src/mesa/main/debug.c
@@ -22,6 +22,7 @@
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
  */
+#define LOG_NDEBUG 0

 #include <stdio.h>
 #include "errors.h"
@@ -41,6 +42,7 @@

 #include "state_tracker/st_cb_texture.h"
 #include "state_tracker/st_cb_readpixels.h"
+#undef NDEBUG

 static const char *
 tex_target_name(GLenum tgt)

diff --git a/src/mesa/main/errors.c b/src/mesa/main/errors.c
index 70813744cd2..540a1d946f2 100644
--- a/src/mesa/main/errors.c
+++ b/src/mesa/main/errors.c
@@ -26,6 +26,7 @@
  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  * OTHER DEALINGS IN THE SOFTWARE.
  */
+#define LOG_NDEBUG 0


 #include <stdarg.h>
@@ -38,6 +39,8 @@
 #include "util/detect_os.h"
 #include "util/log.h"
 #include "api_exec_decl.h"
+#undef NDEBUG

 static void
 output_if_debug(enum mesa_log_level level, const char *outputString)

diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 6eceae83a9c..b573d07995e 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -61,6 +61,7 @@
 #include "pipe/p_state.h"

 #include "frontend/api.h"
+#undef NDEBUG

 #ifdef __cplusplus
 extern "C" {

diff --git a/src/mesa/meson.build b/src/mesa/meson.build
index d07b8fb33a7..639a744d10a 100644
--- a/src/mesa/meson.build
+++ b/src/mesa/meson.build
@@ -470,7 +470,7 @@ endif
 libmesa = static_library(
   'mesa',
   files_libmesa,
-  c_args : [c_msvc_compat_args, _mesa_windows_args],
+  c_args : [c_msvc_compat_args, _mesa_windows_args, '-DDEBUG', '-UNDEBUG'],
   cpp_args : [cpp_msvc_compat_args, _mesa_windows_args],
   gnu_symbol_visibility : 'hidden',
   include_directories : [

diff --git a/src/mesa/vbo/vbo.h b/src/mesa/vbo/vbo.h
index f11824cdaa4..fbf5a5e9a15 100644
--- a/src/mesa/vbo/vbo.h
+++ b/src/mesa/vbo/vbo.h
@@ -38,6 +38,7 @@
 #include "main/macros.h"
 #include "vbo_attrib.h"
 #include "gallium/include/pipe/p_state.h"
+#undef NDEBUG

diff --git a/src/util/log.h b/src/util/log.h
index 17670cc97d9..2342970bf1f 100644
--- a/src/util/log.h
+++ b/src/util/log.h
@@ -32,6 +32,7 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+#define  DEBUG 1

我们将这个问题反馈到mesa官方后(https://gitlab.freedesktop.org/mesa/mesa/-/issues/11148#note_2410145 ),得到了一个修复(原神在amdgpu崩溃修复)。但是修复崩溃后,还存在丢失纹理的问题(就是游戏中变成一些方方正正的盒子)。)。但是修复崩溃后,还存在丢失纹理的问题(就是游戏中变成一些方方正正的盒子)。如下图所示。

...

解决方法

针对这个问题YogSottot给了我们一个解决方案,就是启用mesa的xmlconfig,他的提议在此https://github.com/waydroid/waydroid/issues/1206#issuecomment-2132083401
这个功能的背景是一部分android游戏并不感知开源gpu驱动,当他们看到一款未知驱动时,通常会用最低性能去运行。所以,针对指定的游戏程序名,使用xmlconfig记录的特性值覆盖vendor或者renderer设置返回给游戏程序以获取更高的fps和更好的渲染。修复纹理丢失的问题是使用另外一款gpu的名称代替amd gpu来返回给原神。https://gitlab.freedesktop.org/mesa/mesa/-/commit/b9129496a295f3aef7d96540556eced25961f66a

...

代码块
#将vendor镜像挂载到/mnt目录。
sudo mount /usr/share/waydroid-extra/images/vendor.img /mnt
#打开xml配置文件
sudo vim /mnt/etc/drirc.d/00-mesa-defaults.conf 
910 <application name="Genshin Impact" executable="com.miHoYo.Yuanshen">
911            <option name="ignore_discard_framebuffer" value="true" />
912            <option name="force_gl_renderer" value="Adreno (TM) 630"/>
913           <option name="force_gl_vendor" value="Qualcomm"/>
914 </application>

esc #按下esc vim 退出到命令模式
:wq #输入:wq保存退出。
sudo umount /mnt #卸载镜像

需要注意的是这个兼容方案,有时候会造成原神整个画面显示红色问题。此时需要先注释或删除以上910~914行的内容。先让原神正常启动,进入画面(带纹理丢失的画面)。然后退出fde,再按上述步骤,添加好910~914的内容。再次进入fde,才能正常进入画面。

有兴趣的可以查看 https://github.com/openfde/openfde/issues/15#issuecomment-2116555506

...