昨天eden更新了最新的build,官方下载地址
https://git.eden-emu.dev/eden-emu/eden/releases
这里以 Standard 标准版本为例子,在我自己的odin3上大概讲解一下具体的配置明细。
启动需要导入对应的Switch的prod.key 用于游戏数据的解密。我用的版本:
https://moddedspotify.link/2025/ ... -title-keys-21-0-1/
还需要导入对应的Switch固件的zip,我自己用的老版本18.0,懒得下新版。在这里自己找一个18+的固件zip下好。
https://github.com/THZoria/NX_Firmware/releases
然后选取对应的游戏文件夹,走安卓的SAF管理这里略过。
这里正式开始具体设置的实际操作:
首先点右上角紫色的齿轮(设置)- GPU驱动管理器,点击左下角的获取。选择推荐的Gamehub Adreno 8xx系列 下载最新的驱动。成功会自动出现在GPU驱动管理器里,记得选中这个新的GPU driver。后续如果有对应Adreno 830的可用Turnip版本也可以在这边快速获取下载link;
第二步,去控制-玩家1里设置好对应的按钮键位,这里略过。后续进游戏,如果你不是手机而是带实体键的安卓掌机,记得关闭屏幕上的虚拟键位。方法是进一个游戏,按返回键,虚拟按键选项-显示控制器,取消选择的对勾就行;
第三步,这里着重讲解一下Eden的高级设置包括对于老Yuzu新增的独特设置:Eden‘s Veil 伊甸之幕。实际参考了AI归纳官方文档+官方源码+自己实测了4 5款游戏表现。
设置里进入高级设置,首先进入图形。确保精度等级是精确,磁盘着色器缓存开启。垂直同步我自己一般是关闭,这个非赛车游戏影响不太大。其余保持默认就行;
往下拖,进入伊甸之幕选项我们逐个过一遍:
GPU扩展分区:
1. 扩展动态状态(Extended Dynamic State)建议0
这里实际就是 Vulkan 管线里,有多少“原本写死的状态”,
可以在运行时动态修改,而不用重新创建 pipeline。Odin3可以看到0-3,四个状态。
默认是0,关闭。对于比较老的游戏(女神异闻录4 黄金版 - Persona 4 Golden),只有这个状态可以进游戏,因为这个游戏的图形引擎比较老无法对应新版Vulkan驱动的动态状态改动。这种游戏建议设置默认0(off)。
如果你想试试最新的兼容性可以设置为2,动态化了大部分Vulkan绘图的常用状态,但是可能引入奇怪的光源抖动。
2. 顶点输入动态状态(Vertex Input Dynamic State)建议开启
启用后:
在vulkan的 draw call 前,通过命令动态指定:binding / attribute / format / offset / stride, 简化了具体的绘图结构。在比较新的3d游戏可以全局开启,对于老2D游戏,如果画面出现问题可以关闭。
3. 引发顶点(Primitive Restart)建议开启
引发顶点(Primitive Restart)是一个“索引绘制层”的控制项,
用来告诉 GPU:
当索引缓冲里出现某个特殊值时,
当前图元结束,重新开始一个新的图元。引发顶点(Primitive Restart)只是告诉 GPU“哪里该断开几何拼接”,
是一个成熟、稳定、几乎不需要用户干预的 Vulkan 基础功能。
4. 描述符索引(Descriptor Indexing)建议开启
描述符索引,用来决定:
shader 能不能“像访问数组一样”,
在运行时按索引访问大量纹理 / buffer / sampler,
而不需要为每种组合创建新的 pipeline 或 descriptor set。
实战中的真实表现✅ 好处
UI / 字体 / HUD 更稳定
切场景时 pipeline 抖动减少
对复杂材质组合收益明显
⚠️ 风险
描述符索引是:
Vulkan 1.2+ 的高级特性
对驱动实现要求很高
在 Android / Adreno 上:
极少数游戏会触发驱动 bug
表现为:
花屏
错贴图
甚至直接报错,模拟器强退
描述符索引让 shader 自己决定“用哪份资源”,
是现代 Vulkan 的关键能力;
在 Android 上建议默认开启,但一旦出现资源异常,应优先回退。
5. 采样着色(Sample Shading)建议关闭
采样着色,用来决定:
在开启多重采样(MSAA)时,
片元着色器是“每像素执行一次”,
还是“对每个采样点分别执行”。
采样着色是“用性能换精度”的特定工具,
在 Switch 模拟器中几乎没有必要,
默认关闭反而更接近主机实际行为。
渲染器分区:
6. DMA 精度(DMA Accuracy)建议默认
DMA 精度,用来控制:
模拟器在处理 CPU ↔ GPU 的内存拷贝(DMA)时,
对“时序与可见性”的模拟有多严格。
在 Android 模拟器里,问题出在哪在 Android + Vulkan 上:
CPU、GPU、内存是 UMA
DMA 行为被:
OS
驱动
cache
内部队列
分拆处理
结果是:
“DMA 完成 ≠ GPU 一定立刻看到正确数据”
所以模拟器必须决定:
我要不要 额外补同步
要补到什么程度
这就是 DMA 精度这个选项存在的原因。
7. 禁用缓冲重排序(Disable Buffer Reordering)建议关闭
禁用缓冲重排序,用来决定:
模拟器是否允许对 GPU/CPU 使用的缓冲区(buffer)
进行内部重排、合并或延迟提交,以提升效率。
保持关闭即可
8. 使用快速 GPU 时间(Use Fast GPU Time)建议关闭
使用快速 GPU 时间,用来决定:
模拟器在估算 GPU 执行时间、同步点与时间戳时,
是否采用“加速/简化的时间模型”,
而不是严格贴合真实 GPU 的执行节奏。
✅ 可能的好处
减少 CPU 等待
帧时间看起来更平滑
某些卡在同步点的游戏更容易跑起来
时间线与真实执行脱节
❌风险:
在以下情况可能出问题:
GPU 实际还没完成
但模拟器已经继续推进逻辑
表现为:
偶发闪烁
短暂错贴图
同步边界异常
实测收益很低,风险极大。
9. 着色器后端(Shader Backend)建议SPIR-V
着色器后端决定的是:
模拟器最终把游戏里的着色逻辑,
交给 GPU 的“中间表示(IR)”是哪一种。
① GLSL(高层源码后端)这是最“传统”、也最不推荐的路径。
模拟器输出:
高层 GLSL 源码
交给驱动:
再编译
再优化
再猜语义
特点
✔ 兼容性表面上看起来高
❌ 驱动自由度极大
❌ 行为不稳定
❌ 首帧、切场景更容易抖
可以理解为:
“把最关键的解释权,完全交给驱动。”
② GLASM(中间汇编路径,历史遗留)GLASM 是一个:
早期 / 过渡方案
接近 OpenGL 汇编语义
特点
比 GLSL 更低层
但:
不是真正的现代 Vulkan 路径
维护价值越来越低
在新设备、新驱动上,基本不推荐。
③ SPIR-V(Vulkan 原生中间表示)这是现代 Vulkan 的“正统路径”,也是强烈推荐的选择。
模拟器输出:
SPIR-V(二进制 IR)
语义:
明确
规范化
驱动“能做的事情更少”
只有Spir-V是安卓原生的支持,所以这个是最优的。
10. NVDEC 模拟(视频解码:禁用 / CPU 解码 / GPU 解码)推荐GPU解码
NVDEC 模拟,用来决定:
Switch 游戏中涉及到的视频流(过场动画、FMV),
在模拟器里由谁来解码:
不解码 / CPU 解码 / GPU 解码。
它影响的不是实时 3D 渲染,而是:
过场动画能不能正常播放
是否花屏 / 黑屏
解码稳定性与系统负载
推荐策略
默认:GPU 解码
大多数过场可正常播放
CPU 压力最小
出现以下问题时,切换为 CPU 解码:
过场花屏
黑屏
卡在动画不动
不建议
长期禁用(除非明确知道自己在干什么)
11. ASTC 解码方式(CPU 解码 / GPU 解码 / CPU 异步解码)推荐 GPU 解码
ASTC 解码方式,用来决定:
Switch 游戏中大量使用的 ASTC 压缩纹理,
在模拟器里由谁来解码、什么时候解码。
它直接影响:
纹理是否及时可见
首帧/切场景是否闪烁
CPU / GPU 负载分布
内存占用与带宽压力
推荐策略(Android 8 Gen 2+)
优先:GPU 解码
性能最好
行为最接近 Switch
首帧一致性最佳
GPU 解码不可用或异常时:
尝试 CPU 异步解码
接受短暂首帧闪烁
只有在 GPU/异步都出问题时:
使用 CPU 同步解码兜底
12. ASTC 重压缩方式(BC1 / BC3 / Uncompressed)推荐BC3
ASTC 重压缩方式,用来决定:
ASTC 纹理在被解码之后,
是否要再次压缩,以及以什么格式常驻在 GPU 显存中。
① BC1(DXT1)
特点:
压缩率高
显存占用低
局限:
不支持 alpha
或 alpha 表达能力极弱
实际影响
UI / 字体 / 半透明:
极容易出问题
人脸、阴影:
细节损失明显
除非你非常清楚游戏几乎不用 alpha,否则不推荐。
② BC3(DXT5)——⭐ 主流推荐
特点:
支持完整 alpha
压缩率与质量平衡良好
在模拟器中的实际表现:
显存占用可控
带宽压力适中
行为稳定
这是目前 Android Switch 模拟中,
最“工程正确”的选择。
③ Uncompressed(未压缩 / RGBA)
特点:
不再压缩
ASTC → RGBA,直接存
好处:
纹理质量最好
理论上最少压缩伪影
代价:
❌ 显存占用暴涨
❌ 内存带宽压力巨大
❌ 更容易 OOM / stutter
这是“实验/兜底”选项,不是日常选项。
[
本帖最后由 gggbdm 于 2025-12-23 13:46 编辑 ]
13. 显存使用模式(VRAM 使用模式:保守 / 激进)建议 激进模式
显存使用模式,用来决定:
模拟器在 Android 这种“统一内存架构(UMA)”平台上,
是更积极地把资源常驻在 GPU 可访问内存中,
还是更保守、按需回收。
在真实 Switch 上:
有明确的 GPU 显存区域
纹理 / buffer 一旦上传:
行为稳定
不会被 OS 干预
但在 Android 上:
CPU / GPU 共享一块物理内存(UMA)
“显存”只是:
驱动管理的一部分内存
系统可能随时:
回收
迁移
压缩
👉 这和主机的内存模型是根本不同的。
① 保守模式(Conservative)
行为:
按需分配
用完尽快释放
更积极地让内存回到系统
优点:
系统压力小
不容易 OOM
后台更安全
缺点:
资源可能被频繁重新上传
首帧/切场景更容易抖
偶发“刚加载完闪一下”
👉 更像“Android 应用”的内存策略。
② 激进模式(Aggressive)
行为:
已上传的纹理 / buffer 尽量常驻
减少回收
减少重新分配
优点:
资源可见性更稳定
首帧一致性好
切场景更顺
代价:
占用内存更高
对系统资源要求更高
低内存设备可能风险增大
👉 更像“主机显存”的工作方式。
推荐策略(Android 8 Gen 2+)
内存 ≥ 8GB 的设备:
推荐:激进模式
内存较小 / 后台多的设备:
使用:保守模式
14. SPIR-V 优化(从不 / 加载时 / 总是)建议 加载时(On Load)
SPIR-V 优化,用来决定:
模拟器是否、以及在什么时候,
对生成好的 SPIR-V 中间表示做额外的规范化与优化处理。
大致流程是:
游戏着色逻辑
↓
模拟器生成 SPIR-V
↓
(可选)SPIR-V 优化 / 规范化
↓
驱动后端编译 → GPU ISA
① 从不(Never)
行为:
生成 SPIR-V 后不做任何额外处理
原样交给驱动
优点:
加载最快
实现最简单
缺点:
SPIR-V 结构可能:
冗余
非最优
驱动更难稳定处理
👉 更像“完全信任驱动”的模式。
② 加载时(On Load) ⭐ 推荐
行为:
在 shader / pipeline 加载阶段
对 SPIR-V 做一次集中优化
优化内容通常包括:
死代码消除
常量折叠
控制流简化
规范化指令结构
特点:
✔ 把不确定性前置
✔ 运行期更稳定
❌ 首次加载稍慢
👉 这是“主机式模拟”的最佳平衡点。
③ 总是(Always)
行为:
不仅在加载时
甚至在运行期 / 多次创建 pipeline 时
反复对 SPIR-V 做优化
理论目标:
每一次都用“最优 IR”
但现实是:
❌ 重复优化成本很高
❌ 可能引入:
时序抖动
pipeline cache 不稳定
❌ 在 Android 上几乎没有实际收益
👉 这是“理论正确,工程不划算”的选项。
推荐策略(Android 8 Gen 2+)
全局:加载时(On Load)
什么时候考虑“从不”
排查极端兼容性问题
怀疑优化器本身触发 bug
用于 A/B 对照测试
CPU和内存分区:
15. 快速 CPU 时间(Fast CPU Time)建议关闭
快速 CPU 时间,用来决定:
模拟器在推进 Switch CPU(ARM)执行与计时逻辑时,
是否采用“加速/简化的时间推进模型”,
而不是严格模拟真实硬件的时钟节奏。
在真实 Switch 上:
CPU 时钟
GPU 时钟
DMA / 中断 / fence
都来自统一、稳定的硬件时钟体系
游戏逻辑默认假设:
“CPU 执行速度 ≈ 硬件真实时间推进速度”
Android 模拟器里的现实在 Android 上:
CPU 是:
大核 / 小核混合
动态变频
调度由:
Linux 内核
Android scheduler
热管理
共同决定
结果是:
“执行了多少指令” ≠ “时间过了多久”
这会直接影响:
sleep / wait
轮询式同步
忙等逻辑
某些物理 / 动画节奏判断
如果问题表现为“稳定、必现”,
快速 CPU 时间通常不是解法;
如果问题表现为“卡住、不推进”,
它才有尝试价值。 所以建议关闭。
16. 自定义 CPU 时钟(Custom CPU Clock)建议关闭
自定义 CPU 时钟,用来人为指定:
模拟器中 Switch CPU 的“名义运行频率”,
从而影响 CPU 执行节奏、负载比例与同步假设。
推荐策略(Android 8 Gen 2+)
默认 / 接近 Switch 原始值
不建议:
全局拉满
和 Fast CPU Time 同时使用
17. 跳过 CPU 内部无效化(Skip CPU Internal Invalidation)建议关闭
跳过 CPU 内部无效化,用来决定:
模拟器是否省略 CPU cache / 内部状态的“失效(invalidate)”步骤,
以减少同步与内存一致性开销。
背景:什么叫“CPU 内部无效化”在真实硬件上(尤其是主机):
CPU cache 是有严格规则的
当:
DMA 写入内存
GPU 修改共享区域
CPU 必须:
invalidate 自己的 cache
才能看到最新数据
Switch 的 CPU + GPU 体系:
这套机制是硬件级保证的
游戏代码默认:
“我这么写,cache 一定是对的”
Android 模拟器里的现实问题在 Android + Linux + ART + 驱动 的多层系统中:
CPU cache 行为被:
OS
内核
驱动
多重抽象
模拟器为了“安全”:
往往会 显式插入 invalidate / flush
问题是:
这些操作非常昂贵。
不建议开。
18. 启用主机 MMU 模拟(Enable Host MMU Emulation) 建议关闭
启用主机 MMU 模拟,用来决定:
模拟器是否更严格地模拟 Switch 主机的内存管理单元(MMU)行为,
包括地址映射、页属性、访问权限与可见性语义。
在真实 Switch 上
- CPU + GPU:
- MMU 负责:
- 很多游戏代码隐含假设:
“这个地址这么用,一定是合法、同步、可见的。”
在 Android 上
- 你面对的是:
- Linux MMU
- Android ION / DMA-BUF
- GPU 驱动自己的地址空间
- CPU 和 GPU:
- 不存在一个“像 Switch 那样统一、简单、确定”的内存视图
开启没什么意义
19. 启用 LRU 缓存(Enable LRU Cache)建议开启
LRU 缓存,用来决定:
模拟器在管理纹理、缓冲区等 GPU 资源时,
是否采用“最近最少使用(Least Recently Used)”的淘汰策略,
来回收不再活跃的资源。
在真实 Switch 上:
但在 Android 上:
- 是 UMA 架构
- 显存 ≈ 系统内存的一部分
- 系统可能随时:
如果模拟器不做主动管理:
几乎没有理由关闭它,除非:
20. 同步核心速度(Synchronize Core Speed)建议开启
同步核心速度,用来决定:
模拟器是否强制让 CPU、GPU、定时器等核心模块,
以“一致、受控的节奏”推进,
而不是各跑各的、能快就快。
太长不看的结论:求稳定的情况必开。
21. 同步内存操作(Sync Memory Operations)
同步内存操作,用来决定:
模拟器是否在 CPU ↔ GPU ↔ 内存 的关键交互点,
强制插入更严格的同步与可见性保证,
以避免“谁先看到数据”的不确定性。
推荐策略
- 稳定路线用户:开启
- 纯追 FPS / benchmark:关闭
22. 内存布局(Memory Layout:4GB / 6GB / 8GB)推荐 4GB
内存布局,用来决定:
模拟器在逻辑上“假装 Switch 主机拥有多少可用内存”,
从而影响地址空间、资源分配策略与游戏的内存行为假设。
背景:真实 Switch 的内存情况真实 Nintendo Switch(Tegra X1):
- 物理内存:4GB
- CPU / GPU / 系统共用
- 游戏在设计时:
- 默认可用内存区间
- 默认资源规模
- 默认分配策略
都是围绕 4GB 来写的
所以你懂的 4GB 就好
至此已经设置完毕,亲测这一套设置在我现在的odin3无完善turnip驱动支持的情况比较稳定,fps也几乎是60。体验不错,不想看结识的朋友照着每一项目逐个按照推荐改就行。如果后续Eden加入新的独特选项,我会继续跟进。
[
本帖最后由 gggbdm 于 2025-12-23 12:27 编辑 ]
eden还是不错的 我最近玩的最多的是p4g和p5r。官方fork更新的很勤,和citron那边共享了开发思路。现在几乎所有的问题都是安卓上Vulkan驱动接口和Nvidia switch黑盒驱动模拟的问题,这个只能慢慢拖。