diff --git a/app/src/main/assets/graphics_driver/wrapper-gamenative.tzst b/app/src/main/assets/graphics_driver/wrapper-gamenative.tzst new file mode 100644 index 000000000..edb4aacc5 Binary files /dev/null and b/app/src/main/assets/graphics_driver/wrapper-gamenative.tzst differ diff --git a/app/src/main/feature/library/GameSettings.kt b/app/src/main/feature/library/GameSettings.kt index 85aae8e63..caf83d304 100644 --- a/app/src/main/feature/library/GameSettings.kt +++ b/app/src/main/feature/library/GameSettings.kt @@ -398,6 +398,10 @@ class GameSettingsStateHolder { val gfxSelectedBcnEmulationType = mutableIntStateOf(0) val gfxBcnEmulationCacheEntries = mutableStateOf>(emptyList()) val gfxSelectedBcnEmulationCache = mutableIntStateOf(0) + val gfxTranscoderEntries = mutableStateOf>(emptyList()) + val gfxSelectedTranscoder = mutableIntStateOf(0) + val gfxQualityEntries = mutableStateOf>(emptyList()) + val gfxSelectedQuality = mutableIntStateOf(0) val gfxSyncFrame = mutableStateOf(false) val gfxDisablePresentWait = mutableStateOf(false) @@ -1671,6 +1675,32 @@ private fun GraphicsDriverConfigCard( } } + val gamenativeWrapperActive = state.graphicsDriverEntries.value + .getOrElse(state.selectedGraphicsDriver.intValue) { "" } + .equals("Wrapper-Gamenative", ignoreCase = true) + if (gamenativeWrapperActive) { + Spacer(Modifier.height(SettingItemGap)) + + Row(horizontalArrangement = Arrangement.spacedBy(SettingItemGap)) { + Box(Modifier.weight(1f)) { + SettingDropdown( + label = stringResource(R.string.container_graphics_transcoder), + entries = state.gfxTranscoderEntries.value, + selectedIndex = state.gfxSelectedTranscoder.intValue, + onSelected = { state.gfxSelectedTranscoder.intValue = it } + ) + } + Box(Modifier.weight(1f)) { + SettingDropdown( + label = stringResource(R.string.container_graphics_quality), + entries = state.gfxQualityEntries.value, + selectedIndex = state.gfxSelectedQuality.intValue, + onSelected = { state.gfxSelectedQuality.intValue = it } + ) + } + } + } + Spacer(Modifier.height(SettingItemGap)) Row(horizontalArrangement = Arrangement.spacedBy(SettingItemGap)) { diff --git a/app/src/main/feature/settings/containers/ContainerSettingsComposeDialog.kt b/app/src/main/feature/settings/containers/ContainerSettingsComposeDialog.kt index c6757926b..ea546b208 100644 --- a/app/src/main/feature/settings/containers/ContainerSettingsComposeDialog.kt +++ b/app/src/main/feature/settings/containers/ContainerSettingsComposeDialog.kt @@ -1099,6 +1099,10 @@ class ContainerSettingsComposeDialog @JvmOverloads constructor( context.resources.getStringArray(R.array.bcn_emulation_type_entries).toList() state.gfxBcnEmulationCacheEntries.value = context.resources.getStringArray(R.array.bcn_emulation_cache_entries).toList() + state.gfxTranscoderEntries.value = + context.resources.getStringArray(R.array.wrapper_transcoder_entries).toList() + state.gfxQualityEntries.value = + context.resources.getStringArray(R.array.wrapper_quality_entries).toList() val gpuNames = mutableListOf("Device") try { @@ -1125,6 +1129,8 @@ class ContainerSettingsComposeDialog @JvmOverloads constructor( selectByValue(state.gfxBcnEmulationEntries.value, config.get("bcnEmulation") ?: "none", state.gfxSelectedBcnEmulation) selectByValue(state.gfxBcnEmulationTypeEntries.value, config.get("bcnEmulationType") ?: "compute", state.gfxSelectedBcnEmulationType) selectByValue(state.gfxBcnEmulationCacheEntries.value, config.get("bcnEmulationCache") ?: "0", state.gfxSelectedBcnEmulationCache) + selectByValue(state.gfxTranscoderEntries.value, config.get("transcoder") ?: "cpu", state.gfxSelectedTranscoder) + selectByValue(state.gfxQualityEntries.value, config.get("quality") ?: "low", state.gfxSelectedQuality) state.gfxSyncFrame.value = config.get("syncFrame") == "1" state.gfxDisablePresentWait.value = config.get("disablePresentWait") == "1" state.graphicsDriverVersion.value = config.get("version") ?: "" @@ -1286,12 +1292,15 @@ class ContainerSettingsComposeDialog @JvmOverloads constructor( val bcnEmulation = state.gfxBcnEmulationEntries.value.getOrElse(state.gfxSelectedBcnEmulation.intValue) { "none" } val bcnEmulationType = state.gfxBcnEmulationTypeEntries.value.getOrElse(state.gfxSelectedBcnEmulationType.intValue) { "compute" } val bcnEmulationCache = state.gfxBcnEmulationCacheEntries.value.getOrElse(state.gfxSelectedBcnEmulationCache.intValue) { "0" } + val transcoder = state.gfxTranscoderEntries.value.getOrElse(state.gfxSelectedTranscoder.intValue) { "cpu" } + val quality = state.gfxQualityEntries.value.getOrElse(state.gfxSelectedQuality.intValue) { "low" } return "vulkanVersion=$vulkanVersion;version=$version;blacklistedExtensions=$blacklisted;" + "maxDeviceMemory=$maxDeviceMemory;presentMode=$presentMode;syncFrame=$syncFrame;" + "disablePresentWait=$disablePresentWait;resourceType=$resourceType;" + "bcnEmulation=$bcnEmulation;bcnEmulationType=$bcnEmulationType;" + "bcnEmulationCache=$bcnEmulationCache;gpuName=$gpuName;" + - "compositorPresentMode=$compositorPresentMode" + "compositorPresentMode=$compositorPresentMode;" + + "transcoder=$transcoder;quality=$quality" } private fun buildDxvkConfigFromState(): String { diff --git a/app/src/main/feature/shortcuts/ShortcutSettingsComposeDialog.kt b/app/src/main/feature/shortcuts/ShortcutSettingsComposeDialog.kt index 0fa0f52ba..eb4d1aee3 100644 --- a/app/src/main/feature/shortcuts/ShortcutSettingsComposeDialog.kt +++ b/app/src/main/feature/shortcuts/ShortcutSettingsComposeDialog.kt @@ -1815,13 +1815,16 @@ class ShortcutSettingsComposeDialog private constructor( val bcnEmulation = state.gfxBcnEmulationEntries.value.getOrElse(state.gfxSelectedBcnEmulation.intValue) { "auto" } val bcnEmulationType = state.gfxBcnEmulationTypeEntries.value.getOrElse(state.gfxSelectedBcnEmulationType.intValue) { "compute" } val bcnEmulationCache = state.gfxBcnEmulationCacheEntries.value.getOrElse(state.gfxSelectedBcnEmulationCache.intValue) { "0" } + val transcoder = state.gfxTranscoderEntries.value.getOrElse(state.gfxSelectedTranscoder.intValue) { "cpu" } + val quality = state.gfxQualityEntries.value.getOrElse(state.gfxSelectedQuality.intValue) { "low" } return "vulkanVersion=$vulkanVersion;version=$version;blacklistedExtensions=$blacklisted;" + "maxDeviceMemory=$maxDeviceMemory;presentMode=$presentMode;syncFrame=$syncFrame;" + "disablePresentWait=$disablePresentWait;resourceType=$resourceType;" + "bcnEmulation=$bcnEmulation;bcnEmulationType=$bcnEmulationType;" + "bcnEmulationCache=$bcnEmulationCache;gpuName=$gpuName;" + - "compositorPresentMode=$compositorPresentMode" + "compositorPresentMode=$compositorPresentMode;" + + "transcoder=$transcoder;quality=$quality" } private fun buildDxvkConfigFromState(): String { @@ -1861,6 +1864,8 @@ class ShortcutSettingsComposeDialog private constructor( state.gfxBcnEmulationEntries.value = context.resources.getStringArray(R.array.bcn_emulation_entries).toList() state.gfxBcnEmulationTypeEntries.value = context.resources.getStringArray(R.array.bcn_emulation_type_entries).toList() state.gfxBcnEmulationCacheEntries.value = context.resources.getStringArray(R.array.bcn_emulation_cache_entries).toList() + state.gfxTranscoderEntries.value = context.resources.getStringArray(R.array.wrapper_transcoder_entries).toList() + state.gfxQualityEntries.value = context.resources.getStringArray(R.array.wrapper_quality_entries).toList() val gpuNames = mutableListOf("Device") try { @@ -1888,6 +1893,8 @@ class ShortcutSettingsComposeDialog private constructor( selectByValue(state.gfxBcnEmulationEntries.value, config["bcnEmulation"] ?: "none", state.gfxSelectedBcnEmulation) selectByValue(state.gfxBcnEmulationTypeEntries.value, config["bcnEmulationType"] ?: "compute", state.gfxSelectedBcnEmulationType) selectByValue(state.gfxBcnEmulationCacheEntries.value, config["bcnEmulationCache"] ?: "0", state.gfxSelectedBcnEmulationCache) + selectByValue(state.gfxTranscoderEntries.value, config["transcoder"] ?: "cpu", state.gfxSelectedTranscoder) + selectByValue(state.gfxQualityEntries.value, config["quality"] ?: "low", state.gfxSelectedQuality) state.gfxSyncFrame.value = config["syncFrame"] == "1" state.gfxDisablePresentWait.value = config["disablePresentWait"] == "1" diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 1fc6b6593..137b10ed1 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -21,6 +21,7 @@ Wrapper Wrapper-Leegao + Wrapper-Gamenative System @@ -98,6 +99,14 @@ 0 1 + + cpu + gpu + + + low + high + 32 MB 64 MB diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 540cc9451..d17bdac0b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -602,6 +602,8 @@ BCn Emulation BCn Emulation Type BCn Emulation Cache + BCn Transcoder + BCn Quality Snapdragon™ Game Super Resolution 1 Do you want to duplicate this preset? diff --git a/app/src/main/runtime/container/Container.java b/app/src/main/runtime/container/Container.java index 1d410b6d3..c83a62e68 100644 --- a/app/src/main/runtime/container/Container.java +++ b/app/src/main/runtime/container/Container.java @@ -29,7 +29,7 @@ public class Container { public static final String DEFAULT_DXWRAPPER = "dxvk+vkd3d"; public static final String DEFAULT_DXWRAPPERCONFIG = "version=,async=1,asyncCache=1" + ",vkd3dVersion=None,vkd3dLevel=12_1" + ",ddrawrapper=" + Container.DEFAULT_DDRAWRAPPER + ",csmt=3" + ",gpuName=NVIDIA GeForce GTX 480" + ",videoMemorySize=4096" + ",strict_shader_math=1" + ",OffscreenRenderingMode=fbo" + ",renderer=gl"; public static final String DEFAULT_GRAPHICSDRIVERCONFIG = - "vulkanVersion=1.3" + ";version=" + ";blacklistedExtensions=" + ";maxDeviceMemory=0" + ";presentMode=mailbox" + ";syncFrame=0" + ";disablePresentWait=1" + ";resourceType=auto" + ";bcnEmulation=auto" + ";bcnEmulationType=compute" + ";bcnEmulationCache=0" + ";gpuName=Device"; + "vulkanVersion=1.3" + ";version=" + ";blacklistedExtensions=" + ";maxDeviceMemory=0" + ";presentMode=mailbox" + ";syncFrame=0" + ";disablePresentWait=1" + ";resourceType=auto" + ";bcnEmulation=auto" + ";bcnEmulationType=compute" + ";bcnEmulationCache=0" + ";gpuName=Device" + ";transcoder=cpu" + ";quality=low"; public static final String DEFAULT_DDRAWRAPPER = "none"; public static final String DEFAULT_WINCOMPONENTS = "direct3d=1,directsound=0,directmusic=0,directshow=0,directplay=0,xaudio=0,dinput8=1,vcrun2010=1"; public static final String FALLBACK_WINCOMPONENTS = "direct3d=1,directsound=1,directmusic=1,directshow=1,directplay=1,xaudio=1,dinput8=1,vcrun2010=1"; diff --git a/app/src/main/runtime/display/XServerDisplayActivity.java b/app/src/main/runtime/display/XServerDisplayActivity.java index cf4a7d7f4..ea69e8d3e 100644 --- a/app/src/main/runtime/display/XServerDisplayActivity.java +++ b/app/src/main/runtime/display/XServerDisplayActivity.java @@ -7574,14 +7574,22 @@ private void extractGraphicsDriverFiles() { } boolean wantLeegao = "wrapper-leegao".equals(graphicsDriver); + boolean wantGamenative = "wrapper-gamenative".equals(graphicsDriver); File leegaoMarker = new File(rootDir, "usr/lib/.wrapper_leegao"); + File gamenativeMarker = new File(rootDir, "usr/lib/.wrapper_gamenative"); if (wantLeegao) { TarCompressorUtils.extract(TarCompressorUtils.Type.ZSTD, this, "graphics_driver/wrapper-leegao.tzst", rootDir); try { leegaoMarker.createNewFile(); } catch (IOException ignored) {} - } else if (leegaoMarker.exists()) { + gamenativeMarker.delete(); + } else if (wantGamenative) { + TarCompressorUtils.extract(TarCompressorUtils.Type.ZSTD, this, "graphics_driver/wrapper-gamenative.tzst", rootDir); + try { gamenativeMarker.createNewFile(); } catch (IOException ignored) {} + leegaoMarker.delete(); + } else if (leegaoMarker.exists() || gamenativeMarker.exists()) { TarCompressorUtils.extract(TarCompressorUtils.Type.ZSTD, this, "graphics_driver/wrapper" + ".tzst", rootDir); TarCompressorUtils.extract(TarCompressorUtils.Type.ZSTD, this, "layers" + ".tzst", rootDir); leegaoMarker.delete(); + gamenativeMarker.delete(); } if (adrenoToolsDriverId != null && !adrenoToolsDriverId.isEmpty() @@ -7664,16 +7672,20 @@ private void extractGraphicsDriverFiles() { String bcnEmulation = graphicsDriverConfig.get("bcnEmulation"); String bcnEmulationType = graphicsDriverConfig.get("bcnEmulationType"); + int gpuVendorId = GPUInformation.getVendorID(null, null); + // BCn compute shaders are unsupported on Adreno and crash on Xclipse with this wrapper + boolean excludeBcnCompute = gpuVendorId == 20803 || (wantGamenative && gpuVendorId == 0x144D); + switch (bcnEmulation) { case "auto" -> { - if ("compute".equals(bcnEmulationType) && GPUInformation.getVendorID(null, null) != 20803) { + if ("compute".equals(bcnEmulationType) && !excludeBcnCompute) { envVars.put("ENABLE_BCN_COMPUTE", "1"); envVars.put("BCN_COMPUTE_AUTO", "1"); } envVars.put("WRAPPER_EMULATE_BCN", "3"); } case "full" -> { - if ("compute".equals(bcnEmulationType) && GPUInformation.getVendorID(null, null) != 20803) { + if ("compute".equals(bcnEmulationType) && !excludeBcnCompute) { envVars.put("ENABLE_BCN_COMPUTE", "1"); envVars.put("BCN_COMPUTE_AUTO", "0"); } @@ -7683,6 +7695,13 @@ private void extractGraphicsDriverFiles() { default -> envVars.put("WRAPPER_EMULATE_BCN", "1"); } + if (wantGamenative) { + String transcoder = graphicsDriverConfig.get("transcoder"); + envVars.put("WRAPPER_BCN_GPU", "gpu".equalsIgnoreCase(transcoder) ? "1" : "0"); + String wrapperQuality = graphicsDriverConfig.get("quality"); + envVars.put("WRAPPER_ASTC_BLOCK", "high".equalsIgnoreCase(wrapperQuality) ? "4x4" : "8x8"); + } + String bcnEmulationCache = graphicsDriverConfig.get("bcnEmulationCache"); envVars.put("WRAPPER_USE_BCN_CACHE", bcnEmulationCache);