iOS: expose GS Back Thread mode in Graphics settings

Surface the GS Back Thread (GSBackThreadMode) setting in the Graphics
panel under a Performance section, with a picker for Disabled (default),
Inline Records and Lockstep debug modes, and Pipelined, which splits GS
emulation across a second thread on multi-core devices. The two debug
modes are flagged as much slower and not for play.

The setting is persisted and applied through the same Setting<Int> path
as the other EmuCore/GS options, using the guarded graphics-apply helper
so it cannot fire while SettingsStore is loading.
This commit is contained in:
J1coding
2026-07-24 12:15:28 +02:00
committed by Jeen
parent 622887f093
commit 38f4358b0c
2 changed files with 31 additions and 0 deletions
@@ -554,6 +554,16 @@ final class SettingsStore {
_textureFilteringConfig.writer(_textureFilteringConfig.section, _textureFilteringConfig.key, textureFiltering)
_textureFilteringConfig.onSet?(textureFiltering)
}}
let _backThreadModeConfig = Setting<Int>(
section: "EmuCore/GS", key: "GSBackThreadMode", default: 0,
suppressible: false,
writer: { s, k, v in ARMSX2Bridge.setINIInt(s, key: k, value: Int32(v)) },
onSet: { _ in SettingsStore.shared.requestGraphicsApplyGuarded() })
var backThreadMode: Int = 0 { didSet {
guard !(_backThreadModeConfig.suppressible && suppressINIWrites) else { return }
_backThreadModeConfig.writer(_backThreadModeConfig.section, _backThreadModeConfig.key, backThreadMode)
_backThreadModeConfig.onSet?(backThreadMode)
}}
let _hardwareMipmappingConfig = Setting<Bool>(
section: "EmuCore/GS", key: "hw_mipmap", default: true,
suppressible: false,
@@ -1724,6 +1734,7 @@ final class SettingsStore {
upscaleMultiplier = ARMSX2Bridge.getINIFloat("EmuCore/GS", key: "upscale_multiplier", defaultValue: 1.0)
vsyncQueueSize = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "VsyncQueueSize", defaultValue: 8))
textureFiltering = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "filter", defaultValue: 2))
backThreadMode = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "GSBackThreadMode", defaultValue: 0))
hardwareMipmapping = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "hw_mipmap", defaultValue: true)
fxaa = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "fxaa", defaultValue: false)
casMode = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "CASMode", defaultValue: 0))
@@ -1947,6 +1958,7 @@ final class SettingsStore {
upscaleMultiplier = ARMSX2Bridge.getINIFloat("EmuCore/GS", key: "upscale_multiplier", defaultValue: 1.0)
vsyncQueueSize = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "VsyncQueueSize", defaultValue: 8))
textureFiltering = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "filter", defaultValue: 2))
backThreadMode = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "GSBackThreadMode", defaultValue: 0))
hardwareMipmapping = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "hw_mipmap", defaultValue: true)
fxaa = ARMSX2Bridge.getINIBool("EmuCore/GS", key: "fxaa", defaultValue: false)
casMode = Int(ARMSX2Bridge.getINIInt("EmuCore/GS", key: "CASMode", defaultValue: 0))
@@ -2455,6 +2467,7 @@ final class SettingsStore {
upscaleMultiplier = 1.0 // Native PS2
vsyncQueueSize = 8
textureFiltering = 2 // Bilinear (PS2)
backThreadMode = 0 // Disabled
hardwareMipmapping = true
fxaa = false
casMode = 0 // Disabled
@@ -34,6 +34,24 @@ struct GraphicsSettingsView: View {
var body: some View {
Form {
Section {
intPicker("GS Back Thread", selection: $settings.backThreadMode, options: [
("Disabled (Default)", 0),
("Inline Records (Debug)", 1),
("Lockstep (Debug)", 2),
("Pipelined (Second GS Thread)", 3),
])
if settings.backThreadMode == 1 || settings.backThreadMode == 2 {
Text(settings.localized("Debug mode — much slower than the default. Do not use for play."))
.font(.caption)
.foregroundStyle(.orange)
}
} header: {
Text(settings.localized("Performance"))
} footer: {
Text(settings.localized("Pipelined splits GS emulation across two threads on multi-core systems and competes for cores with EE/VU threads. The debug modes are much slower — do not use them for play."))
}
Section(settings.localized("Renderer")) {
Picker(settings.localized("Renderer"), selection: $settings.renderer) {
Text(settings.localized("Metal (Hardware)")).tag(17)