Compare commits

...

47 Commits

Author SHA1 Message Date
CamilleLaVey 51dc28500b [vulkan, android] Add BGR565 emulated toggle 2026-04-23 15:12:41 +02:00
CamilleLaVey 2b1f163487 [vulkan] Small adjustments to dynamic_vertex_input setting 2026-04-23 15:12:41 +02:00
CamilleLaVey 52281d16e1 Revert "[vulkan] Updated VertexInput Stream offset" 2026-04-23 15:12:41 +02:00
CamilleLaVey d6105c5222 Revert "[vulkan] Rework DynamicState - ExtendedDynamicState" 2026-04-23 15:12:41 +02:00
CamilleLaVey 22bd482732 Revert "[vulkan] Adjustment ExtendedDynamicState" 2026-04-23 15:12:41 +02:00
CamilleLaVey 6770330d8e Revert "[vulkan] Adjusted pipeline keys inside patchControlPoints" 2026-04-23 15:12:41 +02:00
CamilleLaVey e776e337f2 Revert "fix comp err"
This reverts commit 470faa62551294e8073478552ccec437b0d4a9c9.
2026-04-23 15:12:41 +02:00
lizzie b0c04cfab4 fix comp err 2026-04-23 15:12:41 +02:00
CamilleLaVey 69e846f7ad [vulkan] Adjusted pipeline keys inside patchControlPoints 2026-04-23 15:12:41 +02:00
CamilleLaVey 9c53463b81 [vulkan] Adjustment ExtendedDynamicState 2026-04-23 15:12:41 +02:00
CamilleLaVey 0f749028b4 [vulkan] Rework DynamicState - ExtendedDynamicState 2026-04-23 15:12:41 +02:00
CamilleLaVey fee2c7edeb [vulkan] Updated VertexInput Stream offset 2026-04-23 15:12:41 +02:00
CamilleLaVey 657c432254 Fix license headers 2026-04-23 15:12:41 +02:00
CamilleLaVey e3725a160e [vulkan] Adjustment Viewport/Scissor in DynamicState 2026-04-23 15:12:41 +02:00
CamilleLaVey 0e2ff87fb2 [vulkan] Adjustment ImageView creation flags 2026-04-23 15:12:41 +02:00
CamilleLaVey e754ed9018 [vulkan] Adjustment ResetQueryPool 2026-04-23 15:12:41 +02:00
CamilleLaVey d7c1edbde2 [test] Force Synchronization of buffers 2026-04-23 15:12:41 +02:00
CamilleLaVey 5a0c7095c7 [vulkan] Adjustment VK_EXT_transform_feedback & VK_EXT_conditional_rendering 2026-04-23 15:12:41 +02:00
CamilleLaVey de273aefa5 [vulkan] Adjustment VK_EXT_transform_feedback Nº 2 2026-04-23 15:12:41 +02:00
CamilleLaVey da938123e1 [vulkan] Adjustment VK_EXT_transform_feedback 2026-04-23 15:12:41 +02:00
CamilleLaVey 9e2013d7f8 [test] Removed QCOM from presync workaround 2026-04-23 15:12:41 +02:00
CamilleLaVey 7872ae9985 [vulkan] Adjustment VK_EXT_conditional_rendering #1 2026-04-23 15:12:41 +02:00
CamilleLaVey 0a690baa3a [vulkan] Restore gatting flush operation on removed gpu accuracy to new gpu accuracy logic 2026-04-23 15:12:41 +02:00
CamilleLaVey a7cfd8b6a5 Revert "[vulkan] Adjusted VK_EXT_vertex_input_dynamic_state" 2026-04-23 15:12:41 +02:00
CamilleLaVey f1e4f69fc9 Revert "[vulkan] Adjustment ExtendedDynamicState System Nª1" 2026-04-23 15:12:41 +02:00
CamilleLaVey c68de909b8 [vulkan] Adjustment ExtendedDynamicState System Nª1 2026-04-23 15:12:41 +02:00
CamilleLaVey f085a85fbd [vulkan] Adjusted VK_EXT_vertex_input_dynamic_state 2026-04-23 15:12:41 +02:00
CamilleLaVey 4394321aaa [vulkan] Adjusted RobustImageAccess 2026-04-23 15:12:41 +02:00
CamilleLaVey baf51950e6 [vulkan] Adjusted VK_EXT_robustness2 2026-04-23 15:12:41 +02:00
CamilleLaVey 4753abd9f4 [vulkan] Adjusted VK_EXT_Custom_Border_Color implementation 2026-04-23 15:12:41 +02:00
CamilleLaVey 99d3f588f8 [vulkan] Removal of VK_EXT_unified_image_layouts 2026-04-23 15:12:41 +02:00
lizzie 417ed904f0 [dynarmic] fix MWAIT push/pop not being handled properly on xbyak (#3875)
push %edx is not what i wanted, nor what anybody wants, xbyak silently accepting this before was not intended
now that xbyak is updated this is an issue

the issue was simply:
a) ptr being overwritten (if it happened to be EDX/EBX/EAX) due to changed WAITPKG logic (oops)
b) xbyak not reporting wrong r32 pop/push on older versions thus missing it and now it throws an exception

Signed-off-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3875
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-04-23 05:06:33 +02:00
wildcard 838cc926f6 keyboard fixes (#3865)
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3865
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-04-23 03:43:54 +02:00
coolone 860acb4faf [android] Fix crash on start any games for many handhelds (Ayaneo, Retroid etc) (#3647)
## Summary
This change hardens Android Picture-in-Picture handling to avoid runtime crashes on devices/ROMs where PiP APIs are unavailable or behave inconsistently.

## What changed
- Added a feature gate for PiP support using `FEATURE_PICTURE_IN_PICTURE`.
- Early-returned from PiP flows when unsupported.
- Wrapped PiP API calls (`enterPictureInPictureMode`, `setPictureInPictureParams`) in guarded handlers that catch `IllegalStateException` and `UnsupportedOperationException`.
- Logged one warning per failed PiP action to avoid log spam.

## Why
On some Android devices, calling PiP APIs can throw at runtime even when the app is otherwise functioning normally. This patch prevents those calls from crashing/interrupting emulation and keeps behavior unchanged on supported devices.

## Notes
- No behavior changes for fully PiP-capable devices.
- Safe no-op on unsupported devices.

Co-authored-by: Nikolai Trukhin <coolone.official@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3647
Reviewed-by: DraVee <chimera@dravee.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-04-22 05:32:52 +02:00
Eden CI a0bb6324c0 [dist, android] Update translations from Transifex for Apr 21 (#3871)
Automatic translation update for Apr 21

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3871
2026-04-21 16:02:40 +02:00
MaranBr 3a823de605 [dynarmic] Remove Ignore Global Monitor from CPU Accuracy Auto (#3846)
This fixes a flickering issue in some games, such as The Legend of Zelda: Echoes of Wisdom.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3846
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
2026-04-21 05:03:43 +02:00
crueter 0257a8d491 [desktop] Change data manager to use tabs instead of a list (#3856)
Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3856
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
2026-04-21 04:01:39 +02:00
PavelBARABANOV 6c76908ddb [android] Allow manual overlay toggle even with controller connected + move async GPU options to hacks (#3862)
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3862
Co-authored-by: PavelBARABANOV <pavelbarabanov94@gmail.com>
Co-committed-by: PavelBARABANOV <pavelbarabanov94@gmail.com>
2026-04-17 20:29:45 +02:00
omardotdev e6ad51e3d5 [settings] remove duplicate settings (#3847)
this removes the duplicate serial knob, battery/unit serial shown on the settings tab and uses the debugging tab instead
(this used to be a pr to fix breeze compatibility issues where the text/input fields would look wrong when the theme was set to breeze but since the settings was moved its not really needed to change the window size)

Co-authored-by: Omar <180954465+omardotdev@users.noreply.github.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3847
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Co-authored-by: omardotdev <omardotdev@eden-emu.dev>
Co-committed-by: omardotdev <omardotdev@eden-emu.dev>
2026-04-17 06:58:40 +02:00
Eden CI f11b69d6b7 [dist, android] Update translations from Transifex for Apr 14 (#3859)
Automatic translation update for Apr 14

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3859
Co-authored-by: Eden CI <ci@eden-emu.dev>
Co-committed-by: Eden CI <ci@eden-emu.dev>
2026-04-14 18:14:01 +02:00
xbzk 27cadb24f3 [android, intent] Run restoreContentForGame for shortcut launching + Improve custom settings context for shortcut launching (based on normal launch) (#3854)
intended to fix two bugs identified by Pavel upon android shortcut launching (and prolly all FEs since the rely on intent launching too):
1. external content not loading: fixed by running restoreContentForGame  for per game mount in content path.
2. custom settings no loading: that was proven to be user side, but adjustments were made to match normal launch.
should be harmless for normal usage. once validated can be merged.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3854
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: xbzk <xbzk@eden-emu.dev>
Co-committed-by: xbzk <xbzk@eden-emu.dev>
2026-04-14 00:21:51 +02:00
John a7ef19e028 [settings] Exposes the Hidden GPU Async Setting on other Platforms (#3833)
Disabling it may:
- Alleviates and Fixes flickering in Pokemon LZA, Kirby, Jamboree, XCDE, etc.
- Audio improvements in Metroid Prime 4

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3833
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: John <john@eden-emu.dev>
Co-committed-by: John <john@eden-emu.dev>
2026-04-13 00:28:12 +02:00
Eden CI 2c1eff2e60 [dist, android] Update translations from Transifex for Apr 11 (#3850)
Automatic translation update for Apr 11

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3850
Co-authored-by: Eden CI <ci@eden-emu.dev>
Co-committed-by: Eden CI <ci@eden-emu.dev>
2026-04-11 18:37:13 +02:00
xbzk abb616c357 [vk,swapchain] vsync: Changed Immediate fallback from (FIFO) to (Mailbox, then FIFO) (#3746)
Just discovered that stock adreno drivers on a730 had no Immediate VSync mode available, and it was falling back to FIFO, which causes a lot of response delay in Unity games.

But if someone chose Immediate, it prefers low latency above buffering, so Mailbox is his friend, and FIFO is his nemesis.

So i just changed Immediate to fall back to Mailbox first, and only if Mailbox is not available either it falls back to FIFO:

Immediate -> Mailbox -> FIFO;
Mailbox -> FIFO;
FIFO Relaxed -> FIFO.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3746
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Co-authored-by: xbzk <xbzk@eden-emu.dev>
Co-committed-by: xbzk <xbzk@eden-emu.dev>
2026-04-11 02:49:55 +02:00
lizzie c95cb8f8ec [hle] improved flusher that uses jthread (#3837)
not happy with this impl, but I made this a bit quickly to demostrate it can be done better :)

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3837
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2026-04-09 23:46:38 +02:00
CamilleLaVey 3d0eb4b5d7 [vulkan] 1st Vulkan Global Maintenance (#3839)
This pr aims to make a first step into giving Eden's Vulkan backend maintenance with better formatting, understanding and reduce the redundancy between some wrong implementations:

-> ProvokingVertex: Has been reworked completely, now the wiring to ExtendedDynamicState3 (ProvokingVertexMode) it works safe, the gating of the extension no longer requires user enabling on UI, it will be enabled automatically based on what features of the extension are available on driver, depending if first or last mode are available and also will be properly set under TrasformFeedback operations; this way we're gonna ensure all drivers, including Android stock drivers on QCOM, Mali and other mobile vendors drivers access correctly to the extension, fixing some graphical issues (flickering textures or wrong sccisors on vertex that required first mode) generated by the missing first mode handling or the proper clearing on pipeline state. This change will increase/ decrease slightly the performance on some games that changes dynamically between first and last modes, but will also ensure a clear path to GPU to use resources smartly, reducing VRAM consumption in PC and MEM/GPU percentage of use on Android (marginal to 5 - 8% approx).

-> Removal VK_EXT_multi_draw: It has passed some months since the first try to implement this feature, but wasn't completed so functionality was null to negative, taking space in source and using small CPU cicles for initialization during device creation that reduced CPU effectiveness by 2 - 5%, aside that, after reviewing the situation of formally introducing handling for multidraws to reduce the floods of constants draw calls into 1 per batch, seems to not pay the overhead when the multidraw capacity is less or equal to 1, aside that, for the time being batching multidraws will introduce indirections on each batch of command draws, that graphical issues will appear and reducing performance can happen, something it was gonna solve. For the time being it's discarded, but, may be analyzed the chance to introduce it properly in a later date.

-> Removal VK_EXT_indexing_descriptor: Currently the implementation of this feature was partial, with not proper handling on layouts; just the initial checks on device creation and chained up to the pNext feature, currently this extension will require a buffer cache and texture cache rework to set layouts and reduce the amount of use of descriptor into making it a less expensive cost effective, aside that to generate a path for the Bindless Texture and Bindless Buffer, allowing to track state of textures in runtime and ensuring the state of some compiled shaders doesn't change if it's no needed, among other benefits, besides that, enabling this feature was only generating innecessary checks on GPU, so consumption would be higher than it should be.

-> Removal of VK_EXT_swapchain_maintenance1: The use of this feature was really conditional to certain support on newer drivers and cards, which wasn't available for all platforms, I concluded that if the support for this instance wasn't really there, the cost effective between the try to initialize it and running it, won't be good as when it didn't exist on our Vulkan device, with also the constant factor of not being completely implemented, right now I'm aiming to reduce the complexity on Vulkan side to keep it as simple as it could for a future video_core rework, which may start somewhere these weeks.

-> Refined the Maintenance features: Meawhile this features are usually inherent to Vulkan core functionality, sometimes drivers doesn't expose them well, which leads to Eden run Vulkan without really noticing the existence of maintenance features on driver to improve stability, so we're tied to declare them and load them when a device creation starts by asking if driver supports and which, currently 1 - 5 are core maintenance features, meanwhile the 7 - 9 are more experimental and not being available everywhere, so right now to help drivers give attention to this features we not only load them, but also calculate with features bits which features inside Maintenance5 are available to use, that was the initial purpose, but we weren't using the full potential of the extension; I made cleaned part of the unneeded log code for the initialization of this Maintenance5 and it's feature flags, but also making an operation to sanitize depth/ stencil when One is not available in swizzle operations, making it easier to draw it; it's also needed to mention that Maintenance9 was removed from source code until we can have better handling on Arrays2D, aside that, the use of the extension was really conditional to certain drivers being capable of use it, so I remove it.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3839
Co-authored-by: CamilleLaVey <camillelavey99@gmail.com>
Co-committed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-04-08 23:46:50 +02:00
CamilleLaVey 1b4a79c7ee [android] QoL changes to Android Phase - 1 (#3832)
This pr content and goal is to provide following to Eden's user base issues with settings, adjust default values on settings and refactor some handlings to improve the plug-and-play factor:

-> Combo-box for ASTC Recompression Method Removed: The removal of this toggle was due to the redundant process inside Android devices, most drivers do suppot ASTC handling natively and meanwhile this option provided some benefits to some older Mali devices, the specifications from those and the real compatibility doesn't pay the need for this setting, unless something else is provided to be wrong, the default setting will be uncompressed and no longer available in UI to change. Removed some dead code along with it.

-> Removal of ASTC Decode Method ifdef block for Android: Since Yuzu's, the handling for this option was strangely set on CPU, having a specific block for Android in settings, possibly due to the constant spikes on GPU usage that wouldn't be good to load GPU with the whole flow of operations; but since then and until today, Eden's constant effort to make operations more accurate and smartly resolved, have marked the difference that now CPU default on Android no longer provides the benefit to relief GPU stress than reducing performance in some heavy draw commands on some games; the default will be set to GPU to keep parity with PC configuration aiming for a global configuration with all platforms. The setting will be kept to user range, unless is proved to no longer be needed, right now low end devices could still have benefit from CPU/Async, but requires testing from community to show real potential.

-> Adjusted default value of ExtendedDynamicState: Currently we're facing some issues of logic inside of ExtendedDynamicState implementation, that makes it a bit unstable when it comes to use the disabled mode, right now we jump to ExtendedDynamicState1 for more stability, meanwhile we fix the remaining issues in future updates (currently one fix will be presented - or would be merged along this pr, the 1st Global Vulkan Maintenance which has some fixes for this situation), so stock drivers and other mobile drivers will behave and benefit from this.

-> Exposed hidden and defaulted settings to user's UI: Yuzu implemented some settings that were available on PC's UI but weren't presented on Android's UI or wasn't something expected to do, either way there are some strange behaviors due to this default settings and each of them do something different, i'm not gonna dive into a deep explanation, but to make it short, they stablish asynchronous operations for GPU operations, like Async GPU Emulation (to use a CPU thread to boost performance with GPU emulation, currently a performance hack), Asynchronous Vulkan Presentation this does something a like to disperse draw's/ syncing from TimelineSemaphores and set a thread of CPU to help in running some Vulkan operations (another performance Hack), meanwhile most of the Desktop drivers are mostly nice with this setting, Nvidia aren't due to the nature of the hack, so provokes black screen or failing into initialize games. Mostly Asynchronous operations are fast-paths/ hacks to improve performance to the cost of some graphical issues like the pop-in with Asynchronous Shader Building during the shader compilations, sometimes the trade-off could give random crashes and other issues. Android it's not the exception and currently by disabling GPU Async Emulation user's will be able to fix some strange flickering on Zelda - Link's Awakening (NCE) and other games suffering from similar issues, may also fix random crashes on games that are supposed to work. These settings will be exposed for a short amount of time, meanwhile I receive feedback of the usefulness of having them active or the whole operation being used on Android, aside that, disabling them or one of them will inevitable reduce performance a bit, not so notorious, but it will be up to user's decision now to use them or not.

-> AMD FidelityFX's Super Resolution UI handling (a personal request): Now the slider default value will be 0% and will only appear whenever FSR is choosed among other window adapting filters, this will also work with the quick setting menu during runtime.

-> Fixed the issue of changing drivers removing all games compiled shader cache: Currently our implementation to safeguard users from unknown issues when a different driver tries to load/ read compiled shaders from another version of Turnip/ QCOM driver, that will delete shaders if the driver is removed or changed; deleted all games compiled shader cache, which increased the annoyance on Android users along with adding unneeded complexity, this used to happen whenever a driver was changed in global settings or per-game settings. Now no longer will happen if the driver is changed on global settings and changing drivers in per-game configuration will only delete current game where the driver was change without affecting others, from here, I'll apologize for this unneeded situation.

-> Refactored the input controller detection (another request of mine, hehehe...): This implementation will work to reduce the burden on a new installation (since I have to test everything personally, cuz testers are lazy ass mfs), the input detection is now more accurate to what kind of input a device has, whether is in-built or wireless gamepad, will map it once Eden detect's physical input by reading the controllers inputs that OS provides natively and set or disable touchscreen controllers automatically:

   - If in-built is detected (Ayaneo, Ayn, Retroid or any Android handheld), Eden will map it automatically and will disable touchscreen controller.
  - If Wireless gamepad is detected, the same behavior as described above will happen with the extra to recover touchscreen controller whenever the gamepad goes off.

It was quite funny to do this, cuz Xiaomi and some other manufacturers always do strange shenanigans with how the inputs are detected (wasn't funny).

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3832
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Co-authored-by: CamilleLaVey <camillelavey99@gmail.com>
Co-committed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-04-08 23:42:55 +02:00
111 changed files with 9518 additions and 10046 deletions
+333 -360
View File
File diff suppressed because it is too large Load Diff
+301 -327
View File
File diff suppressed because it is too large Load Diff
+301 -327
View File
File diff suppressed because it is too large Load Diff
+301 -327
View File
File diff suppressed because it is too large Load Diff
+301 -327
View File
File diff suppressed because it is too large Load Diff
+301 -327
View File
File diff suppressed because it is too large Load Diff
+330 -357
View File
File diff suppressed because it is too large Load Diff
+301 -327
View File
File diff suppressed because it is too large Load Diff
+303 -331
View File
File diff suppressed because it is too large Load Diff
+301 -327
View File
File diff suppressed because it is too large Load Diff
+363 -388
View File
File diff suppressed because it is too large Load Diff
+303 -331
View File
File diff suppressed because it is too large Load Diff
+301 -327
View File
File diff suppressed because it is too large Load Diff
+301 -327
View File
File diff suppressed because it is too large Load Diff
+302 -328
View File
File diff suppressed because it is too large Load Diff
+301 -327
View File
File diff suppressed because it is too large Load Diff
+303 -331
View File
File diff suppressed because it is too large Load Diff
+495 -493
View File
File diff suppressed because it is too large Load Diff
+301 -327
View File
File diff suppressed because it is too large Load Diff
+303 -331
View File
File diff suppressed because it is too large Load Diff
+304 -331
View File
File diff suppressed because it is too large Load Diff
+303 -329
View File
File diff suppressed because it is too large Load Diff
+304 -331
View File
File diff suppressed because it is too large Load Diff
+301 -327
View File
File diff suppressed because it is too large Load Diff
+301 -328
View File
File diff suppressed because it is too large Load Diff
+303 -330
View File
File diff suppressed because it is too large Load Diff
+301 -327
View File
File diff suppressed because it is too large Load Diff
@@ -15,6 +15,7 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.graphics.Rect
import android.graphics.drawable.Icon
@@ -100,6 +101,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
private var romSwapGeneration = 0
private var hasEmulationSession = processHasEmulationSession
private val romSwapStopTimeoutRunnable = Runnable { onRomSwapStopTimeout() }
private val pictureInPictureFailureActions: MutableSet<String> = mutableSetOf()
private fun onRomSwapStopTimeout() {
if (!isWaitingForRomSwapStop) {
@@ -246,6 +248,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
nfcReader.startScanning()
startMotionSensorListener()
InputHandler.updateControllerData()
notifyPhysicalControllerState()
buildPictureInPictureParams()
}
@@ -265,12 +268,18 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
}
override fun onUserLeaveHint() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
if (BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && !isInPictureInPictureMode) {
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
enterPictureInPictureMode(pictureInPictureParamsBuilder.build())
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ||
!isPictureInPictureSupported() ||
!BooleanSetting.PICTURE_IN_PICTURE.getBoolean() ||
isInPictureInPictureMode
) {
return
}
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
runPictureInPictureAction("enter picture-in-picture mode") {
enterPictureInPictureMode(pictureInPictureParamsBuilder.build())
}
}
@@ -403,8 +412,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
val isPhysicalKeyboard = event.source and InputDevice.SOURCE_KEYBOARD == InputDevice.SOURCE_KEYBOARD &&
event.device?.isVirtual == false
val isControllerInput = event.source and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK ||
event.source and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD
val isControllerInput = InputHandler.isPhysicalGameController(event.device)
if (!isControllerInput &&
event.source and InputDevice.SOURCE_MOUSE != InputDevice.SOURCE_MOUSE &&
@@ -425,8 +433,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
}
override fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
val isControllerInput = event.source and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK ||
event.source and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD
val isControllerInput = InputHandler.isPhysicalGameController(event.device)
if (!isControllerInput &&
event.source and InputDevice.SOURCE_KEYBOARD != InputDevice.SOURCE_KEYBOARD &&
@@ -460,38 +467,36 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
}
private fun isGameController(deviceId: Int): Boolean {
val device = InputDevice.getDevice(deviceId) ?: return false
val sources = device.sources
return sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD ||
sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK
return InputHandler.isPhysicalGameController(InputDevice.getDevice(deviceId))
}
override fun onInputDeviceAdded(deviceId: Int) {
if (isGameController(deviceId)) {
InputHandler.updateControllerData()
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container) as? NavHostFragment
val emulationFragment =
navHostFragment?.childFragmentManager?.fragments?.firstOrNull() as? org.yuzu.yuzu_emu.fragments.EmulationFragment
emulationFragment?.onControllerConnected()
notifyPhysicalControllerState()
}
}
override fun onInputDeviceRemoved(deviceId: Int) {
InputHandler.updateControllerData()
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container) as? NavHostFragment
val emulationFragment =
navHostFragment?.childFragmentManager?.fragments?.firstOrNull() as? org.yuzu.yuzu_emu.fragments.EmulationFragment
emulationFragment?.onControllerDisconnected()
notifyPhysicalControllerState()
}
override fun onInputDeviceChanged(deviceId: Int) {
if (isGameController(deviceId)) {
InputHandler.updateControllerData()
notifyPhysicalControllerState()
}
}
private fun notifyPhysicalControllerState() {
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.fragment_container) as? NavHostFragment
val emulationFragment =
navHostFragment?.childFragmentManager?.fragments?.firstOrNull() as? org.yuzu.yuzu_emu.fragments.EmulationFragment
emulationFragment?.onPhysicalControllerStateChanged(InputHandler.androidControllers.isNotEmpty())
}
override fun onSensorChanged(event: SensorEvent) {
if (!NativeLibrary.isRunning() || NativeLibrary.isPaused()) {
return
@@ -654,7 +659,29 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
return this.apply { setActions(pictureInPictureActions) }
}
private fun isPictureInPictureSupported() =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
private fun runPictureInPictureAction(actionName: String, action: () -> Unit) {
try {
action()
} catch (e: IllegalStateException) {
if (pictureInPictureFailureActions.add(actionName)) {
Log.warning("[PiP] Failed to $actionName: ${e.message}")
}
} catch (e: UnsupportedOperationException) {
if (pictureInPictureFailureActions.add(actionName)) {
Log.warning("[PiP] Failed to $actionName: ${e.message}")
}
}
}
fun buildPictureInPictureParams() {
if (!isPictureInPictureSupported()) {
return
}
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
@@ -664,7 +691,9 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && isEmulationActive
)
}
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
runPictureInPictureAction("set picture-in-picture params") {
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
}
}
fun displayMultiplayerDialog() {
@@ -1,3 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -33,8 +37,10 @@ object SoftwareKeyboard {
val emulationActivity = NativeLibrary.sEmulationActivity.get()
val overlayView = emulationActivity!!.findViewById<View>(R.id.surface_input_overlay)
overlayView.requestFocus()
val im =
overlayView.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
im.restartInput(overlayView)
im.showSoftInput(overlayView, InputMethodManager.SHOW_FORCED)
// There isn't a good way to know that the IMM is dismissed, so poll every 500ms to submit inline keyboard result.
@@ -57,7 +57,8 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
container: ViewGroup,
setting: IntSetting,
namesArrayId: Int,
valuesArrayId: Int
valuesArrayId: Int,
onValueChanged: ((Int) -> Unit)? = null
) {
val inflater = LayoutInflater.from(emulationFragment.requireContext())
val itemView = inflater.inflate(R.layout.item_quick_settings_menu, container, false)
@@ -89,6 +90,7 @@ class QuickSettings(val emulationFragment: EmulationFragment) {
setting.setInt(values[index])
saveSettings()
valueView.text = name
onValueChanged?.invoke(values[index])
}
}
radioGroup.addView(radioButton)
@@ -17,11 +17,14 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
USE_CUSTOM_CPU_TICKS("use_custom_cpu_ticks"),
SKIP_CPU_INNER_INVALIDATION("skip_cpu_inner_invalidation"),
FIX_BLOOM_EFFECTS("fix_bloom_effects"),
EMULATE_BGR565("emulate_bgr565"),
CPUOPT_UNSAFE_HOST_MMU("cpuopt_unsafe_host_mmu"),
USE_DOCKED_MODE("use_docked_mode"),
USE_AUTO_STUB("use_auto_stub"),
RENDERER_USE_DISK_SHADER_CACHE("use_disk_shader_cache"),
RENDERER_FORCE_MAX_CLOCK("force_max_clock"),
RENDERER_ASYNCHRONOUS_GPU_EMULATION("use_asynchronous_gpu_emulation"),
RENDERER_ASYNC_PRESENTATION("async_presentation"),
RENDERER_ASYNCHRONOUS_SHADERS("use_asynchronous_shaders"),
RENDERER_REACTIVE_FLUSHING("use_reactive_flushing"),
ENABLE_BUFFER_HISTORY("enable_buffer_history"),
@@ -31,8 +34,6 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
RENDERER_DEBUG("debug"),
RENDERER_PATCH_OLD_QCOM_DRIVERS("patch_old_qcom_drivers"),
RENDERER_VERTEX_INPUT_DYNAMIC_STATE("vertex_input_dynamic_state"),
RENDERER_PROVOKING_VERTEX("provoking_vertex"),
RENDERER_DESCRIPTOR_INDEXING("descriptor_indexing"),
RENDERER_SAMPLE_SHADING("sample_shading"),
GPU_UNSWIZZLE_ENABLED("gpu_unswizzle_enabled"),
PICTURE_IN_PICTURE("picture_in_picture"),
@@ -17,7 +17,6 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
RENDERER_VRAM_USAGE_MODE("vram_usage_mode"),
RENDERER_NVDEC_EMULATION("nvdec_emulation"),
RENDERER_ASTC_DECODE_METHOD("accelerate_astc"),
RENDERER_ASTC_RECOMPRESSION("astc_recompression"),
RENDERER_ACCURACY("gpu_accuracy"),
RENDERER_RESOLUTION("resolution_setup"),
RENDERER_VSYNC("use_vsync"),
@@ -141,13 +141,6 @@ abstract class SettingsItem(
valuesId = R.array.dynaStateValues
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_PROVOKING_VERTEX,
titleId = R.string.provoking_vertex,
descriptionId = R.string.provoking_vertex_description
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_VERTEX_INPUT_DYNAMIC_STATE,
@@ -155,13 +148,6 @@ abstract class SettingsItem(
descriptionId = R.string.vertex_input_dynamic_state_description
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_DESCRIPTOR_INDEXING,
titleId = R.string.descriptor_indexing,
descriptionId = R.string.descriptor_indexing_description
)
)
put(
SliderSetting(
IntSetting.RENDERER_SAMPLE_SHADING,
@@ -349,15 +335,6 @@ abstract class SettingsItem(
valuesId = R.array.astcDecodingMethodValues
)
)
put(
SingleChoiceSetting(
IntSetting.RENDERER_ASTC_RECOMPRESSION,
titleId = R.string.astc_recompression,
descriptionId = R.string.astc_recompression_description,
choicesId = R.array.astcRecompressionMethodNames,
valuesId = R.array.astcRecompressionMethodValues
)
)
put(
SingleChoiceSetting(
IntSetting.RENDERER_VRAM_USAGE_MODE,
@@ -652,6 +629,20 @@ abstract class SettingsItem(
descriptionId = R.string.renderer_force_max_clock_description
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_ASYNCHRONOUS_GPU_EMULATION,
titleId = R.string.renderer_asynchronous_gpu_emulation,
descriptionId = R.string.renderer_asynchronous_gpu_emulation_description
)
)
put(
SwitchSetting(
BooleanSetting.RENDERER_ASYNC_PRESENTATION,
titleId = R.string.renderer_async_presentation,
descriptionId = R.string.renderer_async_presentation_description
)
)
put(
SingleChoiceSetting(
IntSetting.RENDERER_OPTIMIZE_SPIRV_OUTPUT,
@@ -765,6 +756,13 @@ abstract class SettingsItem(
descriptionId = R.string.fix_bloom_effects_description
)
)
put(
SwitchSetting(
BooleanSetting.EMULATE_BGR565,
titleId = R.string.emulate_bgr565,
descriptionId = R.string.emulate_bgr565_description
)
)
put(
SwitchSetting(
BooleanSetting.CPUOPT_UNSAFE_HOST_MMU,
@@ -29,6 +29,7 @@ import org.yuzu.yuzu_emu.databinding.DialogSliderBinding
import org.yuzu.yuzu_emu.databinding.DialogSpinboxBinding
import org.yuzu.yuzu_emu.features.input.NativeInput
import org.yuzu.yuzu_emu.features.input.model.AnalogDirection
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
import org.yuzu.yuzu_emu.features.settings.model.view.AnalogInputSetting
import org.yuzu.yuzu_emu.features.settings.model.view.ButtonInputSetting
import org.yuzu.yuzu_emu.features.settings.model.view.IntSingleChoiceSetting
@@ -381,6 +382,10 @@ class SettingsDialogFragment : DialogFragment(), DialogInterface.OnClickListener
}
scSetting.setSelectedValue(value)
if (scSetting.setting.key == IntSetting.RENDERER_SCALING_FILTER.key) {
settingsViewModel.setShouldReloadSettingsList(true)
}
if (scSetting.setting.key == "app_language") {
settingsViewModel.setShouldRecreateForLanguageChange(true)
// recreate page apply language change instantly
@@ -58,19 +58,38 @@ class SettingsFragmentPresenter(
val pairedSettingKey = item.setting.pairedSettingKey
if (pairedSettingKey.isNotEmpty()) {
val needsGlobal = getNeedsGlobalForKey(pairedSettingKey)
val pairedSettingValue = NativeConfig.getBoolean(
pairedSettingKey,
if (NativeLibrary.isRunning() && !NativeConfig.isPerGameConfigLoaded()) {
!NativeConfig.usingGlobal(pairedSettingKey)
} else {
NativeConfig.usingGlobal(pairedSettingKey)
}
needsGlobal
)
if (!pairedSettingValue) return
}
add(item)
}
private fun getNeedsGlobalForKey(key: String): Boolean {
return if (NativeLibrary.isRunning() && !NativeConfig.isPerGameConfigLoaded()) {
!NativeConfig.usingGlobal(key)
} else {
NativeConfig.usingGlobal(key)
}
}
private fun isFsrScalingFilterSelected(): Boolean {
val fsrFilterValue = resolveFsrScalingFilterValue() ?: return false
val needsGlobal = getNeedsGlobalForKey(IntSetting.RENDERER_SCALING_FILTER.key)
val selectedFilter = IntSetting.RENDERER_SCALING_FILTER.getInt(needsGlobal)
return selectedFilter == fsrFilterValue
}
private fun resolveFsrScalingFilterValue(): Int? {
val names = context.resources.getStringArray(R.array.rendererScalingFilterNames)
val values = context.resources.getIntArray(R.array.rendererScalingFilterValues)
val fsrIndex = names.indexOf(context.getString(R.string.scaling_filter_fsr))
return if (fsrIndex in values.indices) values[fsrIndex] else null
}
// Allows you to show/hide abstract settings based on the paired setting key
private fun ArrayList<SettingsItem>.addAbstract(item: SettingsItem) {
val pairedSettingKey = item.setting.pairedSettingKey
@@ -248,7 +267,9 @@ class SettingsFragmentPresenter(
add(IntSetting.RENDERER_RESOLUTION.key)
add(IntSetting.RENDERER_VSYNC.key)
add(IntSetting.RENDERER_SCALING_FILTER.key)
add(IntSetting.FSR_SHARPENING_SLIDER.key)
if (isFsrScalingFilterSelected()) {
add(IntSetting.FSR_SHARPENING_SLIDER.key)
}
add(IntSetting.RENDERER_ANTI_ALIASING.key)
add(IntSetting.RENDERER_OPTIMIZE_SPIRV_OUTPUT.key)
@@ -259,7 +280,6 @@ class SettingsFragmentPresenter(
add(IntSetting.MAX_ANISOTROPY.key)
add(IntSetting.RENDERER_VRAM_USAGE_MODE.key)
add(IntSetting.RENDERER_ASTC_DECODE_METHOD.key)
add(IntSetting.RENDERER_ASTC_RECOMPRESSION.key)
add(BooleanSetting.SYNC_MEMORY_OPERATIONS.key)
add(BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE.key)
@@ -273,15 +293,16 @@ class SettingsFragmentPresenter(
add(IntSetting.FAST_GPU_TIME.key)
add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key)
add(BooleanSetting.FIX_BLOOM_EFFECTS.key)
add(BooleanSetting.EMULATE_BGR565.key)
add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key)
add(BooleanSetting.RENDERER_ASYNCHRONOUS_GPU_EMULATION.key)
add(BooleanSetting.RENDERER_ASYNC_PRESENTATION.key)
add(SettingsItem.GPU_UNSWIZZLE_COMBINED)
add(HeaderSetting(R.string.extensions))
add(IntSetting.RENDERER_DYNA_STATE.key)
add(BooleanSetting.RENDERER_VERTEX_INPUT_DYNAMIC_STATE.key)
add(BooleanSetting.RENDERER_PROVOKING_VERTEX.key)
add(BooleanSetting.RENDERER_DESCRIPTOR_INDEXING.key)
add(IntSetting.RENDERER_SAMPLE_SHADING.key)
add(HeaderSetting(R.string.display))
@@ -90,6 +90,7 @@ import org.yuzu.yuzu_emu.utils.FileUtil
import org.yuzu.yuzu_emu.utils.GameHelper
import org.yuzu.yuzu_emu.utils.GameIconUtils
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
import org.yuzu.yuzu_emu.utils.InputHandler
import org.yuzu.yuzu_emu.utils.Log
import org.yuzu.yuzu_emu.utils.NativeConfig
import org.yuzu.yuzu_emu.utils.NativeFreedrenoConfig
@@ -114,6 +115,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
val handler = Handler(Looper.getMainLooper())
private var controllerInputReceived = false
private var hasPhysicalControllerConnected = false
private var overlayHiddenByPhysicalController = false
private var _binding: FragmentEmulationBinding? = null
@@ -288,13 +291,23 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
// Game launched via intent (check for existing custom config)
intentGame != null -> {
game?.let { gameInstance ->
runCatching { GameHelper.restoreContentForGame(gameInstance) }
.onFailure {
Log.warning(
"[EmulationFragment] Failed to restore content for intent launch: ${it.message}"
)
}
val customConfigFile = SettingsFile.getCustomSettingsFile(gameInstance)
if (customConfigFile.exists()) {
shouldUseCustom = true
Log.info(
"[EmulationFragment] Found existing custom settings for ${gameInstance.title}, loading them"
)
SettingsFile.loadCustomConfig(gameInstance)
NativeConfig.unloadPerGameConfig()
} else {
shouldUseCustom = false
Log.info(
"[EmulationFragment] No custom settings found for ${gameInstance.title}, using global settings"
)
@@ -666,6 +679,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
driverInUse = driverViewModel.selectedDriverVersion.value
updateQuickOverlayMenuEntry(BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean())
onPhysicalControllerStateChanged(InputHandler.androidControllers.isNotEmpty())
binding.surfaceEmulation.holder.addCallback(this)
binding.doneControlConfig.setOnClickListener { stopConfiguringControls() }
@@ -760,11 +774,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
R.id.menu_quick_overlay -> {
val newState = !BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()
BooleanSetting.SHOW_INPUT_OVERLAY.setBoolean(newState)
updateQuickOverlayMenuEntry(newState)
binding.surfaceInputOverlay.refreshControls()
// Sync view visibility with the setting
toggleOverlay(newState)
updateQuickOverlayMenuEntry(BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean())
NativeConfig.saveGlobalConfig()
true
}
@@ -870,7 +881,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
if (drawerView == binding.quickSettingsSheet) {
isQuickSettingsMenuOpen = true
if (shouldUseCustom) {
SettingsFile.loadCustomConfig(args.game!!)
SettingsFile.loadCustomConfig(game!!)
}
}
}
@@ -1053,7 +1064,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
val shouldShowOverlay = if (args.overlayGamelessEditMode) {
true
} else {
showInputOverlay && emulationViewModel.emulationStarted.value
showInputOverlay && emulationViewModel.emulationStarted.value &&
!hasPhysicalControllerConnected
}
b.surfaceInputOverlay.setVisible(shouldShowOverlay)
if (!isInFoldableLayout) {
@@ -1078,6 +1090,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
private fun addQuickSettings() {
binding.quickSettingsSheet.apply {
val container = binding.quickSettingsSheet.findViewById<ViewGroup>(R.id.quick_settings_container)
val isFsrSelected = isFsrScalingFilterSelected()
container.removeAllViews()
@@ -1159,16 +1172,20 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
IntSetting.RENDERER_SCALING_FILTER,
R.array.rendererScalingFilterNames,
R.array.rendererScalingFilterValues
)
) {
addQuickSettings()
}
quickSettings.addSliderSetting(
R.string.fsr_sharpness,
container,
IntSetting.FSR_SHARPENING_SLIDER,
minValue = 0,
maxValue = 100,
units = "%"
)
if (isFsrSelected) {
quickSettings.addSliderSetting(
R.string.fsr_sharpness,
container,
IntSetting.FSR_SHARPENING_SLIDER,
minValue = 0,
maxValue = 100,
units = "%"
)
}
quickSettings.addIntSetting(
R.string.renderer_anti_aliasing,
@@ -1180,6 +1197,19 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
}
private fun isFsrScalingFilterSelected(): Boolean {
val fsrFilterValue = resolveFsrScalingFilterValue() ?: return false
val selectedFilter = IntSetting.RENDERER_SCALING_FILTER.getInt(needsGlobal = false)
return selectedFilter == fsrFilterValue
}
private fun resolveFsrScalingFilterValue(): Int? {
val names = resources.getStringArray(R.array.rendererScalingFilterNames)
val values = resources.getIntArray(R.array.rendererScalingFilterValues)
val fsrIndex = names.indexOf(getString(R.string.scaling_filter_fsr))
return if (fsrIndex in values.indices) values[fsrIndex] else null
}
private fun openQuickSettingsMenu() {
binding.drawerLayout.closeDrawer(binding.inGameMenu)
binding.drawerLayout.openDrawer(binding.quickSettingsSheet)
@@ -2502,13 +2532,31 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
fun onControllerConnected() {
controllerInputReceived = false
onPhysicalControllerStateChanged(InputHandler.androidControllers.isNotEmpty())
}
fun onControllerDisconnected() {
if (!BooleanSetting.HIDE_OVERLAY_ON_CONTROLLER_INPUT.getBoolean()) return
if (!BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()) return
onPhysicalControllerStateChanged(InputHandler.androidControllers.isNotEmpty())
}
fun onPhysicalControllerStateChanged(hasConnectedControllers: Boolean) {
hasPhysicalControllerConnected = hasConnectedControllers
controllerInputReceived = false
toggleOverlay(true)
if (!isAdded || _binding == null) return
if (binding.surfaceInputOverlay.isGamelessMode()) return
if (hasConnectedControllers) {
if (BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean() &&
BooleanSetting.HIDE_OVERLAY_ON_CONTROLLER_INPUT.getBoolean()) {
overlayHiddenByPhysicalController = true
toggleOverlay(false)
}
return
}
if (overlayHiddenByPhysicalController) {
overlayHiddenByPhysicalController = false
toggleOverlay(true)
}
}
}
@@ -58,6 +58,7 @@ class DriverViewModel : ViewModel() {
private val driversToDelete = mutableListOf<String>()
private var previousDriverPath: String = ""
private var activeGame: Game? = null
private val _shouldShowDriverShaderDialog = MutableStateFlow(false)
val shouldShowDriverShaderDialog: StateFlow<Boolean> get() = _shouldShowDriverShaderDialog
@@ -98,6 +99,7 @@ class DriverViewModel : ViewModel() {
}
fun onOpenDriverManager(game: Game?) {
activeGame = game
if (game != null) {
SettingsFile.loadCustomConfig(game)
}
@@ -116,10 +118,12 @@ class DriverViewModel : ViewModel() {
}
if (!skipShaderWipe && newDriverPath != previousDriverPath) {
wipeAllShaders()
activeGame?.let {
wipeGameShaders(it)
if (!BooleanSetting.DONT_SHOW_DRIVER_SHADER_WARNING.getBoolean(needsGlobal = true)) {
_shouldShowDriverShaderDialog.value = true
if (!BooleanSetting.DONT_SHOW_DRIVER_SHADER_WARNING.getBoolean(needsGlobal = true)) {
_shouldShowDriverShaderDialog.value = true
}
}
}
@@ -139,12 +143,14 @@ class DriverViewModel : ViewModel() {
_shouldShowDriverShaderDialog.value = false
}
private fun wipeAllShaders() {
private fun wipeGameShaders(game: Game) {
viewModelScope.launch {
withContext(Dispatchers.IO) {
val externalFilesDir = YuzuApplication.appContext.getExternalFilesDir(null)
?: return@withContext
val shaderDir = File(
YuzuApplication.appContext.getExternalFilesDir(null)?.canonicalPath +
"/shader/"
externalFilesDir.absolutePath +
"/shader/" + game.settingsName.lowercase()
)
if (shaderDir.exists()) {
shaderDir.deleteRecursively()
@@ -202,6 +208,7 @@ class DriverViewModel : ViewModel() {
}
driversToDelete.clear()
} finally {
activeGame = null
_isDeletingDrivers.value = false
}
}
@@ -17,16 +17,23 @@ import android.graphics.drawable.VectorDrawable
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.text.Editable
import android.text.InputType
import android.util.AttributeSet
import android.view.HapticFeedbackConstants
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.View
import android.view.View.OnTouchListener
import android.view.WindowInsets
import android.view.inputmethod.BaseInputConnection
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputConnection
import androidx.core.content.ContextCompat
import androidx.window.layout.WindowMetricsCalculator
import kotlin.math.max
import kotlin.math.min
import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.features.input.NativeInput
import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.features.input.model.NativeAnalog
@@ -49,6 +56,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
private val overlayButtons: MutableSet<InputOverlayDrawableButton> = HashSet()
private val overlayDpads: MutableSet<InputOverlayDrawableDpad> = HashSet()
private val overlayJoysticks: MutableSet<InputOverlayDrawableJoystick> = HashSet()
private val imeEditable = Editable.Factory.getInstance().newEditable("")
private var inEditMode = false
private var gamelessMode = false
@@ -75,6 +83,63 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
// External listener for EmulationFragment joypad overlay auto-hide
var touchEventListener: ((MotionEvent) -> Unit)? = null
override fun onCheckIsTextEditor(): Boolean = true
override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection {
imeEditable.clear()
outAttrs.inputType =
InputType.TYPE_CLASS_TEXT or
InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS or
InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI or EditorInfo.IME_ACTION_DONE
outAttrs.initialSelStart = 0
outAttrs.initialSelEnd = 0
return object : BaseInputConnection(this, true) {
override fun getEditable(): Editable = imeEditable
override fun commitText(text: CharSequence?, newCursorPosition: Int): Boolean {
if (!text.isNullOrEmpty()) {
forwardCommittedText(text)
}
return super.commitText(text, newCursorPosition)
}
override fun deleteSurroundingText(beforeLength: Int, afterLength: Int): Boolean {
repeat(beforeLength.coerceAtLeast(0)) {
NativeLibrary.submitInlineKeyboardInput(KeyEvent.KEYCODE_DEL)
}
return super.deleteSurroundingText(beforeLength, afterLength)
}
override fun sendKeyEvent(event: KeyEvent): Boolean {
if (event.action != KeyEvent.ACTION_DOWN) {
return true
}
when (event.keyCode) {
KeyEvent.KEYCODE_BACK,
KeyEvent.KEYCODE_DEL,
KeyEvent.KEYCODE_ENTER -> {
NativeLibrary.submitInlineKeyboardInput(event.keyCode)
}
else -> {
val textChar = event.unicodeChar
if (textChar != 0) {
NativeLibrary.submitInlineKeyboardText(textChar.toChar().toString())
}
}
}
return true
}
override fun performEditorAction(actionCode: Int): Boolean {
NativeLibrary.submitInlineKeyboardInput(KeyEvent.KEYCODE_ENTER)
return true
}
}
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
@@ -119,6 +184,25 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
}
}
private fun forwardCommittedText(text: CharSequence) {
val builder = StringBuilder()
text.forEach { character ->
when (character) {
'\n' -> {
if (builder.isNotEmpty()) {
NativeLibrary.submitInlineKeyboardText(builder.toString())
builder.clear()
}
NativeLibrary.submitInlineKeyboardInput(KeyEvent.KEYCODE_ENTER)
}
else -> builder.append(character)
}
}
if (builder.isNotEmpty()) {
NativeLibrary.submitInlineKeyboardText(builder.toString())
}
}
private fun drawGrid(canvas: Canvas) {
val gridSize = IntSetting.OVERLAY_GRID_SIZE.getInt()
val width = canvas.width
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@@ -14,6 +17,60 @@ object InputHandler {
var androidControllers = mapOf<Int, YuzuPhysicalDevice>()
var registeredControllers = mutableListOf<ParamPackage>()
private val controllerButtons = intArrayOf(
KeyEvent.KEYCODE_BUTTON_A,
KeyEvent.KEYCODE_BUTTON_B,
KeyEvent.KEYCODE_BUTTON_X,
KeyEvent.KEYCODE_BUTTON_Y,
KeyEvent.KEYCODE_BUTTON_L1,
KeyEvent.KEYCODE_BUTTON_R1,
KeyEvent.KEYCODE_BUTTON_L2,
KeyEvent.KEYCODE_BUTTON_R2,
KeyEvent.KEYCODE_BUTTON_THUMBL,
KeyEvent.KEYCODE_BUTTON_THUMBR,
KeyEvent.KEYCODE_BUTTON_START,
KeyEvent.KEYCODE_BUTTON_SELECT,
KeyEvent.KEYCODE_DPAD_UP,
KeyEvent.KEYCODE_DPAD_DOWN,
KeyEvent.KEYCODE_DPAD_LEFT,
KeyEvent.KEYCODE_DPAD_RIGHT
)
private val controllerAxes = intArrayOf(
MotionEvent.AXIS_X,
MotionEvent.AXIS_Y,
MotionEvent.AXIS_Z,
MotionEvent.AXIS_RX,
MotionEvent.AXIS_RY,
MotionEvent.AXIS_RZ,
MotionEvent.AXIS_HAT_X,
MotionEvent.AXIS_HAT_Y,
MotionEvent.AXIS_LTRIGGER,
MotionEvent.AXIS_RTRIGGER
)
fun isPhysicalGameController(device: InputDevice?): Boolean {
device ?: return false
if (device.isVirtual) {
return false
}
val sources = device.sources
val hasControllerSource =
sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD ||
sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK
if (!hasControllerSource) {
return false
}
val hasControllerButtons = device.hasKeys(*controllerButtons).any { it }
val hasControllerAxes = device.motionRanges.any { range ->
controllerAxes.contains(range.axis)
}
return hasControllerButtons || hasControllerAxes
}
fun dispatchKeyEvent(event: KeyEvent): Boolean {
val action = when (event.action) {
KeyEvent.ACTION_DOWN -> NativeInput.ButtonState.PRESSED
@@ -57,10 +114,7 @@ object InputHandler {
val inputSettings = NativeConfig.getInputSettings(true)
deviceIds.forEach { deviceId ->
InputDevice.getDevice(deviceId)?.apply {
// Verify that the device has gamepad buttons, control sticks, or both.
if (sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD ||
sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK
) {
if (isPhysicalGameController(this)) {
if (!gameControllerDeviceIds.contains(controllerNumber)) {
gameControllerDeviceIds[controllerNumber] = YuzuPhysicalDevice(
this,
@@ -95,7 +95,7 @@ namespace AndroidSettings {
Settings::Setting<u32> input_overlay_auto_hide{linkage, 5, "input_overlay_auto_hide",
Settings::Category::Overlay,
Settings::Specialization::Default, true, true, &enable_input_overlay_auto_hide};
Settings::Setting<bool> hide_overlay_on_controller_input{linkage, false,
Settings::Setting<bool> hide_overlay_on_controller_input{linkage, true,
"hide_overlay_on_controller_input",
Settings::Category::Overlay,
Settings::Specialization::Default, true,
@@ -32,7 +32,7 @@
<string name="hide_overlay_on_controller_input">إخفاء الطبقة عند إدخال ذراع التحكم</string>
<string name="hide_overlay_on_controller_input_description">إخفاء تلقائي لطبقة عناصر التحكم باللمس عند استخدام ذراع تحكم فعلية. تظهر الطبقة مرة أخرى عند فصل ذراع التحكم.</string>
<string name="invert_confirm_back_controller_buttons">عكس أزرار التأكيد/الرجوع في وحدة التحكم</string>
<string name="invert_confirm_back_controller_buttons_description">قم بتبديل طريقة عمل زري التأكيد والرجوع في نظام Android لتتوافق مع أنماط Switch و Xbox أثناء استخدام واجهة المستخدم الخاصة بالتطبيق.</string>
<string name="invert_confirm_back_controller_buttons_description">تبديل طريقة التعامل مع زري «تأكيد» و«رجوع» في نظام Android لتتوافق مع أنماط أجهزة Switch وXbox أثناء استخدام واجهة المستخدم الخاصة بالتطبيق.</string>
<string name="input_overlay_options">طبقة الإدخال</string>
<string name="input_overlay_options_description">ضبط ذراع التحكم على الشاشة</string>
@@ -268,7 +268,7 @@
<string name="product">المنتج</string>
<string name="android_version">إصدار Android</string>
<string name="android_security_patch">تصحيح الأمان</string>
<string name="build_id">معرف البناء</string>
<string name="build_id">معرف الإصدار</string>
<string name="general_information">معلومات عامة</string>
<string name="hardware">الأجهزة</string>
<string name="supported_abis">واجهات برمجة التطبيقات المدعومة</string>
@@ -287,7 +287,7 @@
<string name="install_amiibo_keys">تثبيت مفاتيح أميبو</string>
<string name="install_amiibo_keys_description">مطلوب لاستخدام أميبو في اللعبة</string>
<string name="gpu_driver_fetcher">أداة جلب برامج تشغيل وحدة المعالجة الرسومية</string>
<string name="gpu_driver_manager">مدير برامج تشغيل وحدة معالجة الرسومات</string>
<string name="gpu_driver_manager">إدارة برامج تشغيل وحدة معالجة الرسومات</string>
<string name="install_gpu_driver_description">تثبيت برامج تشغيل بديلة لأداء أو دقة أفضل</string>
<string name="advanced_settings">الإعدادات المتقدمة</string>
<string name="settings_description">ضبط إعدادات المحاكي</string>
@@ -403,7 +403,7 @@
<string name="contributors">المساهمين</string>
<string name="contributors_description">الأشخاص الذين جعلوا تطبيق Eden لنظام Android ممكنًا</string>
<string name="licenses_description">المشاريع التي تجعل Eden لأجهزة Android ممكنة</string>
<string name="build">البناء</string>
<string name="build">الإصدار</string>
<string name="user_data">بيانات المستخدم</string>
<string name="user_data_description">استيراد/تصدير جميع بيانات التطبيق.\nعند استيراد بيانات المستخدم، سيتم حذف جميع بيانات المستخدم الموجودة!\nقد يُسبب استيراد البيانات من Citron بعض المشاكل. يُنصح باستيراد جميع البيانات المطلوبة يدويًا.</string>
<string name="exporting_user_data">جارٍ تصدير بيانات المستخدم...</string>
@@ -479,8 +479,6 @@
<string name="vram_usage_mode_description">تحكم في مدى قوة تخصيص المحاكي لذاكرة وحدة معالجة الرسومات وتحريرها.</string>
<string name="accelerate_astc">طريقة فك ضغط ASTC</string>
<string name="accelerate_astc_description">حدد كيفية فك ضغط نسيج ASTC للعرض: CPU (بطيء، آمن)، GPU (سريع، موصى به)، أو CPU Async (بدون توقف، قد يسبب مشاكل)</string>
<string name="astc_recompression">طريقة إعادة ضغط ASTC</string>
<string name="astc_recompression_description">حدد كيفية إعادة ضغط نسيج ASTC لتحسين التوافق والأداء. تمكين هذا الخيار يوفر VRAM ولكن قد يقلل من جودة النسيج.</string>
<string name="sync_memory_operations">مزامنة عمليات الذاكرة</string>
<string name="sync_memory_operations_description">يضمن اتساق البيانات بين عمليات الحوسبة والذاكرة. هذا الخيار قد يحل المشكلات في بعض الألعاب، ولكن قد يقلل الأداء في بعض الحالات. يبدو أن الألعاب التي تستخدم Unreal Engine 4 هي الأكثر تأثرًا.</string>
@@ -488,6 +486,10 @@
<string name="use_disk_shader_cache_description">يقلل من التأتأة عن طريق تخزين وتحميل التظليلات التي تم إنشاؤها محليًا.</string>
<string name="renderer_force_max_clock">إجبار السرعة القصوى (لأجهزة Adreno فقط)</string>
<string name="renderer_force_max_clock_description">يجبر وحدة معالجة الرسومات على العمل بأقصى سرعة ممكنة (سيظل يتم تطبيق القيود الحرارية).</string>
<string name="renderer_asynchronous_gpu_emulation">محاكاة غير متزامنة لوحدة معالجة الرسومات</string>
<string name="renderer_asynchronous_gpu_emulation_description">يُشغّل هذا الخيار محاكاة وحدة معالجة الرسومات بشكل غير متزامن لتقليل توقف وحدة المعالجة المركزية وتحسين الإنتاجية. عطّل هذا الخيار فقط في حال واجهت مشاكل متعلقة بالتوقيت.</string>
<string name="renderer_async_presentation">عرض غير متزامن</string>
<string name="renderer_async_presentation_description">يحسّن الأداء بشكل طفيف عن طريق نقل عملية العرض إلى خيط معالجة منفصل لوحدة المعالجة المركزية.</string>
<string name="renderer_reactive_flushing">استخدم التنظيف التفاعلي</string>
<string name="renderer_reactive_flushing_description">يحسن دقة العرض في بعض الألعاب على حساب الأداء.</string>
<string name="enable_buffer_history">تمكين سجل التخزين المؤقت</string>
@@ -525,10 +527,6 @@
<string name="disabled">معطل</string>
<string name="vertex_input_dynamic_state">حالة ديناميكية لإدخال الرأس</string>
<string name="vertex_input_dynamic_state_description">يتيح ميزة الحالة الديناميكية لإدخال الرأس لتحسين الجودة والأداء.</string>
<string name="provoking_vertex">الرأس المثير</string>
<string name="provoking_vertex_description">يحسن الإضاءة ومعالجة الرؤوس في بعض الألعاب. مدعوم فقط على وحدات معالجة الرسومات Vulkan 1.0+.</string>
<string name="descriptor_indexing">فهرسة الوصف</string>
<string name="descriptor_indexing_description">يحسن معالجة النسيج والمخزن المؤقت، بالإضافة إلى طبقة الترجمة Maxwell. مدعوم من بعض وحدات معالجة الرسومات Vulkan 1.1 وجميع وحدات معالجة الرسومات Vulkan 1.2+.</string>
<string name="sample_shading_fraction">تظليل العينة</string>
<string name="sample_shading_fraction_description">يسمح هذا الخيار بتنفيذ مُظلل الأجزاء لكل عينة في جزء متعدد العينات بدلاً من تنفيذه مرة واحدة لكل جزء. يُحسّن هذا من جودة الرسومات على حساب بعض الأداء.</string>
@@ -633,10 +631,10 @@
<string name="gamecube_controller">ذراع تحكم GameCube</string>
<string name="invert_axis">عكس المحور</string>
<string name="invert_button">عكس الزر</string>
<string name="toggle_button">زر التبديل</string>
<string name="toggle_button">زر تشغيل/إيقاف</string>
<string name="turbo_button">زر التوربو</string>
<string name="set_threshold">تعيين الحد الفاصل</string>
<string name="toggle_axis">تبديل المحور</string>
<string name="toggle_axis">تشغيل/إيقاف المحور</string>
<string name="connected">متصل</string>
<string name="use_system_vibrator">استخدم هزاز النظام</string>
<string name="input_overlay">طبقة الإدخال</string>
@@ -662,7 +660,7 @@
<!-- Miscellaneous -->
<string name="slider_default">افتراضي</string>
<string name="default_string">الافتراضي</string>
<string name="default_string">افتراضي</string>
<string name="loading">جارٍ التحميل…</string>
<string name="shutting_down">جارٍ إيقاف التشغيل...</string>
<string name="reset_setting_confirmation">هل تريد إعادة تعيين هذا الإعداد إلى قيمته الافتراضية؟</string>
@@ -688,8 +686,8 @@
<string name="import_success">تم الاستيراد بنجاح</string>
<string name="export_success">تم التصدير بنجاح</string>
<string name="start">بدء</string>
<string name="global">المتغيرات العامة</string>
<string name="custom">مخصص</string>
<string name="global">الإعدادات العامة</string>
<string name="custom">الإعدادات المخصصة للعبة</string>
<string name="import_complete">اكتمل الاستيراد</string>
<string name="use_global_setting">استخدام الإعداد العام</string>
<string name="operation_completed_successfully">اكتملت العملية بنجاح</string>
@@ -768,7 +766,7 @@
<string name="info_description">معرف العنوان، المطور، الإصدار</string>
<string name="per_game_settings">الإعدادات الخاصة للعبة</string>
<string name="per_game_settings_description">تعديل الإعدادات الخاصة بهذه اللعبة</string>
<string name="launch_options">تشغيل الإعدادات</string>
<string name="launch_options">إعدادات التشغيل</string>
<string name="path">المسار</string>
<string name="program_id">معرف العنوان</string>
<string name="developer">المطور</string>
@@ -880,13 +878,13 @@
<!-- Emulation Menu -->
<string name="emulation_exit">خروج من المحاكاة</string>
<string name="emulation_done">إنهاء</string>
<string name="emulation_toggle_controls">تبديل أزرار التحكم</string>
<string name="emulation_toggle_controls">تشغيل/إيقاف أزرار التحكم</string>
<string name="emulation_rel_stick_center">مركز العصا النسبي</string>
<string name="emulation_dpad_slide">انزلاق الأسهم</string>
<string name="emulation_haptics">الاهتزازات الديناميكية</string>
<string name="emulation_show_overlay">عرض ذراع التحكم</string>
<string name="emulation_hide_overlay">إخفاء ذراع التحكم</string>
<string name="emulation_toggle_all">تبديل الكل</string>
<string name="emulation_toggle_all">تشغيل/إيقاف الكل</string>
<string name="emulation_control_adjust">ضبط الطبقة</string>
<string name="emulation_control_scale">الحجم</string>
<string name="emulation_control_opacity">الشفافية</string>
@@ -997,9 +995,6 @@
<string name="dma_accuracy_unsafe">غير آمن</string>
<string name="dma_accuracy_safe">آمن</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">غير مضغوط</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">محافظ</string>
<string name="vram_usage_aggressive">عدواني</string>
@@ -1131,7 +1126,7 @@
<string name="enable_overlay_description">تمكين التطبيق الصغير المدمج في Horizon. اضغط مع الاستمرار على زر الشاشة الرئيسية لمدة 1 ثانية لإظهاره.</string>
<!-- Profile Management -->
<string name="profile_manager">مدير الملف الشخصي</string>
<string name="profile_manager">إدارة ملف التعريف</string>
<string name="profile_manager_description">إدارة ملفات تعريف المستخدمين</string>
<string name="profile_add_user">إضافة مستخدم</string>
<string name="profile_new_user">مستخدم جديد</string>
@@ -343,8 +343,6 @@
<string name="vram_usage_mode_description">کۆنتڕۆڵی بەکارهێنانی VRAM</string>
<string name="accelerate_astc">ڕێگای دیکۆدکردنی ASTC</string>
<string name="accelerate_astc_description">هەڵبژێرە چۆن تێکستوورە پەستووکراوەکانی ASTC دەکرێنەوە بۆ ڕێندرکردن: CPU (هێواش، سەلامەت)، GPU (خێرا، پێشنیارکراو)، یان CPU Async (بێ ستەتەر، لەوانەیە کێشە دروست بکات)</string>
<string name="astc_recompression">ڕێگای پێکهێنانەوەی ASTC</string>
<string name="astc_recompression_description">هەڵبژێرە چۆن تێکستوورەکانی ASTC پەستوو دەکرێنەوە بۆ باشترکردنی گونجاندن و کارایی. چالاککردنی ئەم هەڵبژاردە VRAM هەڵدەگرێت بەڵام لەوانەیە کەمکردنەوەی کوالێتی تێکستوور بکات.</string>
<string name="sync_memory_operations">هاوبەشیی کردارەکانی بیرگە</string>
<string name="sync_memory_operations_description">دڵنیایی داتا لە نێوان کردارەکانی کۆمپیوتەر و بیرگە. ئەم هەڵبژاردە کێشەکان لە هەندێک یاری چارەسەر دەکات، بەڵام لە هەندێک حاڵەت کارایی کەم دەکاتەوە. وا دیارە یارییەکانی Unreal Engine 4 زۆرترین کاریگەریان هەیە.</string>
@@ -360,10 +358,6 @@
<string name="renderer_asynchronous_shaders_description">کۆمپایلکردنی شادەرەکان بەشێوەی ناڕێک. ئەمە ڕەنگە کەمکردنەوەی ستەتەر بکات بەڵام لەوانەیە هەڵەش دروست بکات.</string>
<string name="dyna_state">الحالة الديناميكية الممتدة</string>
<string name="disabled">ناچالاک</string>
<string name="provoking_vertex">الرأس المثير</string>
<string name="provoking_vertex_description">يحسن الإضاءة ومعالجة الرؤوس في بعض الألعاب. مدعوم فقط على وحدات معالجة الرسومات التي تدعم فولكان 1.0+.</string>
<string name="descriptor_indexing">فهرسة الواصفات</string>
<string name="descriptor_indexing_description">يحسن معالجة القوام والمخازن المؤقتة، بالإضافة إلى طبقة ترجمة ماكسويل. مدعوم من قبل بعض وحدات معالجة الرسومات التي تدعم فولكان 1.1 وجميع وحدات معالجة الرسومات التي تدعم فولكان 1.2+.</string>
<string name="display">پیشاندان</string>
<string name="renderer_screen_layout">ڕێکخستنی شاشە</string>
@@ -577,9 +571,6 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">بنەڕەتی</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">پێکهێنەنەوە</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">پارێزەر</string>
<string name="vram_usage_aggressive">توند</string>
@@ -458,8 +458,6 @@
<string name="vram_usage_mode_description">Určuje, jak moc agresivně emulátor přiděluje a uvolňuje grafickou paměť.</string>
<string name="accelerate_astc">Metoda dekódování ASTC</string>
<string name="accelerate_astc_description">Vyberte způsob jak se dekódují ASTC textury: CPU (pomalé, bezpečné), GPU (rychlé, doporučené) nebo CPU Async (asynchronní, žádné zasekávání, ale může způsobit problémy)</string>
<string name="astc_recompression">Metoda rekomprese ASTC</string>
<string name="astc_recompression_description">Vyberte způsob rekomprese textur ASTC pro zlepšení kompatibility a výkonu. Zapnutí této volby ušetří VRAM, ale může snížit kvalitu textur.</string>
<string name="sync_memory_operations">Synchronizace paměťových operací</string>
<string name="sync_memory_operations_description">Zajišťuje konzistenci dat mezi výpočetními a paměťovými operacemi. Tato volba by měla opravit problémy v některých hrách, ale může v některých případech snížit výkon. Největší změny se týkají her založených na Unreal Engine 4.</string>
@@ -486,10 +484,6 @@
<string name="disabled">Vypnuto</string>
<string name="vertex_input_dynamic_state">Dynamický stav vstupu vrcholů (Vertex Input)</string>
<string name="vertex_input_dynamic_state_description">Aktivuje funkci dynamického stavu vstupu vrcholů (Vertex Input Dynamic State) pro lepší kvalitu a výkon.</string>
<string name="provoking_vertex">Určující vrchol</string>
<string name="provoking_vertex_description">Zlepšuje osvětlení a zpracování vrcholů v některých hrách. Podporováno pouze na GPU s API Vulkan 1.0+.</string>
<string name="descriptor_indexing">Indexování deskriptorů</string>
<string name="descriptor_indexing_description">Zlepšuje zpracování textur a bufferů, stejně jako překladovou vrstvu architektury Maxwell. Podporováno některými GPU s API Vulkan 1.1 a všemi GPU s API Vulkan 1.2+.</string>
<string name="display">Zobrazení</string>
<string name="renderer_screen_layout">Orientace</string>
@@ -727,9 +721,6 @@
<string name="dma_accuracy_unsafe">Nebezpečné</string>
<string name="dma_accuracy_safe">Bezpečné</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">Nekomprimované</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">Konzervativní</string>
<string name="vram_usage_aggressive">Agresivní</string>
@@ -458,8 +458,6 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
<string name="vram_usage_mode_description">Steuerung der GPU-Speicherzuweisung</string>
<string name="accelerate_astc">ASTC-Decodierung</string>
<string name="accelerate_astc_description">Wählen Sie aus, wie ASTC-komprimierte Texturen für das Rendering decodiert werden: CPU (langsam, sicher), GPU (schnell, empfohlen) oder CPU Async (kein Ruckeln, kann Probleme verursachen)</string>
<string name="astc_recompression">ASTC-Neukompression</string>
<string name="astc_recompression_description">Wählen Sie, wie ASTC-Texturen neu komprimiert werden, um die Kompatibilität und Leistung zu verbessern. Diese Option spart VRAM, kann aber die Texturqualität verringern.</string>
<string name="sync_memory_operations">Speicheroperationen synchronisieren</string>
<string name="sync_memory_operations_description">Stellt die Datenkonsistenz zwischen Compute- und Speicheroperationen sicher. Diese Option sollte Probleme in einigen Spielen beheben, kann aber in einigen Fällen die Leistung verringern. Spiele mit Unreal Engine 4 scheinen am stärksten betroffen zu sein.</string>
@@ -484,10 +482,6 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
<string name="disabled">Deaktiviert</string>
<string name="vertex_input_dynamic_state">Vertex Input Dynamic State</string>
<string name="vertex_input_dynamic_state_description">Aktiviert die Funktion \"Vertex Input Dynamic State\" für bessere Qualität und Leistung.</string>
<string name="provoking_vertex">Provokanter Vertex</string>
<string name="provoking_vertex_description">Verbessert die Beleuchtung und die Vertex-Verarbeitung in einigen Spielen. Wird nur von GPUs mit Vulkan 1.0+ unterstützt.</string>
<string name="descriptor_indexing">Deskriptor-Indizierung</string>
<string name="descriptor_indexing_description">Verbessert die Textur- und Puffer-Verarbeitung sowie die Maxwell-Übersetzungsschicht. Wird von einigen Vulkan 1.1-GPUs und allen Vulkan 1.2+-GPUs unterstützt.</string>
<string name="sample_shading_fraction">Sample Shading</string>
<string name="sample_shading_fraction_description">Ermöglicht es dem Fragment-Shader, in einem Multisample-Fragment pro Sample anstatt einmal pro Fragment ausgeführt zu werden. Verbessert die Grafikqualität auf Kosten der Leistung.</string>
@@ -935,9 +929,6 @@ Wirklich fortfahren?</string>
<string name="dma_accuracy_unsafe">Unsicher</string>
<string name="dma_accuracy_safe">Sicher</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">Unkomprimiert</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">Konservativ</string>
<string name="vram_usage_aggressive">Aggressiv</string>
@@ -272,7 +272,7 @@
<string name="general_information">Información general</string>
<string name="hardware">Hardware</string>
<string name="supported_abis">ABIs soportadas</string>
<string name="cpu_info">Información de la CPU</string>
<string name="cpu_info">Información del procesador</string>
<string name="gpu_information">Información de la GPU</string>
<string name="vulkan_driver_version">Versión del controlador de Vulkan</string>
<string name="error_getting_emulator_info">Error al obtener la información del emulador</string>
@@ -351,7 +351,7 @@
<item quantity="other">%d archivos de guardado importados con éxito.</item>
</plurals>
<string name="no_save_data_found">No se encontraron datos de guardado</string>
<string name="verify_installed_content">Verificar contenido instalado</string>
<string name="verify_installed_content">Verificar los contenidos instalados</string>
<string name="verify_installed_content_description">Comprueba todo el contenido instalado por si hubiese alguno corrupto</string>
<string name="keys_missing">Faltan las claves de encriptación</string>
@@ -416,8 +416,8 @@
<string name="turbo_speed_limit_description">Cuando el modo turbo esté activado, la emulación se ejecutará a esta velocidad.</string>
<string name="slow_speed_limit">Velocidad lenta</string>
<string name="slow_speed_limit_description">Cuando el modo lento esté activado, la emulación se ejecutará a esta velocidad.</string>
<string name="cpu_backend">Motor de la CPU</string>
<string name="cpu_accuracy">Precisión de la CPU</string>
<string name="cpu_backend">Motor del procesador</string>
<string name="cpu_accuracy">Precisión del procesador</string>
<string name="value_with_units">%1$s%2$s</string>
<!-- System settings strings -->
@@ -433,7 +433,7 @@
<string name="set_custom_rtc">Configurar RTC personalizado</string>
<!-- CPU -->
<string name="fast_cpu_time">Overclock de la CPU</string>
<string name="fast_cpu_time">Overclock del procesador</string>
<string name="fast_cpu_time_description">Fuerza a la CPU emulada a ejecutarser a una velocidad de reloj más alta, lo cual reduce ciertos limitadores de fotogramas por segundo. Usa Boost (1700 MHz) para ejecutar a la velocidad de reloj nativa más alta de la Switch, o Fast (2000 MHz) para ejecutar a una velocidad doble de reloj.</string>
<string name="custom_cpu_ticks">Ticks de CPU personalizados</string>
<string name="custom_cpu_ticks_description">Establezca un valor personalizado de los ciclos de la CPU. Los valores más altos pueden aumentar el rendimiento, pero también pueden hacer que el juego se congele. Se recomienda un rango de 7721000.</string>
@@ -473,8 +473,6 @@
<string name="vram_usage_mode_description">Controla con qué agresividad el emulador asigna y libera la memoria de la GPU.</string>
<string name="accelerate_astc">Método de decodificación ASTC</string>
<string name="accelerate_astc_description">Elija cómo se descodifican las texturas comprimidas ASTC para el renderizado: CPU (lento, seguro), GPU (rápido, recomendado) o CPU Async (sin tirones, puede causar problemas)</string>
<string name="astc_recompression">Método de recompresión ASTC</string>
<string name="astc_recompression_description">Elija cómo se recomprimen las texturas ASTC para mejorar la compatibilidad y el rendimiento. Habilitar esta opción ahorra VRAM pero puede reducir la calidad de las texturas.</string>
<string name="sync_memory_operations">Sincronizar operaciones de memoria</string>
<string name="sync_memory_operations_description">Garantiza la consistencia de los datos entre las operaciones de computación y memoria. Esta opción debería solucionar problemas en algunos juegos, pero también puede reducir el rendimiento en algunos casos. Los juegos de Unreal Engine 4 a menudo ven los cambios más significativos de los mismos.</string>
@@ -482,6 +480,10 @@
<string name="use_disk_shader_cache_description">Reduce los tirones almacenando y cargando los sombreadores generados.</string>
<string name="renderer_force_max_clock">Forzar velocidad al máximo (solo Adreno)</string>
<string name="renderer_force_max_clock_description">Fuerza a la GPU a ejecutarse a la velocidad máxima de reloj posible (se seguirán aplicando restricciones térmicas).</string>
<string name="renderer_asynchronous_gpu_emulation">Emulación de GPU asíncrona</string>
<string name="renderer_asynchronous_gpu_emulation_description">Ejecuta la emulación de la GPU de forma asíncrona para reducir los bloqueos de la CPU y mejorar el rendimiento. Desactiva esta opción solo si experimentas problemas de sincronización.</string>
<string name="renderer_async_presentation">Presentación asíncrona</string>
<string name="renderer_async_presentation_description">Mejora ligeramente el rendimiento al mover la presentación a un hilo independiente de la CPU.</string>
<string name="renderer_reactive_flushing">Usar limpieza reactiva</string>
<string name="renderer_reactive_flushing_description">Mejora la precisión de renderizado en algunos juegos, pero reduce el rendimiento.</string>
<string name="enable_buffer_history">Activar el historial del búfer</string>
@@ -519,10 +521,6 @@
<string name="disabled">Desactivado</string>
<string name="vertex_input_dynamic_state">Estado dinámico de entrada de vértices</string>
<string name="vertex_input_dynamic_state_description">Activa la función de estado dinámico de entrada de vértices para una mejor calidad y rendimiento.</string>
<string name="provoking_vertex">Vértice provocante</string>
<string name="provoking_vertex_description">Mejora la iluminación y el manejo de vértices en ciertos juegos. Solo es compatible con las GPU Vulkan 1.0+.</string>
<string name="descriptor_indexing">Indexación del descriptor</string>
<string name="descriptor_indexing_description">Mejora la textura y el manejo del búfer, así como la capa de traducción Maxwell. Compatible con algunas GPU Vulkan 1.1 y todas las GPU Vulkan 1.2+.</string>
<string name="sample_shading_fraction">Muestreo de sombreado</string>
<string name="sample_shading_fraction_description">Permite que el sombreador de fragmentos se ejecute por muestra en un fragmento multimuestreado, en lugar de una sola vez por fragmento. Mejora la calidad de los gráficos a coste de algo de rendimiento.</string>
@@ -538,7 +536,7 @@
<string name="warning_resolution">Escalar la resolución a 2x o más puede causar problemas y ralentizar significativamente su dispositivo.</string>
<!-- Debug settings strings -->
<string name="cpu">CPU</string>
<string name="cpu">Procesador</string>
<string name="use_auto_stub">Usar Auto Stub</string>
<string name="use_auto_stub_description">Rellena automáticamente servicios y funciones ausentes. Puede mejorar la compatibilidad pero puede causar cierres inesperados.</string>
@@ -991,9 +989,6 @@
<string name="dma_accuracy_unsafe">Inseguro</string>
<string name="dma_accuracy_safe">Seguro</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">Sin compresión</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">Conservador</string>
<string name="vram_usage_aggressive">Agresivo</string>
@@ -71,10 +71,6 @@
<string name="uninstall_firmware_description">حذف فرمور آن را از دستگاه پاک می‌کند و ممکن است بر سازگاری بازی‌ها تأثیر بگذارد</string>
<string name="firmware_uninstalling">در حال حذف فرمور</string>
<string name="firmware_uninstalled_success">فرمور با موفقیت حذف شد</string>
<string name="provoking_vertex">رأس تحریک‌کننده</string>
<string name="provoking_vertex_description">نورپردازی و مدیریت رأس را در برخی بازی‌ها بهبود می‌بخشد. فقط در کارت‌های گرافیک با پشتیبانی از ولکان 1.0+ قابل استفاده است</string>
<string name="descriptor_indexing">نمایه‌سازی توصیفگر</string>
<string name="descriptor_indexing_description">مدیریت بافت‌ها و بافرها و همچنین لایه ترجمه ماکسول را بهبود می‌بخشد. توسط برخی کارت‌های گرافیک ولکان 1.1 و تمام کارت‌های گرافیک ولکان 1.2+ پشتیبانی می‌شود</string>
<string name="fast_gpu_time">فاکتور اورکلاک GPU</string>
<string name="fast_gpu_time_description">برای حداکثر عملکرد از 128 و برای حداکثر وفاداری گرافیکی از 512 استفاده کنید.</string>
<string name="fast_gpu_medium">متوسط (256)</string>
@@ -114,12 +110,6 @@
<string name="accelerate_astc_gpu">GPU</string>
<string name="accelerate_astc_async">CPU ناهمگام</string>
<!-- ASTC Recompression Method -->
<string name="astc_recompression">روش فشرده‌سازی مجدد ASTC</string>
<string name="astc_recompression_description">انتخاب کنید که بافت‌های ASTC چگونه فشرده‌سازی مجدد شوند تا سازگاری و عملکرد بهبود یابد. فعال کردن این گزینه VRAM را ذخیره می‌کند اما ممکن است کیفیت بافت را کاهش دهد.</string>
<string name="astc_recompression_uncompressed">فشرده‌نشده</string>
<string name="astc_recompression_bc1">BC1 (کیفیت پایین)</string>
<string name="astc_recompression_bc3">BC3 (کیفیت متوسط)</string>
<!-- VRAM Usage Mode -->
<string name="vram_usage_mode">حالت استفاده از VRAM</string>
@@ -466,8 +466,6 @@
<string name="vram_usage_mode_description">Gestion de la mémoire GPU</string>
<string name="accelerate_astc">Méthode ASTC</string>
<string name="accelerate_astc_description">Choisissez comment les textures compressées ASTC sont décodées pour le rendu : CPU (lent, sûr), GPU (rapide, recommandé) ou CPU Async (pas de saccades, peut causer des problèmes)</string>
<string name="astc_recompression">Recompression ASTC</string>
<string name="astc_recompression_description">Choisissez comment les textures ASTC sont recompressées pour améliorer la compatibilité et les performances. Activer cette option économise la VRAM mais peut réduire la qualité des textures.</string>
<string name="sync_memory_operations">Synchroniser les opérations mémoire</string>
<string name="sync_memory_operations_description">Garantit la cohérence des données entre les opérations de calcul et de mémoire. Cette option devrait résoudre les problèmes dans certains jeux, mais peut réduire les performances dans certains cas. Les jeux utilisant Unreal Engine 4 semblent être les plus affectés.</string>
@@ -485,10 +483,6 @@
<string name="disabled">Désactivé</string>
<string name="vertex_input_dynamic_state">État dynamique d\'entrée de sommet</string>
<string name="vertex_input_dynamic_state_description">Active la fonctionnalité d\'état dynamique des entrées de sommets pour une meilleure qualité et de meilleures performances.</string>
<string name="provoking_vertex">Provoque des Vertex</string>
<string name="provoking_vertex_description">Améliore l`éclairage et la gestion des vertex dans certains jeux. Pris en charge uniquement par les GPU Vulkan 1.0+.</string>
<string name="descriptor_indexing">Indexation des descripteurs</string>
<string name="descriptor_indexing_description">Améliore la gestion des textures et des tampons, ainsi que la couche de traduction Maxwell. Pris en charge par certains GPU Vulkan 1.1 et tous les GPU Vulkan 1.2+.</string>
<string name="display">Affichage</string>
<string name="renderer_screen_layout">Orientation</string>
@@ -864,9 +858,6 @@
<string name="dma_accuracy_unsafe">Dangereux</string>
<string name="dma_accuracy_safe">Sûr</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">Non compressé</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">Conservateur</string>
<string name="vram_usage_aggressive">Agressif</string>
@@ -373,8 +373,6 @@
<string name="vram_usage_mode_description">שליטה בקצב הקצאת ושחרור זיכרון GPU</string>
<string name="accelerate_astc">שיטת פענוח ASTC</string>
<string name="accelerate_astc_description">בחר כיצד לפרק את הטקסטורות הדחוסות ב-ASTC עבור רינדור: CPU (איטי, בטוח), GPU (מהיר, מומלץ) או CPU Async (ללא קפיצות, עלול לגרום לבעיות)</string>
<string name="astc_recompression">שיטת דחיסת ASTC</string>
<string name="astc_recompression_description">בחר כיצד דחיסה מחדש של טקסטורות ASTC משפרת תאימות וביצועים. הפעלת אפשרות זו חוסכת VRAM אך עלולה להוריד את איכות הטקסטורה.</string>
<string name="sync_memory_operations">סנכרון פעולות זיכרון</string>
<string name="sync_memory_operations_description">מבטיח עקביות נתונים בין פעולות חישוב וזיכרון. אפשרות זו אמורה לתקן בעיות במשחקים מסוימים, אך עלולה להפחית ביצועים במקרים מסוימים. נראה שהמשחקים עם Unreal Engine 4 הם המושפעים ביותר.</string>
@@ -390,10 +388,6 @@
<string name="renderer_asynchronous_shaders_description">מקמפל שיידרים באופן אסינכרוני. זה עשוי להפחית קפיצות אך גם עלול לגרום לתקלות גרפיות.</string>
<string name="dyna_state">מצב דינמי מורחב</string>
<string name="disabled">מושבת</string>
<string name="provoking_vertex">קודקוד מעורר</string>
<string name="provoking_vertex_description">משפר תאורה וטיפול בקודקודים במשחקים מסוימים. נתמך רק בכרטיסי מסך עם Vulkan 1.0+.</string>
<string name="descriptor_indexing">אינדוקס תיאורים</string>
<string name="descriptor_indexing_description">משפר טיפול במרקמים ומאגרים, כמו גם בשכבת התרגום של Maxwell. נתמך בחלק מכרטיסי ה-Vulkan 1.1 ובכל כרטיסי ה-Vulkan 1.2+.</string>
<string name="display">תצוגה</string>
<string name="renderer_screen_layout">כיוון</string>
@@ -622,9 +616,6 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">ברירת מחדל</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">לא דחוס</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">שמרני</string>
<string name="vram_usage_aggressive">אגרסיבי</string>
@@ -362,8 +362,6 @@
<string name="vram_usage_mode_description">GPU memória kezelésének módja</string>
<string name="accelerate_astc">ASTC dekódolási módszer</string>
<string name="accelerate_astc_description">Válassza ki, hogyan legyenek dekódolva az ASTC tömörített textúrák a rendereléshez: CPU (lassú, biztonságos), GPU (gyors, ajánlott) vagy CPU Async (nincs megakadás, de problémákat okozhat)</string>
<string name="astc_recompression">ASTC újratömörítési módszer</string>
<string name="astc_recompression_description">Válassza ki, hogyan történik az ASTC textúrák újratömörítése a kompatibilitás és a teljesítmény javításáért. Ez az opció VRAM-ot takarít meg, de csökkentheti a textúra minőségét.</string>
<string name="sync_memory_operations">Memória-műveletek szinkronizálása</string>
<string name="sync_memory_operations_description">Biztosítja az adatok konzisztenciáját a számítási és memória-műveletek között. Ez az opciónak javítania kell néhány játékban előforduló problémát, de bizonyos esetekben csökkentheti a teljesítményt. Az Unreal Engine 4-et használó játékok látszanak a legérintettebbek.</string>
@@ -379,10 +377,6 @@
<string name="renderer_asynchronous_shaders_description">A shaderek aszinkron fordítása. Csökkentheti a belassulásokat, de hibákat is okozhat.</string>
<string name="dyna_state">Kiterjesztett Dinamikus Állapot</string>
<string name="disabled">Letiltva</string>
<string name="provoking_vertex">Provokáló csúcs</string>
<string name="provoking_vertex_description">Javítja a világítást és a csúcskezelést bizonyos játékokban. Csak Vulkan 1.0+ GPU-kon támogatott.</string>
<string name="descriptor_indexing">Deskriptor Indexelés</string>
<string name="descriptor_indexing_description">Javítja a textúrák és pufferek kezelését, valamint a Maxwell fordítási réteget. Néhány Vulkan 1.1 GPU és minden Vulkan 1.2+ GPU támogatja.</string>
<string name="display">Kijelző</string>
<string name="renderer_screen_layout">Orientáció</string>
@@ -711,9 +705,6 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Alapértelmezett</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">Tömörítetlen</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">Konzervatív</string>
<string name="vram_usage_aggressive">Aggresszív</string>
@@ -394,8 +394,6 @@
<string name="vram_usage_mode_description">Kontrol seberapa agresif emulator mengalokasikan dan membebaskan memori GPU.</string>
<string name="accelerate_astc">Metode Dekoding ASTC</string>
<string name="accelerate_astc_description">Pilih cara tekstur terkompresi ASTC didekode untuk rendering: CPU (lambat, aman), GPU (cepat, direkomendasikan), atau CPU Async (tanpa lag, mungkin menyebabkan masalah)</string>
<string name="astc_recompression">Metode Rekompresi ASTC</string>
<string name="astc_recompression_description">Pilih cara tekstur ASTC dikompresi ulang untuk meningkatkan kompatibilitas dan performa. Mengaktifkan opsi ini menghemat VRAM tetapi dapat menurunkan kualitas tekstur.</string>
<string name="sync_memory_operations">Sinkronisasi Operasi Memori</string>
<string name="sync_memory_operations_description">Memastikan konsistensi data antara operasi komputasi dan memori. Opsi ini seharusnya memperbaiki masalah di beberapa game, tetapi mungkin mengurangi performa dalam beberapa kasus. Game dengan Unreal Engine 4 tampaknya yang paling terpengaruh.</string>
@@ -411,10 +409,6 @@
<string name="renderer_asynchronous_shaders_description">Kompilasi shader secara asinkron. Ini dapat mengurangi lag tetapi juga dapat menyebabkan glitch.</string>
<string name="dyna_state">Status Dinamis Ekstensi</string>
<string name="disabled">Dinonaktifkan</string>
<string name="provoking_vertex">Vertex Provokasi</string>
<string name="provoking_vertex_description">Meningkatkan pencahayaan dan penanganan vertex di beberapa game. Hanya didukung di GPU Vulkan 1.0+.</string>
<string name="descriptor_indexing">Pengindeks Deskriptor</string>
<string name="descriptor_indexing_description">Meningkatkan penanganan tekstur dan buffer, serta lapisan terjemahan Maxwell. Didukung oleh beberapa GPU Vulkan 1.1 dan semua GPU Vulkan 1.2+.</string>
<string name="display">Tampilan</string>
<string name="renderer_screen_layout">Orientasi</string>
@@ -757,9 +751,6 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Bawaan</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">Tidak Dikompresi</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">Konservatif</string>
<string name="vram_usage_aggressive">Agresif</string>
@@ -401,8 +401,6 @@
<string name="vram_usage_mode_description">Controlla l`allocazione della memoria GPU</string>
<string name="accelerate_astc">Metodo decodifica ASTC</string>
<string name="accelerate_astc_description">Scegli come decodificare le texture compresse ASTC per il rendering: CPU (lento, sicuro), GPU (veloce, consigliato) o CPU Async (senza stuttering, può causare problemi)</string>
<string name="astc_recompression">Metodo ricompressione ASTC</string>
<string name="astc_recompression_description">Scegli come ricomprimere le texture ASTC per migliorare compatibilità e prestazioni. Abilitare questa opzione salva VRAM ma può ridurre la qualità delle texture.</string>
<string name="sync_memory_operations">Sincronizza operazioni di memoria</string>
<string name="sync_memory_operations_description">Garantisce la coerenza dei dati tra le operazioni di calcolo e memoria. Questa opzione dovrebbe risolvere problemi in alcuni giochi, ma potrebbe ridurre le prestazioni in alcuni casi. I giochi con Unreal Engine 4 sembrano essere i più colpiti.</string>
@@ -418,10 +416,6 @@
<string name="renderer_asynchronous_shaders_description">Compila gli shader in modo asincrono. Può ridurre gli scatti, ma può anche causare glitch grafici.</string>
<string name="dyna_state">Stato dinamico esteso</string>
<string name="disabled">Disabilitato</string>
<string name="provoking_vertex">Vertice provocante</string>
<string name="provoking_vertex_description">Migliora illuminazione e gestione dei vertici in alcuni giochi. Supportato solo su GPU Vulkan 1.0+.</string>
<string name="descriptor_indexing">Indicizzazione descrittori</string>
<string name="descriptor_indexing_description">Migliora la gestione di texture e buffer, nonché il livello di traduzione Maxwell. Supportato da alcune GPU Vulkan 1.1 e tutte le GPU Vulkan 1.2+.</string>
<string name="display">Schermo</string>
<string name="renderer_screen_layout">Orientamento</string>
@@ -797,9 +791,6 @@
<string name="dma_accuracy_unsafe">Non sicura</string>
<string name="dma_accuracy_safe">Sicura</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">Non compresso</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">Conservativa</string>
<string name="vram_usage_aggressive">Aggressiva</string>
@@ -360,8 +360,6 @@
<string name="vram_usage_mode_description">VRAMの使用効率を設定</string>
<string name="accelerate_astc">ASTCデコード方法</string>
<string name="accelerate_astc_description">ASTC圧縮テクスチャのデコード方法を選択: CPU (低速、安全)、GPU (高速、推奨)、またはCPU非同期 (カクつきなし、問題が発生する可能性あり)</string>
<string name="astc_recompression">ASTC再圧縮方法</string>
<string name="astc_recompression_description">ASTCテクスチャの再圧縮方法を選択して互換性とパフォーマンスを向上させます。このオプションを有効にするとVRAMを節約できますが、テクスチャ品質が低下する可能性があります。</string>
<string name="sync_memory_operations">メモリ操作の同期</string>
<string name="sync_memory_operations_description">計算処理とメモリ操作間のデータ一貫性を保証します。 このオプションは一部のゲームの問題を修正しますが、場合によってはパフォーマンスが低下する可能性があります。 Unreal Engine 4のゲームが最も影響を受けるようです。</string>
@@ -377,10 +375,6 @@
<string name="renderer_asynchronous_shaders_description">シェーダーを非同期でコンパイルします。これによりカクつきが減る可能性がありますが、グラフィックの不具合が発生する場合もあります。</string>
<string name="dyna_state">拡張ダイナミックステート</string>
<string name="disabled">無効</string>
<string name="provoking_vertex">プロボーキング頂点</string>
<string name="provoking_vertex_description">特定のゲームで照明と頂点処理を改善します。Vulkan 1.0+ GPUでのみサポートされています。</string>
<string name="descriptor_indexing">ディスクリプタインデキシング</string>
<string name="descriptor_indexing_description">テクスチャとバッファの処理、およびMaxwell翻訳レイヤーを改善します。一部のVulkan 1.1 GPUとすべてのVulkan 1.2+ GPUでサポートされています。</string>
<string name="display">ディスプレイ</string>
<string name="renderer_screen_layout">画面の向き</string>
@@ -618,9 +612,6 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">デフォルト</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">非圧縮</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">保守的</string>
<string name="vram_usage_aggressive">積極的</string>
@@ -360,8 +360,6 @@
<string name="vram_usage_mode_description">GPU 메모리 할당/해제 방식 선택</string>
<string name="accelerate_astc">ASTC 디코딩 방법</string>
<string name="accelerate_astc_description">ASTC 압축 텍스처의 디코딩 방식을 선택하세요: CPU (느림, 안전), GPU (빠름, 권장), 또는 CPU 비동기 (끊김 없음, 문제 발생 가능)</string>
<string name="astc_recompression">ASTC 재압축 방법</string>
<string name="astc_recompression_description">ASTC 텍스처의 재압축 방식을 선택하여 호환성과 성능을 향상시킵니다. 이 옵션을 활성화하면 VRAM을 절약할 수 있지만 텍스처 품질이 저하될 수 있습니다.</string>
<string name="sync_memory_operations">메모리 작업 동기화</string>
<string name="sync_memory_operations_description">컴퓨팅 및 메모리 작업 간 데이터 일관성을 보장합니다. 이 옵션은 일부 게임의 문제를 해결할 수 있지만 경우에 따라 성능이 저하될 수 있습니다. Unreal Engine 4 게임이 가장 큰 영향을 받는 것으로 보입니다.</string>
@@ -377,10 +375,6 @@
<string name="renderer_asynchronous_shaders_description">셰이더를 비동기적으로 컴파일합니다. 이로 인해 끊김 현상이 줄어들 수 있지만 그래픽 오류가 발생할 수도 있습니다.</string>
<string name="dyna_state">확장 동적 상태</string>
<string name="disabled">비활성화됨</string>
<string name="provoking_vertex">프로보킹 버텍스</string>
<string name="provoking_vertex_description">일부 게임에서 조명과 버텍스 처리를 개선합니다. Vulkan 1.0+ GPU에서만 지원됩니다.</string>
<string name="descriptor_indexing">디스크립터 인덱싱</string>
<string name="descriptor_indexing_description">텍스처 및 버퍼 처리와 Maxwell 변환 레이어를 개선합니다. 일부 Vulkan 1.1 GPU 및 모든 Vulkan 1.2+ GPU에서 지원됩니다.</string>
<string name="display">디스플레이</string>
<string name="renderer_screen_layout">화면 방향</string>
@@ -670,9 +664,6 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">기본값</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">비압축</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">보수적</string>
<string name="vram_usage_aggressive">적극적</string>
@@ -343,8 +343,6 @@
<string name="vram_usage_mode_description">Kontroller minnetildeling for GPU</string>
<string name="accelerate_astc">ASTC-dekoding</string>
<string name="accelerate_astc_description">Velg hvordan ASTC-komprimerte teksturer skal dekodes for rendering: CPU (tregt, sikkert), GPU (raskt, anbefalt) eller CPU Async (ingen stuttering, kan forårsake problemer)</string>
<string name="astc_recompression">ASTC-komprimering</string>
<string name="astc_recompression_description">Velg hvordan ASTC-teksturer komprimeres på nytt for å forbedre kompatibilitet og ytelse. Å aktivere dette alternativet sparer VRAM, men kan redusere teksturkvaliteten.</string>
<string name="sync_memory_operations">Synkroniser minneoperasjoner</string>
<string name="sync_memory_operations_description">Sikrer datakonsistens mellom beregnings- og minneoperasjoner. Dette alternativet bør fikse problemer i noen spill, men kan redusere ytelsen i noen tilfeller. Spill med Unreal Engine 4 ser ut til å være de mest berørte.</string>
@@ -360,10 +358,6 @@
<string name="renderer_asynchronous_shaders_description">Kompilerer shadere asynkront. Dette kan redusere rykk, men kan også forårsake grafiske feil.</string>
<string name="dyna_state">Utvidet dynamisk tilstand</string>
<string name="disabled">Deaktivert</string>
<string name="provoking_vertex">Provoserende vertex</string>
<string name="provoking_vertex_description">Forbedrer belysning og vertexhåndtering i enkelte spill. Støttes kun på Vulkan 1.0+ GPU-er.</string>
<string name="descriptor_indexing">Beskrivelsesindeksering</string>
<string name="descriptor_indexing_description">Forbedrer tekstur- og bufferhåndtering, samt Maxwell-oversettelseslaget. Støttes av noen Vulkan 1.1 GPU-er og alle Vulkan 1.2+ GPU-er.</string>
<string name="display">Skjerm</string>
<string name="renderer_screen_layout">Orientering</string>
@@ -590,9 +584,6 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Standard</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">Ukomprimert</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">Konservativ</string>
<string name="vram_usage_aggressive">Aggressiv</string>
@@ -458,8 +458,6 @@
<string name="vram_usage_mode_description">Kontroluj alokację i zwalnianie pamięci GPU.</string>
<string name="accelerate_astc">Metoda dekodowania ASTC</string>
<string name="accelerate_astc_description">Wybierz sposób dekodowania tekstur skompresowanych w formacie ASTC do renderowania: CPU (wolne, bezpieczne), GPU (szybkie, zalecane) lub CPU Async (bez zacięć, może powodować problemy)</string>
<string name="astc_recompression">Metoda rekompresji ASTC</string>
<string name="astc_recompression_description">Wybierz sposób ponownej kompresji tekstur ASTC w celu poprawy zgodności i wydajności. Włączenie tej opcji oszczędza VRAM, ale może obniżyć jakość tekstur.</string>
<string name="sync_memory_operations">Synchronizuj operacje pamięci</string>
<string name="sync_memory_operations_description">Zapewnia spójność danych między operacjami obliczeniowymi i pamięciowymi. Ta opcja powinna naprawiać problemy w niektórych grach, ale może zmniejszyć wydajność w niektórych przypadkach. Gry z Unreal Engine 4 wydają się być najbardziej dotknięte.</string>
@@ -484,10 +482,6 @@
<string name="disabled">Wyłączone</string>
<string name="vertex_input_dynamic_state">Dynamiczny stan wejścia wierzchołków</string>
<string name="vertex_input_dynamic_state_description">Włącza funkcję dynamicznego stanu wejścia wierzchołków, poprawiając jakość i wydajność.</string>
<string name="provoking_vertex">Wierzchołek prowokujący</string>
<string name="provoking_vertex_description">Poprawia oświetlenie i obsługę wierzchołków w niektórych grach. Obsługiwane tylko przez GPU Vulkan 1.0+.</string>
<string name="descriptor_indexing">Indeksowanie deskryptorów</string>
<string name="descriptor_indexing_description">Poprawia obsługę tekstur i buforów oraz warstwę tłumaczenia Maxwell. Obsługiwane przez niektóre GPU Vulkan 1.1 i wszystkie GPU Vulkan 1.2+.</string>
<string name="sample_shading_fraction">Cieniowanie próbkowane</string>
<string name="sample_shading_fraction_description">Pozwala uruchamiać shader fragmentów dla każdej próbki w wielopróbkowanym fragmencie zamiast raz na fragment. Poprawia jakość grafiki kosztem części wydajności.</string>
@@ -913,9 +907,6 @@
<string name="dma_accuracy_unsafe">Niezalecane</string>
<string name="dma_accuracy_safe">Bezpieczne</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">Bez kompresji</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">Oszczędny</string>
<string name="vram_usage_aggressive">Agresywny</string>
@@ -446,8 +446,6 @@
<string name="vram_usage_mode_description">Controla a alocação de memória GPU</string>
<string name="accelerate_astc">Método de decodificação ASTC</string>
<string name="accelerate_astc_description">Escolha como as texturas comprimidas em ASTC são decodificadas para renderização: CPU (lenta, segura), GPU (rápida, recomendada) ou CPU Assíncrona (sem travamentos, mas pode causar problemas).</string>
<string name="astc_recompression">Método de recompressão ASTC</string>
<string name="astc_recompression_description">Escolha como as texturas ASTC são recompactadas para melhorar a compatibilidade e o desempenho. Ativar esta opção economiza VRAM, mas pode reduzir a qualidade da textura.</string>
<string name="sync_memory_operations">Sincronizar Operações de Memória</string>
<string name="sync_memory_operations_description">Garante a consistência de dados entre operações de computação e memória. Esta opção pode corrigir problemas em alguns jogos, mas também pode reduzir o desempenho, sendo os jogos da Unreal Engine 4 os mais afetados.</string>
@@ -467,10 +465,6 @@
<string name="disabled">Desativado</string>
<string name="vertex_input_dynamic_state">Vertex Input Dynamic State</string>
<string name="vertex_input_dynamic_state_description">Ativa o recurso de vertex input dynamic state para melhor qualidade e desempenho.</string>
<string name="provoking_vertex">Provoking Vertex</string>
<string name="provoking_vertex_description">Vértice Provocante: Melhora a iluminação e o processamento de vértices em certos jogos. Suportado apenas em GPUs com Vulkan 1.0 ou superior.</string>
<string name="descriptor_indexing">Descriptor Indexing</string>
<string name="descriptor_indexing_description">Indexação de Descritores: Melhora o processamento de texturas e buffers, assim como a camada de tradução Maxwell. Suportado por algumas GPUs Vulkan 1.1 e todas as GPUs Vulkan 1.2 ou superiores.</string>
<string name="display">Tela</string>
<string name="renderer_screen_layout">Orientação</string>
@@ -858,9 +852,6 @@
<string name="dma_accuracy_unsafe">Insegura</string>
<string name="dma_accuracy_safe">Segura</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">Não comprimido</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">Conservador</string>
<string name="vram_usage_aggressive">Agressivo</string>
@@ -366,8 +366,6 @@
<string name="vram_usage_mode_description">Controla alocação de memória GPU.</string>
<string name="accelerate_astc">Método ASTC</string>
<string name="accelerate_astc_description">Escolha como as texturas comprimidas em ASTC são descodificadas para renderização: CPU (lento, seguro), GPU (rápido, recomendado) ou CPU Async (sem engasgos, pode causar problemas)</string>
<string name="astc_recompression">Recompressão ASTC</string>
<string name="astc_recompression_description">Escolha como as texturas ASTC são recomprimidas para melhorar a compatibilidade e o desempenho. Ativar esta opção poupa VRAM, mas pode reduzir a qualidade da textura.</string>
<string name="sync_memory_operations">Sincronizar Operações de Memória</string>
<string name="sync_memory_operations_description">Garante a consistência dos dados entre operações de computação e memória. Esta opção deve corrigir problemas em alguns jogos, mas pode reduzir o desempenho nalguns casos. Os jogos com Unreal Engine 4 parecem ser os mais afectados.</string>
@@ -383,10 +381,6 @@
<string name="renderer_asynchronous_shaders_description">Compila shaders de forma assíncrona. Isto pode reduzir engasgadelas, mas também pode introduzir falhas gráficas.</string>
<string name="dyna_state">Estado Dinâmico Estendido</string>
<string name="disabled">Desativado</string>
<string name="provoking_vertex">Vértice provocante</string>
<string name="provoking_vertex_description">Melhora a iluminação e o tratamento de vértices em certos jogos. Suportado apenas em GPUs Vulkan 1.0+.</string>
<string name="descriptor_indexing">Indexação de descritores</string>
<string name="descriptor_indexing_description">Melhora o tratamento de texturas e buffers, assim como a camada de tradução Maxwell. Suportado por algumas GPUs Vulkan 1.1 e todas Vulkan 1.2+.</string>
<string name="display">Ecrã</string>
<string name="renderer_screen_layout">Oriantação</string>
@@ -723,9 +717,6 @@ uma tentativa de mapeamento automático</string>
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Predefinido</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">Não Comprimido</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">Conservador</string>
<string name="vram_usage_aggressive">Agressivo</string>
@@ -475,8 +475,6 @@
<string name="vram_usage_mode_description">Стратегия управления видеопамятью</string>
<string name="accelerate_astc">Метод декодирования ASTC</string>
<string name="accelerate_astc_description">Выберите способ декодирования сжатых текстур ASTC для рендеринга: ЦП (медленно, безопасно), ГПУ (быстро, рекомендуется) или ЦП асинхронно (без заиканий, могут возникнуть проблемы)</string>
<string name="astc_recompression">Метод пережатия ASTC</string>
<string name="astc_recompression_description">Выберите способ пересжатия текстур ASTC для улучшения совместимости и производительности. Включение этой опции экономит VRAM, но может снизить качество текстур.</string>
<string name="sync_memory_operations">Синхронизация операций с памятью</string>
<string name="sync_memory_operations_description">Обеспечивает согласованность данных между вычислительными операциями и операциями с памятью. Эта опция должна исправлять проблемы в некоторых играх, но может снижать производительность в некоторых случаях. Наиболее сильно это затрагивает игры на Unreal Engine 4.</string>
@@ -484,6 +482,10 @@
<string name="use_disk_shader_cache_description">Уменьшение зависаний за счет хранения и загрузки сгенерированных шейдеров.</string>
<string name="renderer_force_max_clock">Принудительная максимальная тактовая частота (только для Adreno)</string>
<string name="renderer_force_max_clock_description">Заставляет ГПУ работать на максимально возможных тактовых частотах (тепловые ограничения все равно будут применяться).</string>
<string name="renderer_asynchronous_gpu_emulation">Асинхронная эмуляция ГПУ</string>
<string name="renderer_asynchronous_gpu_emulation_description">Выполняет эмуляцию ГПУ асинхронно для снижения задержек ЦП и увеличения производительности. Отключайте только при возникновении проблем с таймингами.</string>
<string name="renderer_async_presentation">Асинхронная презентация</string>
<string name="renderer_async_presentation_description">Немного улучшает производительность, перемещая презентацию в отдельный поток ЦП.</string>
<string name="renderer_reactive_flushing">Реактивная очистка</string>
<string name="renderer_reactive_flushing_description">Повышение точности рендеринга в некоторых играх за счет снижения производительности.</string>
<string name="enable_buffer_history">Включить историю буфера</string>
@@ -521,10 +523,6 @@
<string name="disabled">Отключено</string>
<string name="vertex_input_dynamic_state">Динамическое состояние ввода вершин</string>
<string name="vertex_input_dynamic_state_description">Включает функцию динамического состояния ввода вершин для повышения качества и производительности</string>
<string name="provoking_vertex">Определяющая вершина</string>
<string name="provoking_vertex_description">Улучшает освещение и обработку вершин в некоторых играх. Поддерживается только ГПУ с Vulkan 1.0+.</string>
<string name="descriptor_indexing">Индексирование дескрипторов</string>
<string name="descriptor_indexing_description">Улучшает обработку текстур и буферов, а также слой перевода Maxwell. Поддерживается некоторыми ГПУ Vulkan 1.1 и всеми ГПУ Vulkan 1.2+.</string>
<string name="sample_shading_fraction">Сэмпловое затенение</string>
<string name="sample_shading_fraction_description">Позволяет шейдеру фрагментов выполняться для каждого сэмпла в многосэмпловом фрагменте, а не один раз на фрагмент. Улучшает качество графики ценой некоторого падения производительности.</string>
@@ -993,9 +991,6 @@
<string name="dma_accuracy_unsafe">Небезопасно</string>
<string name="dma_accuracy_safe">Безопасный</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">Без сжатия</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">Консервативный</string>
<string name="vram_usage_aggressive">Агрессивный</string>
@@ -1089,6 +1084,7 @@
<string name="app_language_system">Следовать системе</string>
<!-- Static Themes -->
<string name="static_theme_color">Цвет темы</string>
<string name="eden_theme">Eden</string>
<string name="violet">Фиолетовый </string>
<string name="blue">Синий</string>
<string name="cyan">Циановый</string>
@@ -365,8 +365,6 @@
<string name="vram_usage_mode_description">Контролишите колико агресивно емулатор додељује и ослобађа ГПУ меморију.</string>
<string name="accelerate_astc">АСТЦ метода декодирања</string>
<string name="accelerate_astc_description">Изаберите како су текстуре са компримираним текстовима декодиране за приказивање: ЦПУ (споро, сигуран), ГПУ (Фаст, Препоручи) или ЦПУ АСИНЦ (без затезача, могу да изазове питања)</string>
<string name="astc_recompression">Метода рекомпресије АСТЦ-а</string>
<string name="astc_recompression_description">Изаберите како се текстуре АСТЦ препоручују да би се побољшале компатибилност и перформансе. Омогућавање ове опције штеди ВРАМ, али може смањити квалитет текстуре.</string>
<string name="sync_memory_operations">Синхронизација меморијских операција</string>
<string name="sync_memory_operations_description">Осигурава конзистентност података између рачунских и меморијских операција. Ова опција би требало да поправи проблеме у неким играма, али може смањити перформансе у неким случајевима. Чини се да су игре са Unreal Engine 4 највише погођене.</string>
@@ -382,10 +380,6 @@
<string name="renderer_asynchronous_shaders_description">Саставља схадера асинхроно. Ово може умањити затезаче, али могу такође да уведе пропусте.</string>
<string name="dyna_state">Проширена динамичка држава</string>
<string name="disabled">Искључено</string>
<string name="provoking_vertex">Провоцирајући врх</string>
<string name="provoking_vertex_description">Побољшава осветљење и вертификат руковања у одређеним играма. Подржан само на Вулкану 1.0+ ГПУ-у.</string>
<string name="descriptor_indexing">Индексирање дескриптора</string>
<string name="descriptor_indexing_description">Побољшава текстуру и руковање међуспремника, као и преводилачки слој Маквелл. Подржани од стране неких Вулкана 1.1 ГПУ-а и сви Вулкан 1.2+ ГПУ.</string>
<string name="display">Приказ</string>
<string name="renderer_screen_layout">Оријентација</string>
@@ -720,9 +714,6 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Подразумевано</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">Некомпримован</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">Конзервативан</string>
<string name="vram_usage_aggressive">Агресиван</string>
@@ -475,8 +475,6 @@
<string name="vram_usage_mode_description">Налаштування виділення пам`яті GPU</string>
<string name="accelerate_astc">Метод декодування ASTC</string>
<string name="accelerate_astc_description">Виберіть спосіб декодування стиснених текстур ASTC для рендерингу: CPU (повільно, безпечно), GPU (швидко, рекомендовано) або CPU Async (без затримок, можуть виникнути несправності)</string>
<string name="astc_recompression">Метод перестиснення ASTC</string>
<string name="astc_recompression_description">Виберіть спосіб перестиснення текстур ASTC для покращення сумісності та продуктивності. Увімкнення цієї опції зберігає VRAM, але може знизити якість текстур.</string>
<string name="sync_memory_operations">Синхронізація операцій з пам\'яттю</string>
<string name="sync_memory_operations_description">Забезпечує узгодженість даних між обчислювальними операціями та операціями з пам\'яттю. Ця опція має виправляти проблеми в деяких іграх, але може знижувати продуктивність у деяких випадках. Ігри на Unreal Engine 4, здається, найбільш постраждалі.</string>
@@ -484,6 +482,10 @@
<string name="use_disk_shader_cache_description">Зменшує затримки шляхом збереження шейдерів.</string>
<string name="renderer_force_max_clock">Максимальна тактова частота (тільки Adreno)</string>
<string name="renderer_force_max_clock_description">Змушує GPU працювати на максимальній тактовій частоті.</string>
<string name="renderer_asynchronous_gpu_emulation">Асинхронна емуляція ГП</string>
<string name="renderer_asynchronous_gpu_emulation_description">Емуляція ГП виконується асинхронно для зменшення затримок ЦП й покращення пропускної здатності. Вимкніть лише у випадку виникнення проблем із таймінгами.</string>
<string name="renderer_async_presentation">Асинхронне подання</string>
<string name="renderer_async_presentation_description">Трохи покращує продуктивність завдяки переміщенню подання на окремий потік ЦП.</string>
<string name="renderer_reactive_flushing">Реактивне очищення</string>
<string name="renderer_reactive_flushing_description">Покращує точність рендерингу в деяких іграх.</string>
<string name="enable_buffer_history">Увімкнути історію буфера</string>
@@ -521,10 +523,6 @@
<string name="disabled">Вимкнено</string>
<string name="vertex_input_dynamic_state">Динамічний стан введення вершин</string>
<string name="vertex_input_dynamic_state_description">Вмикає можливість динамічного стану введення вершин для кращих якості й продуктивності.</string>
<string name="provoking_vertex">Провокативна вершина</string>
<string name="provoking_vertex_description">Покращує освітлення та взаємодію з вершинами у деяких іграх. Лише для ГП з підтримкою Vulkan 1.0+.</string>
<string name="descriptor_indexing">Індексація дескрипторів</string>
<string name="descriptor_indexing_description">Покращує обробку текстур та буферів, а також шар перекладу Maxwell. Підтримується деякими GPU Vulkan 1.1 та всіма GPU Vulkan 1.2+.</string>
<string name="sample_shading_fraction">Простий шейдинг</string>
<string name="sample_shading_fraction_description">Дозволяє виконувати фрагмент шейдера для кожного зразка в багатозразковому фрагменті замість одного разу для кожного фрагмента. Покращує якість графікі ціною втрати продуктивності.</string>
@@ -993,9 +991,6 @@
<string name="dma_accuracy_unsafe">Небезпечно</string>
<string name="dma_accuracy_safe">Безпечно</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">Без стиснення</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">Консервативний</string>
<string name="vram_usage_aggressive">Агресивний</string>
@@ -341,8 +341,6 @@
<string name="vram_usage_mode_description">Kiểm soát cách cấp phát bộ nhớ GPU</string>
<string name="accelerate_astc">Phương thức giải mã ASTC</string>
<string name="accelerate_astc_description">Chọn cách giải mã texture nén ASTC để kết xuất: CPU (chậm, an toàn), GPU (nhanh, khuyên dùng) hoặc CPU Async (không giật, có thể gây ra sự cố)</string>
<string name="astc_recompression">Phương thức nén lại ASTC</string>
<string name="astc_recompression_description">Chọn cách nén lại texture ASTC để cải thiện khả năng tương thích và hiệu suất. Bật tùy chọn này tiết kiệm VRAM nhưng có thể làm giảm chất lượng texture.</string>
<string name="sync_memory_operations">Đồng bộ hoá thao tác bộ nhớ</string>
<string name="sync_memory_operations_description">Đảm bảo tính nhất quán dữ liệu giữa các thao tác tính toán và bộ nhớ. Tùy chọn này nên khắc phục sự cố trong một số trò chơi, nhưng có thể làm giảm hiệu suất trong một số trường hợp. Các trò chơi với Unreal Engine 4 có vẻ bị ảnh hưởng nhiều nhất.</string>
@@ -358,10 +356,6 @@
<string name="renderer_asynchronous_shaders_description">Biên dịch shader không đồng bộ. Điều này có thể giảm giật lag nhưng cũng có thể gây ra lỗi đồ họa.</string>
<string name="dyna_state">Trạng thái động mở rộng</string>
<string name="disabled">Đã tắt</string>
<string name="provoking_vertex">Đỉnh kích hoạt</string>
<string name="provoking_vertex_description">Cải thiện ánh sáng và xử lý đỉnh trong một số trò chơi. Chỉ được hỗ trợ trên GPU Vulkan 1.0+.</string>
<string name="descriptor_indexing">Lập chỉ mục bộ mô tả</string>
<string name="descriptor_indexing_description">Cải thiện xử lý kết cấu và bộ đệm, cũng như lớp dịch Maxwell. Được hỗ trợ bởi một số GPU Vulkan 1.1 và tất cả GPU Vulkan 1.2+.</string>
<string name="display">Hiển thị</string>
<string name="renderer_screen_layout">Hướng màn hình</string>
@@ -586,9 +580,6 @@
<!-- DMA Accuracy -->
<string name="dma_accuracy_default">Mặc định</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">Không nén</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">Bảo thủ</string>
<string name="vram_usage_aggressive">Mạnh</string>
@@ -55,7 +55,7 @@
<string name="stats_overlay_options_description">配置性能统计叠加层中显示的信息</string>
<string name="show_fps">显示帧率</string>
<string name="show_fps_description">显示当前帧率</string>
<string name="show_frametime">显示帧时间</string>
<string name="show_frametime">显示 Frametime</string>
<string name="show_app_ram_usage">显示应用内存使用情况</string>
<string name="show_app_ram_usage_description">显示模拟器内存用量</string>
<string name="show_system_ram_usage">显示系统内存使用情况</string>
@@ -469,8 +469,6 @@
<string name="vram_usage_mode_description">控制显存分配策略</string>
<string name="accelerate_astc">ASTC解码方式</string>
<string name="accelerate_astc_description">选择ASTC压缩纹理的解码方式:CPU(慢速、安全)、GPU(快速、推荐)或CPU异步(无卡顿,可能导致问题)</string>
<string name="astc_recompression">ASTC重压缩方式</string>
<string name="astc_recompression_description">选择ASTC纹理的重新压缩方式以提高兼容性和性能。启用此选项可节省VRAM,但可能会降低纹理质量。</string>
<string name="sync_memory_operations">同步内存操作</string>
<string name="sync_memory_operations_description">确保计算和内存操作之间的数据一致性。 此选项应能修复某些游戏中的问题,但在某些情况下可能会降低性能。 使用Unreal Engine 4的游戏似乎受影响最大。</string>
@@ -478,21 +476,25 @@
<string name="use_disk_shader_cache_description">将生成的着色器缓存于磁盘中并进行读取,以减少卡顿。</string>
<string name="renderer_force_max_clock">强制最大时钟 (仅限 Adreno)</string>
<string name="renderer_force_max_clock_description">强制 GPU 以最大时钟运行 (仍被温控限制)。</string>
<string name="renderer_asynchronous_gpu_emulation">GPU 异步模拟</string>
<string name="renderer_asynchronous_gpu_emulation_description">异步运行 GPU 模拟,以减少 CPU 停顿并提高吞吐量。仅当遇到与时序相关的问题时才应禁用此功能。</string>
<string name="renderer_async_presentation">异步呈现</string>
<string name="renderer_async_presentation_description">通过将呈现操作移至单独的 CPU 线程来略微提升性能。</string>
<string name="renderer_reactive_flushing">启用反应性刷新</string>
<string name="renderer_reactive_flushing_description">牺牲性能提高某些游戏的渲染精度。</string>
<string name="renderer_reactive_flushing_description">通过牺牲性能提高某些游戏的渲染精度。</string>
<string name="enable_buffer_history">启用缓冲区历史</string>
<string name="enable_buffer_history_description">允许访问之前的缓冲状态。\n这个选项可能会提升某些游戏渲染质量性能一致性。</string>
<string name="enable_buffer_history_description">启用对先前缓冲状态的访问。此选项可在某些游戏中提升渲染质量并保持性能一致性。</string>
<string name="use_optimized_vertex_buffers">优化顶点缓冲区</string>
<string name="use_optimized_vertex_buffers_description">实现优化顶点缓冲区绑定以提升性能。需要 Mesa 26.0+ Turnip 驱动。老驱动会崩溃。</string>
<string name="use_optimized_vertex_buffers_description">启用经过优化顶点缓冲区绑定以提升性能。需要 Mesa 26.0 及以上版本的 Turnip 驱动程序。在旧版驱动程序上会导致程序崩溃。</string>
<string name="hacks">Hacks</string>
<string name="fast_gpu_time">GPU 超频频率</string>
<string name="fast_gpu_time_description">强制大多数游戏以其最高原生分辨率运行。使用 256 获得最性能,使用 512 获得最大图形保真度。</string>
<string name="fast_gpu_time_description">强制大多数游戏以其最高原生分辨率运行。设置为 256 获得最性能,设置为 512 获得最佳画面保真度。</string>
<string name="skip_cpu_inner_invalidation">跳过CPU内部无效化</string>
<string name="skip_cpu_inner_invalidation_description">在内存更新期间跳过某些CPU端缓存无效化,减少CPU使用率并提高其性能。可能会导致某些游戏出现故障或崩溃。</string>
<string name="fix_bloom_effects">修复泛光效果</string>
<string name="fix_bloom_effects_description">减少《塞尔达传说:智慧的再现》(LA/EOW) 在 Adreno 700 系列 GPU 上的模糊,并移除《横冲直撞》(Burnout) 中的模糊特效。警告:可能会导致其他游戏出现画面花屏或异常</string>
<string name="fix_bloom_effects">修复 Bloom 效果</string>
<string name="fix_bloom_effects_description">减少《塞尔达传说:智慧的再现》Adreno 700)中的 bloom 模糊,并移除《Burnout》中的 bloom 效果。警告:可能会导致其他游戏出现画面显示问题</string>
<string name="renderer_asynchronous_shaders">使用异步着色器</string>
<string name="renderer_asynchronous_shaders_description">异步编译着色器。这可能会减少卡顿,但也可能会导致图形错误。</string>
<string name="gpu_unswizzle_settings">GPU 还原设置</string>
@@ -515,10 +517,6 @@
<string name="disabled">已禁用</string>
<string name="vertex_input_dynamic_state">顶点输入动态状态</string>
<string name="vertex_input_dynamic_state_description">开启顶点输入动态状态功能来获得更好的质量和性能。</string>
<string name="provoking_vertex">引发顶点</string>
<string name="provoking_vertex_description">改善某些游戏中的光照和顶点处理。仅支持Vulkan 1.0+ GPU。</string>
<string name="descriptor_indexing">描述符索引</string>
<string name="descriptor_indexing_description">改进纹理和缓冲区处理以及Maxwell转换层。部分Vulkan 1.1 GPU和所有Vulkan 1.2+ GPU支持。</string>
<string name="sample_shading_fraction">采样着色</string>
<string name="sample_shading_fraction_description">允许片段着色器在多采样片段中每个样本执行一次,而不是每个片段执行一次。以提高性能为代价改善图形质量。</string>
@@ -987,9 +985,6 @@
<string name="dma_accuracy_unsafe">不安全</string>
<string name="dma_accuracy_safe">安全</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">不压缩</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">保守模式</string>
<string name="vram_usage_aggressive">激进模式</string>
@@ -451,8 +451,6 @@
<string name="vram_usage_mode_description">控制GPU記憶體的分配與釋放策略</string>
<string name="accelerate_astc">ASTC解碼方式</string>
<string name="accelerate_astc_description">選擇ASTC壓縮紋理的解碼方式:CPU(慢速、安全)、GPU(快速、推薦)或CPU非同步(無卡頓,可能導致問題)</string>
<string name="astc_recompression">ASTC重新壓縮方式</string>
<string name="astc_recompression_description">選擇ASTC紋理的重新壓縮方式以提高相容性和效能。啟用此選項可節省VRAM,但可能會降低紋理品質。</string>
<string name="sync_memory_operations">同步記憶體操作</string>
<string name="sync_memory_operations_description">確保計算和記憶體操作之間的資料一致性。 此選項應能修復某些遊戲中的問題,但在某些情況下可能會降低效能。 使用Unreal Engine 4的遊戲似乎受影響最大。</string>
@@ -470,10 +468,6 @@
<string name="disabled">已停用</string>
<string name="vertex_input_dynamic_state">頂點輸入動態狀態</string>
<string name="vertex_input_dynamic_state_description">啟用頂點輸入動態狀態以取得更佳的品質及性能</string>
<string name="provoking_vertex">引發頂點</string>
<string name="provoking_vertex_description">改善某些遊戲中的光照和頂點處理。僅支援Vulkan 1.0+ GPU。</string>
<string name="descriptor_indexing">描述符索引</string>
<string name="descriptor_indexing_description">改進紋理和緩衝區處理以及Maxwell轉換層。部分Vulkan 1.1 GPU和所有Vulkan 1.2+ GPU支援。</string>
<string name="display">顯示</string>
<string name="renderer_screen_layout">方向</string>
@@ -861,9 +855,6 @@
<string name="dma_accuracy_unsafe">不安全</string>
<string name="dma_accuracy_safe">安全</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">未壓縮</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">保守</string>
<string name="vram_usage_aggressive">積極</string>
@@ -138,21 +138,6 @@
<item>1</item> <!-- GPU -->
<item>2</item> <!-- CPU Asynchronously -->
</integer-array>
<!-- ASTC Recompression Method Choices -->
<string-array name="astcRecompressionMethodNames">
<item>@string/astc_recompression_uncompressed</item>
<item>@string/astc_recompression_bc1</item>
<item>@string/astc_recompression_bc3</item>
</string-array>
<!-- ASTC Recompression Method Values -->
<integer-array name="astcRecompressionMethodValues">
<item>0</item> <!-- Uncompressed -->
<item>1</item> <!-- BC1 -->
<item>2</item> <!-- BC3 -->
</integer-array>
<!-- NVDEC Emulation Choices -->
<string-array name="rendererNvdecNames">
<item>@string/nvdec_emulation_none</item> <!-- Off -->
@@ -485,8 +485,6 @@
<string name="vram_usage_mode_description">Control how aggressively the emulator allocates and frees GPU memory.</string>
<string name="accelerate_astc">ASTC Decoding Method</string>
<string name="accelerate_astc_description">Pick how ASTC-compressed textures are decoded for rendering: CPU (slow, safe), GPU (fast, recommended), or CPU Async (no stutters, may cause issues)</string>
<string name="astc_recompression">ASTC Recompression Method</string>
<string name="astc_recompression_description">Choose how ASTC textures are recompressed to improve compatibility and performance. Enabling this option saves VRAM but may lower texture quality.</string>
<string name="sync_memory_operations">Sync Memory Operations</string>
<string name="sync_memory_operations_description">Ensures data consistency between compute and memory operations. This option should fix issues in some games, but may also reduce performance in some cases. Unreal Engine 4 games often see the most significant changes thereof.</string>
@@ -494,12 +492,16 @@
<string name="use_disk_shader_cache_description">Reduces stuttering by locally storing and loading generated shaders.</string>
<string name="renderer_force_max_clock">Force maximum clocks (Adreno only)</string>
<string name="renderer_force_max_clock_description">Forces the GPU to run at the maximum possible clocks (thermal constraints will still be applied).</string>
<string name="renderer_asynchronous_gpu_emulation">GPU async emulation</string>
<string name="renderer_asynchronous_gpu_emulation_description">Runs GPU emulation asynchronously to reduce CPU stalls and improve throughput. Disable this only if you run into timing-related issues.</string>
<string name="renderer_async_presentation">Asynchronous presentation</string>
<string name="renderer_async_presentation_description">Slightly improves performance by moving presentation to a separate CPU thread.</string>
<string name="renderer_reactive_flushing">Use reactive flushing</string>
<string name="renderer_reactive_flushing_description">Improves rendering accuracy in some games at the cost of performance.</string>
<string name="enable_buffer_history">Enable buffer history</string>
<string name="enable_buffer_history_description">Enables access to previous buffer states. This option may improve rendering quality and performance consistency in some games.</string>
<string name="use_optimized_vertex_buffers">Optimized Vertex Buffers</string>
<string name="use_optimized_vertex_buffers_description">Enables optimized vertex buffer binding for improved performance. Requires Mesa 26.0+ Turnip drivers. Will crash on older drivers.</string>
<string name="use_optimized_vertex_buffers_description">Enables optimized vertex buffer binding for improved performance. Requires Mesa 26.0+ Turnip drivers/ QCOM drivers. Will crash on older Turnip drivers.</string>
<string name="hacks">Hacks</string>
@@ -508,7 +510,9 @@
<string name="skip_cpu_inner_invalidation">Skip CPU Inner Invalidation</string>
<string name="skip_cpu_inner_invalidation_description">Skips certain CPU-side cache invalidations during memory updates, reducing CPU usage and improving it\'s performance. This may cause glitches or crashes on some games.</string>
<string name="fix_bloom_effects">Fix Bloom Effects</string>
<string name="fix_bloom_effects_description">Reduces bloom blur in LA/EOW (Adreno 700), removes bloom in Burnout. Warning: may cause graphical artifacts in other games.</string>
<string name="fix_bloom_effects_description">Reduces bloom blur in LA/EOW (Adreno A6XX - A7XX/ Turnip), removes bloom in Burnout. Warning: may cause graphical artifacts in other games.</string>
<string name="emulate_bgr565">Emulate BGR565</string>
<string name="emulate_bgr565_description">Fixes problems with inverted colors in games or strange artifacts or strange shadows.</string>
<string name="renderer_asynchronous_shaders">Use asynchronous shaders</string>
<string name="renderer_asynchronous_shaders_description">Compiles shaders asynchronously. This may reduce stutters but may also introduce glitches.</string>
<string name="gpu_unswizzle_settings">GPU Unswizzle Settings</string>
@@ -531,10 +535,6 @@
<string name="disabled">Disabled</string>
<string name="vertex_input_dynamic_state">Vertex Input Dynamic State</string>
<string name="vertex_input_dynamic_state_description">Enables vertex input dynamic state feature for better quality and performance.</string>
<string name="provoking_vertex">Provoking Vertex</string>
<string name="provoking_vertex_description">Improves lighting and vertex handling in certain games. Only supported on Vulkan 1.0+ GPUs.</string>
<string name="descriptor_indexing">Descriptor Indexing</string>
<string name="descriptor_indexing_description">Improves texture and buffer handling, as well as the Maxwell translation layer. Supported by some Vulkan 1.1 GPUs and all Vulkan 1.2+ GPUs.</string>
<string name="sample_shading_fraction">Sample Shading</string>
<string name="sample_shading_fraction_description">Allows the fragment shader to execute per sample in a multi-sampled fragment instead once per fragment. Improves graphics quality at the cost of some performance.</string>
@@ -1041,12 +1041,7 @@
<string name="accelerate_astc_gpu" translatable="false">GPU</string>
<string name="accelerate_astc_async" translatable="false">CPU Async</string>
<!-- ASTC Recompression Method Choices -->
<string name="astc_recompression_uncompressed">Uncompressed</string>
<string name="astc_recompression_bc1" translatable="false">BC1</string>
<string name="astc_recompression_bc3" translatable="false">BC3</string>
<!-- ASTC Recompression Method Choices -->
<string name="vram_usage_conservative">Conservative</string>
<string name="vram_usage_aggressive">Aggressive</string>
@@ -243,6 +243,9 @@ void AndroidKeyboard::SubmitInlineKeyboardInput(int key_code) {
static_cast<s32>(m_current_text.size()));
break;
case KEYCODE_DEL:
if (m_current_text.empty()) {
return;
}
m_current_text.pop_back();
submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, m_current_text,
static_cast<int>(m_current_text.size()));
+13 -10
View File
@@ -359,7 +359,11 @@ struct Values {
true,
true};
SwitchableSetting<int, true> fsr_sharpening_slider{linkage,
#ifdef ANDROID
0,
#else
25,
#endif
0,
200,
"fsr_sharpening_slider",
@@ -450,11 +454,7 @@ struct Values {
"max_anisotropy",
Category::RendererAdvanced};
SwitchableSetting<AstcDecodeMode, true> accelerate_astc{linkage,
#ifdef ANDROID
AstcDecodeMode::Cpu,
#else
AstcDecodeMode::Gpu,
#endif
"accelerate_astc",
Category::RendererAdvanced};
@@ -555,6 +555,9 @@ struct Values {
SwitchableSetting<bool> fix_bloom_effects{linkage, false, "fix_bloom_effects",
Category::RendererHacks};
SwitchableSetting<bool> emulate_bgr565{linkage, false, "emulate_bgr565",
Category::RendererHacks};
SwitchableSetting<bool> rescale_hack{linkage, false, "rescale_hack",
Category::RendererHacks};
@@ -583,7 +586,9 @@ struct Values {
Category::RendererHacks};
SwitchableSetting<ExtendedDynamicState> dyna_state{linkage,
#if defined (ANDROID) || defined (__APPLE__)
#if defined(ANDROID)
ExtendedDynamicState::Disabled,
#elif defined(__APPLE__)
ExtendedDynamicState::Disabled,
#else
ExtendedDynamicState::EDS2,
@@ -606,8 +611,6 @@ struct Values {
true,
#endif
"vertex_input_dynamic_state", Category::RendererExtensions};
SwitchableSetting<bool> provoking_vertex{linkage, false, "provoking_vertex", Category::RendererExtensions};
SwitchableSetting<bool> descriptor_indexing{linkage, false, "descriptor_indexing", Category::RendererExtensions};
Setting<bool> renderer_debug{linkage, false, "debug", Category::RendererDebug};
Setting<bool> renderer_shader_feedback{linkage, false, "shader_feedback",
@@ -636,8 +639,8 @@ struct Values {
Category::System};
SwitchableSetting<Region, true> region_index{linkage, Region::Usa, "region_index", Category::System};
SwitchableSetting<TimeZone, true> time_zone_index{linkage, TimeZone::Auto, "time_zone_index", Category::System};
Setting<u32> serial_battery{linkage, 0, "serial_battery", Category::System};
Setting<u32> serial_unit{linkage, 0, "serial_unit", Category::System};
Setting<u32> serial_battery{linkage, 0, "serial_battery", Category::Debugging};
Setting<u32> serial_unit{linkage, 0, "serial_unit", Category::Debugging};
// Measured in seconds since epoch
SwitchableSetting<bool> custom_rtc_enabled{linkage, false, "custom_rtc_enabled", Category::System, Specialization::Paired, true, true};
SwitchableSetting<s64> custom_rtc{
@@ -807,7 +810,7 @@ struct Values {
0,
65535,
"debug_knobs",
Category::Core,
Category::Debugging,
Specialization::Countable,
true,
true};
@@ -289,7 +289,6 @@ void ArmDynarmic32::MakeJit(Common::PageTable* page_table) {
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue;
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN;
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor;
break;
// Paranoia mode for debugging optimizations
case Settings::CpuAccuracy::Paranoid:
@@ -340,7 +340,6 @@ void ArmDynarmic64::MakeJit(Common::PageTable* page_table, std::size_t address_s
config.unsafe_optimizations = true;
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA;
config.fastmem_address_space_bits = 64;
config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreGlobalMonitor;
break;
// Paranoia mode for debugging optimizations
case Settings::CpuAccuracy::Paranoid:
+43 -59
View File
@@ -6,6 +6,8 @@
#include <condition_variable>
#include <mutex>
#include <optional>
#include <stop_token>
#include <thread>
#include "core/core.h"
@@ -18,59 +20,53 @@ namespace Kernel::Svc {
constexpr auto MAX_MSG_TIME = std::chrono::milliseconds(250);
const auto MAX_MSG_SIZE = 0x1000;
static std::string msg_buffer;
static std::mutex msg_mutex;
static std::condition_variable msg_cv;
static std::chrono::steady_clock::time_point last_msg_time;
static bool worker_running = true;
static std::unique_ptr<std::thread> flush_thread;
static std::once_flag start_flag;
static void FlushDbgLoop() {
while (true) {
std::unique_lock lock(msg_mutex);
msg_cv.wait(lock, [] { return !msg_buffer.empty() || !worker_running; });
if (!worker_running && msg_buffer.empty()) break;
auto timeout = last_msg_time + MAX_MSG_TIME;
bool woke_early = msg_cv.wait_until(lock, timeout, [] {
return msg_buffer.size() >= MAX_MSG_SIZE || !worker_running;
});
if (!woke_early || msg_buffer.size() >= MAX_MSG_SIZE || !worker_running) {
if (!msg_buffer.empty()) {
// Remove trailing newline as LOG_INFO adds that anyways
if (msg_buffer.back() == '\n')
msg_buffer.pop_back();
LOG_INFO(Debug_Emulated, "\n{}", msg_buffer);
msg_buffer.clear();
}
if (!worker_running) break;
}
}
}
/// Used to output a message on a debug hardware unit - does nothing on a retail unit
Result OutputDebugString(Core::System& system, u64 address, u64 len) {
static struct DebugFlusher {
std::string msg_buffer;
std::mutex msg_mutex;
std::condition_variable msg_cv;
std::chrono::steady_clock::time_point last_msg_time;
std::optional<std::jthread> thread;
} flusher_data;
R_SUCCEED_IF(len == 0);
// Only start the thread the very first time this function is called
std::call_once(start_flag, [] {
flush_thread = std::make_unique<std::thread>(FlushDbgLoop);
});
if (!flusher_data.thread) {
flusher_data.thread.emplace([](std::stop_token stop_token) {
while (!stop_token.stop_requested()) {
std::unique_lock lock(flusher_data.msg_mutex);
flusher_data.msg_cv.wait(lock, [&stop_token] {
return !flusher_data.msg_buffer.empty() || stop_token.stop_requested();
});
if (stop_token.stop_requested() && flusher_data.msg_buffer.empty())
break;
auto timeout = flusher_data.last_msg_time + MAX_MSG_TIME;
bool woke_early = flusher_data.msg_cv.wait_until(lock, timeout, [&stop_token] {
return flusher_data.msg_buffer.size() >= MAX_MSG_SIZE || stop_token.stop_requested();
});
if (!woke_early || flusher_data.msg_buffer.size() >= MAX_MSG_SIZE || stop_token.stop_requested()) {
if (!flusher_data.msg_buffer.empty()) {
// Remove trailing newline as LOG_INFO adds that anyways
if (flusher_data.msg_buffer.back() == '\n')
flusher_data.msg_buffer.pop_back();
{
std::lock_guard lock(msg_mutex);
const auto old_size = msg_buffer.size();
msg_buffer.resize(old_size + len);
GetCurrentMemory(system.Kernel()).ReadBlock(address, msg_buffer.data() + old_size, len);
last_msg_time = std::chrono::steady_clock::now();
LOG_INFO(Debug_Emulated, "\n{}", flusher_data.msg_buffer);
flusher_data.msg_buffer.clear();
}
if (stop_token.stop_requested()) break;
}
}
flusher_data.msg_cv.notify_all();
});
}
msg_cv.notify_one();
{
std::lock_guard lock(flusher_data.msg_mutex);
const auto old_size = flusher_data.msg_buffer.size();
flusher_data.msg_buffer.resize(old_size + len);
GetCurrentMemory(system.Kernel()).ReadBlock(address, flusher_data.msg_buffer.data() + old_size, len);
flusher_data.last_msg_time = std::chrono::steady_clock::now();
}
flusher_data.msg_cv.notify_one();
R_SUCCEED();
}
@@ -82,16 +78,4 @@ Result OutputDebugString64From32(Core::System& system, uint32_t debug_str, uint3
R_RETURN(OutputDebugString(system, debug_str, len));
}
struct BufferAutoFlush {
~BufferAutoFlush() {
{
std::lock_guard lock(msg_mutex);
worker_running = false;
}
msg_cv.notify_all();
if (flush_thread && flush_thread->joinable()) flush_thread->join();
}
};
static BufferAutoFlush auto_flusher;
} // namespace Kernel::Svc
@@ -23,16 +23,14 @@ static const auto default_cg_mode = nullptr; //Allow RWE
namespace Dynarmic {
void EmitSpinLockLock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg32 tmp, bool waitpkg) {
// TODO: this is because we lack regalloc - so better to be safe :(
if (waitpkg) {
code.push(Xbyak::util::eax);
code.push(Xbyak::util::ebx);
code.push(Xbyak::util::edx);
}
Xbyak::Label start, loop;
code.jmp(start, code.T_NEAR);
code.L(loop);
if (waitpkg) {
// TODO: this is because we lack regalloc - so better to be safe :(
code.push(Xbyak::util::rax);
code.push(Xbyak::util::rbx);
code.push(Xbyak::util::rdx);
// TODO: This clobbers EAX and EDX did we tell the regalloc?
// ARM ptr for address-monitoring
code.umonitor(ptr);
@@ -49,6 +47,9 @@ void EmitSpinLockLock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg32
code.umwait(Xbyak::util::ebx);
// CF == 1 if we hit the OS-timeout in IA32_UMWAIT_CONTROL without a write
// CF == 0 if we exited the wait for any other reason
code.pop(Xbyak::util::rdx);
code.pop(Xbyak::util::rbx);
code.pop(Xbyak::util::rax);
} else {
code.pause();
}
@@ -57,11 +58,6 @@ void EmitSpinLockLock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg32
/*code.lock();*/ code.xchg(code.dword[ptr], tmp);
code.test(tmp, tmp);
code.jnz(loop, code.T_NEAR);
if (waitpkg) {
code.pop(Xbyak::util::edx);
code.pop(Xbyak::util::ebx);
code.pop(Xbyak::util::eax);
}
}
void EmitSpinLockUnlock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg32 tmp) {
+2 -11
View File
@@ -169,6 +169,8 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent) {
tr("Runs an additional optimization pass over generated SPIRV shaders.\n"
"Will increase time required for shader compilation.\nMay slightly improve "
"performance.\nThis feature is experimental."));
INSERT(Settings, use_asynchronous_gpu_emulation, tr("Use asynchronous GPU emulation"),
tr("Uses an extra CPU thread for rendering.\nThis option should always remain enabled."));
INSERT(Settings, nvdec_emulation, tr("NVDEC emulation:"),
tr("Specifies how videos should be decoded.\nIt can either use the CPU or the GPU for "
"decoding, or perform no decoding at all (black screen on videos).\n"
@@ -286,14 +288,6 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent) {
INSERT(Settings, vertex_input_dynamic_state, tr("Vertex Input Dynamic State"),
tr("Enables vertex input dynamic state feature for better quality and performance."));
INSERT(Settings, provoking_vertex, tr("Provoking Vertex"),
tr("Improves lighting and vertex handling in some games.\n"
"Only Vulkan 1.0+ devices support this extension."));
INSERT(Settings, descriptor_indexing, tr("Descriptor Indexing"),
tr("Improves texture & buffer handling and the Maxwell translation layer.\n"
"Some Vulkan 1.1+ and all 1.2+ devices support this extension."));
INSERT(
Settings, sample_shading, tr("Sample Shading"),
tr("Allows the fragment shader to execute per sample in a multi-sampled fragment "
@@ -323,9 +317,6 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent) {
"their resolution, details and supported controllers and depending on this setting.\n"
"Setting to Handheld can help improve performance for low end systems."));
INSERT(Settings, current_user, QString(), QString());
INSERT(Settings, serial_unit, tr("Unit Serial"), QString());
INSERT(Settings, serial_battery, tr("Battery Serial"), QString());
INSERT(Settings, debug_knobs, tr("Debug knobs"), QString());
// Controls
@@ -178,6 +178,9 @@ void DefineGenericOutput(EmitContext& ctx, size_t index, std::optional<u32> invo
ctx.Decorate(id, spv::Decoration::XfbBuffer, xfb_varying->buffer);
ctx.Decorate(id, spv::Decoration::XfbStride, xfb_varying->stride);
ctx.Decorate(id, spv::Decoration::Offset, xfb_varying->offset);
if (ctx.stage == Stage::Geometry && xfb_varying->stream != 0) {
ctx.Decorate(id, spv::Decoration::Stream, xfb_varying->stream);
}
}
if (num_components < 4 || element > 0) {
const std::string_view subswizzle{swizzle.substr(element, num_components)};
+1
View File
@@ -76,6 +76,7 @@ enum class TessSpacing {
struct TransformFeedbackVarying {
u32 buffer{};
u32 stream{};
u32 stride{};
u32 offset{};
u32 components{};
+18 -15
View File
@@ -1067,26 +1067,29 @@ void BufferCache<P>::BindHostTransformFeedbackBuffers() {
HostBindings<typename P::Buffer> host_bindings;
for (u32 index = 0; index < NUM_TRANSFORM_FEEDBACK_BUFFERS; ++index) {
const Binding& binding = channel_state->transform_feedback_buffers[index];
if (maxwell3d->regs.transform_feedback.controls[index].varying_count == 0 &&
maxwell3d->regs.transform_feedback.controls[index].stride == 0) {
break;
const auto& control = maxwell3d->regs.transform_feedback.controls[index];
const bool has_layout = control.varying_count != 0 || control.stride != 0;
Buffer* host_buffer = &slot_buffers[NULL_BUFFER_ID];
u32 offset = 0;
u32 size = 0;
if (has_layout && binding.buffer_id != NULL_BUFFER_ID && binding.size != 0) {
Buffer& buffer = slot_buffers[binding.buffer_id];
TouchBuffer(buffer, binding.buffer_id);
size = binding.size;
SynchronizeBuffer(buffer, binding.device_addr, size);
MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size);
offset = buffer.Offset(binding.device_addr);
buffer.MarkUsage(offset, size);
host_buffer = &buffer;
}
Buffer& buffer = slot_buffers[binding.buffer_id];
TouchBuffer(buffer, binding.buffer_id);
const u32 size = binding.size;
SynchronizeBuffer(buffer, binding.device_addr, size);
MarkWrittenBuffer(binding.buffer_id, binding.device_addr, size);
const u32 offset = buffer.Offset(binding.device_addr);
buffer.MarkUsage(offset, size);
host_bindings.buffers.push_back(&buffer);
host_bindings.buffers.push_back(host_buffer);
host_bindings.offsets.push_back(offset);
host_bindings.sizes.push_back(size);
}
if (host_bindings.buffers.size() > 0) {
runtime.BindTransformFeedbackBuffers(host_bindings);
}
runtime.BindTransformFeedbackBuffers(host_bindings);
}
template <class P>
+11 -2
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
@@ -92,7 +92,16 @@ void ThreadManager::InvalidateRegion(DAddr addr, u64 size) {
}
void ThreadManager::FlushAndInvalidateRegion(DAddr addr, u64 size) {
// Skip flush on asynch mode, as FlushAndInvalidateRegion is not used for anything too important
if (Settings::IsGPULevelHigh()) {
if (!is_async) {
PushCommand(FlushRegionCommand(addr, size));
} else {
auto& gpu = system.GPU();
const u64 fence = gpu.RequestFlush(addr, size);
TickGPU();
gpu.WaitForSyncOperation(fence);
}
}
rasterizer->OnCacheInvalidation(addr, size);
}
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@@ -5,16 +8,22 @@
layout(local_size_x = 1) in;
layout(std430, binding = 0) buffer Query {
uvec2 initial;
uvec2 unknown;
uvec2 current;
layout(std430, binding = 0) readonly buffer Query {
uint data[];
};
layout(std430, binding = 1) buffer Result {
layout(std430, binding = 1) writeonly buffer Result {
uint result;
};
layout(push_constant) uniform PushConstants {
uint compare_to_zero;
};
void main() {
result = all(equal(initial, current)) ? 1 : 0;
if (compare_to_zero != 0u) {
result = (data[0] != 0u && data[1] != 0u) ? 1u : 0u;
} else {
result = (data[0] == data[4] && data[1] == data[5]) ? 1u : 0u;
}
}
+2 -2
View File
@@ -285,11 +285,11 @@ void HLE_MultiDrawIndexedIndirectCount::Fallback(Engines::Maxwell3D& maxwell3d,
}
void HLE_DrawIndirectByteCount::Execute(Engines::Maxwell3D& maxwell3d, std::span<const u32> parameters, [[maybe_unused]] u32 method) {
const bool force = maxwell3d.Rasterizer().HasDrawTransformFeedback();
auto topology = Maxwell3D::Regs::PrimitiveTopology(parameters[0] & 0xFFFFU);
if (!force && (!maxwell3d.AnyParametersDirty() || !IsTopologySafe(topology))) {
if (!force) {
Fallback(maxwell3d, parameters);
return;
}
auto topology = Maxwell3D::Regs::PrimitiveTopology(parameters[0] & 0xFFFFU);
auto& params = maxwell3d.draw_manager->GetIndirectParams();
params.is_byte_count = true;
params.is_indexed = false;
+1
View File
@@ -412,6 +412,7 @@ bool QueryCacheBase<Traits>::AccelerateHostConditionalRendering() {
.found_query = nullptr,
};
}
it_current = it_current_2;
}
auto* query = impl->ObtainQuery(it_current->second);
qc_dirty |= True(query->flags & QueryFlagBits::IsHostManaged) &&
+4 -1
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@@ -75,7 +78,7 @@ public:
}
u64 GetDependentMask() const {
return dependence_mask;
return dependent_mask;
}
u64 GetAmendValue() const {
@@ -629,6 +629,9 @@ void RasterizerOpenGL::ReleaseFences(bool force) {
void RasterizerOpenGL::FlushAndInvalidateRegion(DAddr addr, u64 size,
VideoCommon::CacheType which) {
if (Settings::IsGPULevelHigh()) {
FlushRegion(addr, size, which);
}
InvalidateRegion(addr, size, which);
}
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
@@ -83,7 +83,29 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
depth_enabled.Assign(regs.zeta_enable != 0 ? 1 : 0);
depth_format.Assign(static_cast<u32>(regs.zeta.format));
y_negate.Assign(regs.window_origin.mode != Maxwell::WindowOrigin::Mode::UpperLeft ? 1 : 0);
provoking_vertex_last.Assign(regs.provoking_vertex == Maxwell::ProvokingVertex::Last ? 1 : 0);
bool use_last_provoking_vertex = false;
const bool provoking_vertex_available = features.has_provoking_vertex;
const bool supports_first_mode = features.has_provoking_vertex_first_mode;
const bool supports_last_mode = features.has_provoking_vertex_last_mode;
const bool transform_feedback_active = regs.transform_feedback_enabled != 0;
const bool tf_preserves_provoking_vertex = features.has_provoking_vertex_tf_preserve;
if (provoking_vertex_available && (supports_first_mode || supports_last_mode)) {
use_last_provoking_vertex = regs.provoking_vertex == Maxwell::ProvokingVertex::Last;
if (transform_feedback_active && !tf_preserves_provoking_vertex) {
use_last_provoking_vertex = false;
}
if (use_last_provoking_vertex && !supports_last_mode) {
use_last_provoking_vertex = false;
} else if (!use_last_provoking_vertex && !supports_first_mode) {
use_last_provoking_vertex = true;
}
}
provoking_vertex_last.Assign(use_last_provoking_vertex ? 1 : 0);
conservative_raster_enable.Assign(regs.conservative_raster_enable != 0 ? 1 : 0);
smooth_lines.Assign(regs.line_anti_alias_enable != 0 ? 1 : 0);
alpha_to_coverage_enabled.Assign(regs.anti_alias_alpha_control.alpha_to_coverage != 0 ? 1 : 0);
@@ -168,9 +190,7 @@ void FixedPipelineState::Refresh(Tegra::Engines::Maxwell3D& maxwell3d, DynamicFe
}
}
}
if (!extended_dynamic_state_3_enables) {
dynamic_state.Refresh3(regs);
}
dynamic_state.Refresh3(regs, features);
if (xfb_enabled) {
RefreshXfbState(xfb_state, regs);
}
@@ -273,16 +293,22 @@ void FixedPipelineState::DynamicState::Refresh2(const Maxwell& regs,
depth_bias_enable.Assign(enabled_lut[POLYGON_OFFSET_ENABLE_LUT[topology_index]] != 0 ? 1 : 0);
}
void FixedPipelineState::DynamicState::Refresh3(const Maxwell& regs) {
logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0);
depth_clamp_disabled.Assign(regs.viewport_clip_control.geometry_clip ==
Maxwell::ViewportClipControl::GeometryClip::Passthrough ||
regs.viewport_clip_control.geometry_clip ==
Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ ||
regs.viewport_clip_control.geometry_clip ==
Maxwell::ViewportClipControl::GeometryClip::FrustumZ);
line_stipple_enable.Assign(regs.line_stipple_enable);
void FixedPipelineState::DynamicState::Refresh3(const Maxwell& regs,
const DynamicFeatures& features) {
if (!features.has_dynamic_state3_logic_op_enable) {
logic_op_enable.Assign(regs.logic_op.enable != 0 ? 1 : 0);
}
if (!features.has_dynamic_state3_depth_clamp_enable) {
depth_clamp_disabled.Assign(regs.viewport_clip_control.geometry_clip ==
Maxwell::ViewportClipControl::GeometryClip::Passthrough ||
regs.viewport_clip_control.geometry_clip ==
Maxwell::ViewportClipControl::GeometryClip::FrustumXYZ ||
regs.viewport_clip_control.geometry_clip ==
Maxwell::ViewportClipControl::GeometryClip::FrustumZ);
}
if (!features.has_dynamic_state3_line_stipple_enable) {
line_stipple_enable.Assign(regs.line_stipple_enable);
}
}
size_t FixedPipelineState::Hash() const noexcept {
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
@@ -27,7 +27,14 @@ struct DynamicFeatures {
bool has_extended_dynamic_state_2_patch_control_points;
bool has_extended_dynamic_state_3_blend;
bool has_extended_dynamic_state_3_enables;
bool has_dynamic_state3_depth_clamp_enable;
bool has_dynamic_state3_logic_op_enable;
bool has_dynamic_state3_line_stipple_enable;
bool has_dynamic_vertex_input;
bool has_provoking_vertex;
bool has_provoking_vertex_first_mode;
bool has_provoking_vertex_last_mode;
bool has_provoking_vertex_tf_preserve;
};
struct FixedPipelineState {
@@ -171,7 +178,7 @@ struct FixedPipelineState {
void Refresh(const Maxwell& regs);
void Refresh2(const Maxwell& regs, Maxwell::PrimitiveTopology topology,
bool base_features_supported);
void Refresh3(const Maxwell& regs);
void Refresh3(const Maxwell& regs, const DynamicFeatures& features);
Maxwell::ComparisonOp DepthTestFunc() const noexcept {
return UnpackComparisonOp(depth_test_func);
@@ -261,8 +268,7 @@ struct FixedPipelineState {
return sizeof(*this);
}
if (dynamic_vertex_input && extended_dynamic_state_3_blend) {
// Exclude dynamic state and attributes
return offsetof(FixedPipelineState, dynamic_state);
return offsetof(FixedPipelineState, attachments);
}
if (dynamic_vertex_input) {
// Exclude dynamic state
@@ -8,6 +8,7 @@
#include <array>
#include <cstring>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <vector>
@@ -171,7 +172,11 @@ try
RendererVulkan::~RendererVulkan() {
scheduler.RegisterOnSubmit([] {});
void(device.GetLogical().WaitIdle());
scheduler.Finish();
{
std::scoped_lock lock{scheduler.submit_mutex};
void(device.GetLogical().WaitIdle());
}
}
void RendererVulkan::Composite(std::span<const Tegra::FramebufferConfig> framebuffers) {
@@ -8,6 +8,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <vulkan/vulkan_core.h>
#include <mutex>
#include "video_core/framebuffer_config.h"
#include "video_core/present.h"
#include "video_core/renderer_vulkan/present/filters.h"
@@ -31,7 +32,10 @@ BlitScreen::~BlitScreen() = default;
void BlitScreen::WaitIdle() {
present_manager.WaitPresent();
scheduler.Finish();
device.GetLogical().WaitIdle();
{
std::scoped_lock lock{scheduler.submit_mutex};
device.GetLogical().WaitIdle();
}
}
void BlitScreen::SetWindowAdaptPass() {
@@ -637,12 +637,10 @@ void BufferCacheRuntime::BindTransformFeedbackBuffers(VideoCommon::HostBindings<
for (u32 i = 0; i < bindings.buffers.size(); ++i) {
auto handle = bindings.buffers[i]->Handle();
if (handle == VK_NULL_HANDLE) {
ReserveNullBuffer();
handle = *null_buffer;
bindings.offsets[i] = 0;
bindings.sizes[i] = VK_WHOLE_SIZE;
if (!device.HasNullDescriptor()) {
ReserveNullBuffer();
handle = *null_buffer;
}
bindings.sizes[i] = 0;
}
buffer_handles[i] = handle;
}
@@ -228,6 +228,10 @@ struct QueriesPrefixScanPushConstants {
u32 accumulation_limit;
u32 buffer_offset;
};
struct ConditionalRenderingResolvePushConstants {
u32 compare_to_zero;
};
} // Anonymous namespace
ComputePass::ComputePass(const Device& device_, DescriptorPool& descriptor_pool,
@@ -413,7 +417,8 @@ ConditionalRenderingResolvePass::ConditionalRenderingResolvePass(
const Device& device_, Scheduler& scheduler_, DescriptorPool& descriptor_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue_)
: ComputePass(device_, descriptor_pool_, INPUT_OUTPUT_DESCRIPTOR_SET_BINDINGS,
INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO, nullptr,
INPUT_OUTPUT_DESCRIPTOR_UPDATE_TEMPLATE, INPUT_OUTPUT_BANK_INFO,
COMPUTE_PUSH_CONSTANT_RANGE<sizeof(ConditionalRenderingResolvePushConstants)>,
RESOLVE_CONDITIONAL_RENDER_COMP_SPV),
scheduler{scheduler_}, compute_pass_descriptor_queue{compute_pass_descriptor_queue_} {}
@@ -430,7 +435,7 @@ void ConditionalRenderingResolvePass::Resolve(VkBuffer dst_buffer, VkBuffer src_
const void* const descriptor_data{compute_pass_descriptor_queue.UpdateData()};
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([this, descriptor_data](vk::CommandBuffer cmdbuf) {
scheduler.Record([this, descriptor_data, compare_to_zero](vk::CommandBuffer cmdbuf) {
static constexpr VkMemoryBarrier read_barrier{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
.pNext = nullptr,
@@ -443,6 +448,9 @@ void ConditionalRenderingResolvePass::Resolve(VkBuffer dst_buffer, VkBuffer src_
.srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT,
.dstAccessMask = VK_ACCESS_CONDITIONAL_RENDERING_READ_BIT_EXT,
};
const ConditionalRenderingResolvePushConstants uniforms{
.compare_to_zero = compare_to_zero ? 1U : 0U,
};
const VkDescriptorSet set = descriptor_allocator.Commit();
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
@@ -450,9 +458,11 @@ void ConditionalRenderingResolvePass::Resolve(VkBuffer dst_buffer, VkBuffer src_
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, read_barrier);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {});
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, uniforms);
cmdbuf.Dispatch(1, 1, 1);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, write_barrier);
VK_PIPELINE_STAGE_CONDITIONAL_RENDERING_BIT_EXT, 0,
write_barrier);
});
}
@@ -520,7 +530,7 @@ void QueriesPrefixScanPass::Run(VkBuffer accumulation_buffer, VkBuffer dst_buffe
const VkDescriptorSet set = descriptor_allocator.Commit();
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, read_barrier);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {});
@@ -467,6 +467,10 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
bind_stage_info(4);
}
if (regs.transform_feedback_enabled != 0) {
scheduler.RequestOutsideRenderPassOperationContext();
}
buffer_cache.UpdateGraphicsBuffers(is_indexed);
buffer_cache.BindHostGeometryBuffers(is_indexed);
@@ -749,12 +753,19 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
: VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT,
.extraPrimitiveOverestimationSize = 0.0f,
};
const bool supports_provoking_first_mode = device.SupportsProvokingVertexFirstMode();
const bool supports_provoking_last_mode = device.SupportsProvokingVertexLastMode();
const bool requested_provoking_last_mode = key.state.provoking_vertex_last != 0;
const VkProvokingVertexModeEXT provoking_vertex_mode =
requested_provoking_last_mode
? (supports_provoking_last_mode ? VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT
: VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT)
: (supports_provoking_first_mode ? VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT
: VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT);
VkPipelineRasterizationProvokingVertexStateCreateInfoEXT provoking_vertex{
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT,
.pNext = nullptr,
.provokingVertexMode = key.state.provoking_vertex_last != 0
? VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT
: VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT,
.provokingVertexMode = provoking_vertex_mode,
};
if (IsLine(input_assembly_topology) && device.IsExtLineRasterizationSupported()) {
@@ -763,7 +774,7 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
if (device.IsExtConservativeRasterizationSupported()) {
conservative_raster.pNext = std::exchange(rasterization_ci.pNext, &conservative_raster);
}
if (device.IsExtProvokingVertexSupported() && Settings::values.provoking_vertex.GetValue()) {
if (device.IsExtProvokingVertexSupported()) {
provoking_vertex.pNext = std::exchange(rasterization_ci.pNext, &provoking_vertex);
}
@@ -485,11 +485,25 @@ PipelineCache::PipelineCache(Tegra::MaxwellDeviceMemoryManager& device_memory_,
device.IsExtExtendedDynamicState3BlendingSupported();
dynamic_features.has_extended_dynamic_state_3_enables =
device.IsExtExtendedDynamicState3EnablesSupported();
dynamic_features.has_dynamic_state3_depth_clamp_enable =
device.SupportsDynamicState3DepthClampEnable();
dynamic_features.has_dynamic_state3_logic_op_enable =
device.SupportsDynamicState3LogicOpEnable();
dynamic_features.has_dynamic_state3_line_stipple_enable =
device.SupportsDynamicState3LineStippleEnable();
// VIDS: Independent toggle (not affected by dyna_state levels)
dynamic_features.has_dynamic_vertex_input =
device.IsExtVertexInputDynamicStateSupported() &&
Settings::values.vertex_input_dynamic_state.GetValue();
dynamic_features.has_provoking_vertex = device.IsExtProvokingVertexSupported();
dynamic_features.has_provoking_vertex_first_mode =
device.SupportsProvokingVertexFirstMode();
dynamic_features.has_provoking_vertex_last_mode =
device.SupportsProvokingVertexLastMode();
dynamic_features.has_provoking_vertex_tf_preserve =
device.SupportsTransformFeedbackProvokingVertexPreservation();
}
PipelineCache::~PipelineCache() {
@@ -603,6 +617,18 @@ void PipelineCache::LoadDiskResources(u64 title_id, std::stop_token stop_loading
(key.state.dynamic_vertex_input != 0) != dynamic_features.has_dynamic_vertex_input) {
return;
}
const bool key_requests_provoking_last = key.state.provoking_vertex_last != 0;
if (key_requests_provoking_last && !dynamic_features.has_provoking_vertex_last_mode) {
return;
}
const bool key_uses_transform_feedback = key.state.xfb_enabled != 0;
if (key_uses_transform_feedback && key_requests_provoking_last &&
!dynamic_features.has_provoking_vertex_tf_preserve) {
return;
}
workers.QueueWork([this, key, envs_ = std::move(envs), &state, &callback]() mutable {
ShaderPools pools;
boost::container::static_vector<Shader::Environment*, 5> env_ptrs;
@@ -189,7 +189,7 @@ void PresentManager::RecreateFrame(Frame* frame, u32 width, u32 height, VkFormat
frame->image = memory_allocator.CreateImage({
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.pNext = nullptr,
.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT,
.imageType = VK_IMAGE_TYPE_2D,
.format = swapchain.GetImageFormat(),
.extent =
+129 -26
View File
@@ -157,8 +157,9 @@ public:
ReserveHostQuery();
scheduler.Record([query_pool = current_query_pool,
query_index = current_bank_slot](vk::CommandBuffer cmdbuf) {
query_index = current_bank_slot](vk::CommandBuffer cmdbuf) {
const bool use_precise = Settings::IsGPULevelHigh();
cmdbuf.ResetQueryPool(query_pool, static_cast<u32>(query_index), 1);
cmdbuf.BeginQuery(query_pool, static_cast<u32>(query_index),
use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0);
});
@@ -220,8 +221,7 @@ public:
}
PauseCounter();
const auto driver_id = device.GetDriverID();
if (driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY ||
driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) {
if (driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) {
pending_sync.clear();
sync_values_stash.clear();
return;
@@ -666,13 +666,18 @@ public:
offsets.fill(0);
last_queries.fill(0);
last_queries_stride.fill(1);
stream_to_slot.fill(INVALID_SLOT);
VkBufferUsageFlags counter_buffer_usage =
VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
if (device.IsExtTransformFeedbackSupported()) {
counter_buffer_usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT;
}
const VkBufferCreateInfo buffer_ci = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.size = TFBQueryBank::QUERY_SIZE * NUM_STREAMS,
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT,
.usage = counter_buffer_usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr,
@@ -692,6 +697,9 @@ public:
~TFBCounterStreamer() = default;
void StartCounter() override {
if (!device.IsExtTransformFeedbackSupported()) {
return;
}
FlushBeginTFB();
has_started = true;
}
@@ -706,7 +714,9 @@ public:
void CloseCounter() override {
if (has_flushed_end_pending) {
FlushEndTFB();
if (scheduler.IsRenderPassActive()) {
FlushEndTFB();
}
}
runtime.View3DRegs([this](Maxwell3D& maxwell3d) {
if (maxwell3d.regs.transform_feedback_enabled == 0) {
@@ -756,18 +766,33 @@ public:
if (has_timestamp) {
new_query->flags |= VideoCommon::QueryFlagBits::HasTimestamp;
}
if (!device.IsExtTransformFeedbackSupported()) {
new_query->flags |= VideoCommon::QueryFlagBits::IsFinalValueSynced;
return index;
}
if (!subreport_) {
new_query->flags |= VideoCommon::QueryFlagBits::IsFinalValueSynced;
return index;
}
const size_t subreport = static_cast<size_t>(*subreport_);
if (subreport >= NUM_STREAMS) {
new_query->flags |= VideoCommon::QueryFlagBits::IsFinalValueSynced;
return index;
}
last_queries[subreport] = address;
if ((streams_mask & (1ULL << subreport)) == 0) {
new_query->flags |= VideoCommon::QueryFlagBits::IsFinalValueSynced;
return index;
}
const size_t slot = stream_to_slot[subreport];
if (slot >= NUM_STREAMS) {
new_query->flags |= VideoCommon::QueryFlagBits::IsFinalValueSynced;
return index;
}
scheduler.RequestOutsideRenderPassOperationContext();
CloseCounter();
auto [bank_slot, data_slot] = ProduceCounterBuffer(subreport);
auto [bank_slot, data_slot] = ProduceCounterBuffer(slot);
new_query->start_bank_id = static_cast<u32>(bank_slot);
new_query->size_banks = 1;
new_query->start_slot = static_cast<u32>(data_slot);
@@ -778,6 +803,9 @@ public:
}
std::optional<std::pair<DAddr, size_t>> GetLastQueryStream(size_t stream) {
if (stream >= NUM_STREAMS) {
return std::nullopt;
}
if (last_queries[stream] != 0) {
std::pair<DAddr, size_t> result(last_queries[stream], last_queries_stride[stream]);
return result;
@@ -789,6 +817,10 @@ public:
return out_topology;
}
u32 GetPatchVertices() const {
return patch_vertices;
}
bool HasUnsyncedQueries() const override {
return !pending_flush_queries.empty();
}
@@ -855,6 +887,9 @@ public:
private:
void FlushBeginTFB() {
if (!device.IsExtTransformFeedbackSupported()) [[unlikely]] {
return;
}
if (has_flushed_end_pending) [[unlikely]] {
return;
}
@@ -868,12 +903,24 @@ private:
});
return;
}
static constexpr VkMemoryBarrier COUNTER_RESUME_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT,
.dstAccessMask = VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT,
};
scheduler.Record([this, total = static_cast<u32>(buffers_count)](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,
VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, 0,
COUNTER_RESUME_BARRIER);
cmdbuf.BeginTransformFeedbackEXT(0, total, counter_buffers.data(), offsets.data());
});
}
void FlushEndTFB() {
if (!device.IsExtTransformFeedbackSupported()) [[unlikely]] {
return;
}
if (!has_flushed_end_pending) [[unlikely]] {
UNREACHABLE();
return;
@@ -899,28 +946,48 @@ private:
void UpdateBuffers() {
last_queries.fill(0);
last_queries_stride.fill(1);
stream_to_slot.fill(INVALID_SLOT);
streams_mask = 0; // reset previously recorded streams
runtime.View3DRegs([this](Maxwell3D& maxwell3d) {
buffers_count = 0;
out_topology = maxwell3d.draw_manager->GetDrawState().topology;
patch_vertices = std::max(maxwell3d.regs.patch_vertices, 1U);
if (out_topology == Maxwell3D::Regs::PrimitiveTopology::Patches) {
switch (maxwell3d.regs.tessellation.params.output_primitives.Value()) {
case Maxwell3D::Regs::Tessellation::OutputPrimitives::Points:
out_topology = Maxwell3D::Regs::PrimitiveTopology::Points;
break;
case Maxwell3D::Regs::Tessellation::OutputPrimitives::Lines:
out_topology = Maxwell3D::Regs::PrimitiveTopology::LineStrip;
break;
case Maxwell3D::Regs::Tessellation::OutputPrimitives::Triangles_CW:
case Maxwell3D::Regs::Tessellation::OutputPrimitives::Triangles_CCW:
out_topology = Maxwell3D::Regs::PrimitiveTopology::TriangleStrip;
break;
}
}
for (size_t i = 0; i < Maxwell3D::Regs::NumTransformFeedbackBuffers; i++) {
const auto& tf = maxwell3d.regs.transform_feedback;
if (tf.buffers[i].enable == 0) {
continue;
}
buffers_count = std::max<size_t>(buffers_count, i + 1);
const size_t stream = tf.controls[i].stream;
if (stream >= last_queries_stride.size()) {
LOG_WARNING(Render_Vulkan, "TransformFeedback stream {} out of range", stream);
continue;
}
if ((streams_mask & (1ULL << stream)) != 0) {
continue;
}
last_queries_stride[stream] = tf.controls[i].stride;
stream_to_slot[stream] = i;
streams_mask |= 1ULL << stream;
buffers_count = std::max<size_t>(buffers_count, stream + 1);
}
});
}
std::pair<size_t, size_t> ProduceCounterBuffer(size_t stream) {
std::pair<size_t, size_t> ProduceCounterBuffer(size_t slot_index) {
if (current_bank == nullptr || current_bank->IsClosed()) {
current_bank_id =
bank_pool.ReserveBank([this](std::deque<TFBQueryBank>& queue, size_t index) {
@@ -946,7 +1013,8 @@ private:
};
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([dst_buffer = current_bank->GetBuffer(),
src_buffer = counter_buffers[stream], src_offset = offsets[stream],
src_buffer = counter_buffers[slot_index],
src_offset = offsets[slot_index],
slot](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER);
@@ -965,6 +1033,7 @@ private:
friend class PrimitivesSucceededStreamer;
static constexpr size_t NUM_STREAMS = 4;
static constexpr size_t INVALID_SLOT = NUM_STREAMS;
QueryCacheRuntime& runtime;
const Device& device;
@@ -994,7 +1063,9 @@ private:
std::array<VkDeviceSize, NUM_STREAMS> offsets{};
std::array<DAddr, NUM_STREAMS> last_queries;
std::array<size_t, NUM_STREAMS> last_queries_stride;
std::array<size_t, NUM_STREAMS> stream_to_slot;
Maxwell3D::Regs::PrimitiveTopology out_topology;
u32 patch_vertices{1};
u64 streams_mask;
};
@@ -1015,6 +1086,7 @@ public:
u64 stride{};
DAddr dependant_address{};
Maxwell3D::Regs::PrimitiveTopology topology{Maxwell3D::Regs::PrimitiveTopology::Points};
u32 patch_vertices{1};
size_t dependant_index{};
bool dependant_manage{};
};
@@ -1031,6 +1103,10 @@ public:
~PrimitivesSucceededStreamer() = default;
void ResetCounter() override {
tfb_streamer.ResetCounter();
}
size_t WriteCounter(DAddr address, bool has_timestamp, u32 value,
std::optional<u32> subreport_) override {
auto index = BuildQuery();
@@ -1048,6 +1124,7 @@ public:
auto dependant_address_opt = tfb_streamer.GetLastQueryStream(subreport);
bool must_manage_dependance = false;
new_query->topology = tfb_streamer.GetOutputTopology();
new_query->patch_vertices = tfb_streamer.GetPatchVertices();
if (dependant_address_opt) {
auto [dep_address, stride] = *dependant_address_opt;
new_query->dependant_address = dep_address;
@@ -1068,6 +1145,7 @@ public:
}
new_query->stride = 1;
runtime.View3DRegs([new_query, subreport](Maxwell3D& maxwell3d) {
new_query->patch_vertices = std::max(maxwell3d.regs.patch_vertices, 1U);
for (size_t i = 0; i < Maxwell3D::Regs::NumTransformFeedbackBuffers; i++) {
const auto& tf = maxwell3d.regs.transform_feedback;
if (tf.buffers[i].enable == 0) {
@@ -1131,27 +1209,39 @@ public:
}
}
query->value = [&]() -> u64 {
const auto saturating_subtract = [](u64 value, u64 amount) {
return value > amount ? value - amount : 0;
};
switch (query->topology) {
case Maxwell3D::Regs::PrimitiveTopology::Points:
return num_vertices;
case Maxwell3D::Regs::PrimitiveTopology::Lines:
return num_vertices / 2;
case Maxwell3D::Regs::PrimitiveTopology::LineLoop:
return (num_vertices / 2) + 1;
return num_vertices > 1 ? num_vertices : 0;
case Maxwell3D::Regs::PrimitiveTopology::LineStrip:
return num_vertices - 1;
case Maxwell3D::Regs::PrimitiveTopology::Patches:
return saturating_subtract(num_vertices, 1);
case Maxwell3D::Regs::PrimitiveTopology::LinesAdjacency:
return num_vertices / 4;
case Maxwell3D::Regs::PrimitiveTopology::LineStripAdjacency:
return saturating_subtract(num_vertices, 3);
case Maxwell3D::Regs::PrimitiveTopology::Triangles:
case Maxwell3D::Regs::PrimitiveTopology::TrianglesAdjacency:
return num_vertices / 3;
case Maxwell3D::Regs::PrimitiveTopology::TrianglesAdjacency:
return num_vertices / 6;
case Maxwell3D::Regs::PrimitiveTopology::TriangleFan:
case Maxwell3D::Regs::PrimitiveTopology::TriangleStrip:
return saturating_subtract(num_vertices, 2);
case Maxwell3D::Regs::PrimitiveTopology::TriangleStripAdjacency:
return num_vertices - 2;
return num_vertices > 4 ? (num_vertices - 4) / 2 : 0;
case Maxwell3D::Regs::PrimitiveTopology::Quads:
return num_vertices / 4;
case Maxwell3D::Regs::PrimitiveTopology::QuadStrip:
return num_vertices > 2 ? (num_vertices - 2) / 2 : 0;
case Maxwell3D::Regs::PrimitiveTopology::Polygon:
return 1U;
return num_vertices >= 3 ? 1U : 0U;
case Maxwell3D::Regs::PrimitiveTopology::Patches:
return num_vertices / std::max<u64>(query->patch_vertices, 1U);
default:
return num_vertices;
}
@@ -1202,16 +1292,24 @@ struct QueryCacheRuntimeImpl {
hcr_setup.pNext = nullptr;
hcr_setup.flags = 0;
conditional_resolve_pass = std::make_unique<ConditionalRenderingResolvePass>(
device, scheduler, descriptor_pool, compute_pass_descriptor_queue);
const bool has_conditional_rendering = device.IsExtConditionalRendering();
if (has_conditional_rendering) {
conditional_resolve_pass = std::make_unique<ConditionalRenderingResolvePass>(
device, scheduler, descriptor_pool, compute_pass_descriptor_queue);
}
VkBufferUsageFlags hcr_buffer_usage =
VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
if (has_conditional_rendering) {
hcr_buffer_usage |= VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT;
}
const VkBufferCreateInfo buffer_ci = {
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.size = sizeof(u32),
.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT,
.usage = hcr_buffer_usage,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0,
.pQueueFamilyIndices = nullptr,
@@ -1338,15 +1436,17 @@ void QueryCacheRuntime::HostConditionalRenderingCompareValueImpl(VideoCommon::Lo
}
}
void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, bool is_equal) {
void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, bool is_equal,
bool compare_to_zero) {
VkBuffer to_resolve;
u32 to_resolve_offset;
const u32 resolve_size = compare_to_zero ? 8 : 24;
{
std::scoped_lock lk(impl->buffer_cache.mutex);
static constexpr auto sync_info = VideoCommon::ObtainBufferSynchronize::NoSynchronize;
const auto sync_info = VideoCommon::ObtainBufferSynchronize::FullSynchronize;
const auto post_op = VideoCommon::ObtainBufferOperation::DoNothing;
const auto [buffer, offset] =
impl->buffer_cache.ObtainCPUBuffer(address, 24, sync_info, post_op);
impl->buffer_cache.ObtainCPUBuffer(address, resolve_size, sync_info, post_op);
to_resolve = buffer->Handle();
to_resolve_offset = static_cast<u32>(offset);
}
@@ -1355,7 +1455,7 @@ void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, boo
PauseHostConditionalRendering();
}
impl->conditional_resolve_pass->Resolve(*impl->hcr_resolve_buffer, to_resolve,
to_resolve_offset, false);
to_resolve_offset, compare_to_zero);
impl->hcr_setup.buffer = *impl->hcr_resolve_buffer;
impl->hcr_setup.offset = 0;
impl->hcr_setup.flags = is_equal ? 0 : VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT;
@@ -1371,7 +1471,7 @@ bool QueryCacheRuntime::HostConditionalRenderingCompareValue(VideoCommon::Lookup
if (!impl->device.IsExtConditionalRendering()) {
return false;
}
HostConditionalRenderingCompareValueImpl(object_1, false);
HostConditionalRenderingCompareBCImpl(object_1.address, true, true);
return true;
}
@@ -1420,7 +1520,8 @@ bool QueryCacheRuntime::HostConditionalRenderingCompareValues(VideoCommon::Looku
auto driver_id = impl->device.GetDriverID();
const bool is_gpu_high = Settings::IsGPULevelHigh();
if ((!is_gpu_high && driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) || driver_id == VK_DRIVER_ID_QUALCOMM_PROPRIETARY || driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) {
if ((!is_gpu_high && driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) || driver_id == VK_DRIVER_ID_ARM_PROPRIETARY || driver_id == VK_DRIVER_ID_MESA_TURNIP) {
EndHostConditionalRendering();
return true;
}
@@ -1437,10 +1538,12 @@ bool QueryCacheRuntime::HostConditionalRenderingCompareValues(VideoCommon::Looku
}
if (!is_gpu_high) {
EndHostConditionalRendering();
return true;
}
if (!is_in_bc[0] && !is_in_bc[1]) {
EndHostConditionalRendering();
return true;
}
HostConditionalRenderingCompareBCImpl(object_1.address, equal_check);
@@ -63,7 +63,8 @@ public:
private:
void HostConditionalRenderingCompareValueImpl(VideoCommon::LookupData object, bool is_equal);
void HostConditionalRenderingCompareBCImpl(DAddr address, bool is_equal);
void HostConditionalRenderingCompareBCImpl(DAddr address, bool is_equal,
bool compare_to_zero = false);
friend struct QueryCacheRuntimeImpl;
std::unique_ptr<QueryCacheRuntimeImpl> impl;
};
+112 -77
View File
@@ -173,6 +173,28 @@ DrawParams MakeDrawParams(const MaxwellDrawState& draw_state, u32 num_instances,
}
return params;
}
bool SupportsPrimitiveRestart(VkPrimitiveTopology topology) {
switch (topology) {
case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
return false;
default:
return true;
}
}
bool IsPrimitiveRestartSupported(const Device& device, VkPrimitiveTopology topology) {
return ((topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
device.IsTopologyListPrimitiveRestartSupported()) ||
SupportsPrimitiveRestart(topology) ||
(topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
device.IsPatchListPrimitiveRestartSupported()));
}
} // Anonymous namespace
RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_,
@@ -200,11 +222,6 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra
fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler),
wfi_event(device.GetLogical().CreateEvent()) {
scheduler.SetQueryCache(query_cache);
// Log multi-draw support
if (device.IsExtMultiDrawSupported()) {
LOG_INFO(Render_Vulkan, "VK_EXT_multi_draw is enabled for optimized draw calls");
}
}
RasterizerVulkan::~RasterizerVulkan() = default;
@@ -230,6 +247,7 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
UpdateDynamicStates();
query_cache.NotifySegment(true);
HandleTransformFeedback();
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64,
maxwell3d->regs.zpass_pixel_count_enable);
@@ -243,43 +261,16 @@ void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
const u32 num_instances{instance_count};
const DrawParams draw_params{MakeDrawParams(draw_state, num_instances, is_indexed)};
// Use VK_EXT_multi_draw if available (single draw becomes multi-draw with count=1)
if (device.IsExtMultiDrawSupported()) {
scheduler.Record([draw_params](vk::CommandBuffer cmdbuf) {
if (draw_params.is_indexed) {
// Use multi-draw indexed with single draw
const VkMultiDrawIndexedInfoEXT multi_draw_info{
.firstIndex = draw_params.first_index,
.indexCount = draw_params.num_vertices,
};
const int32_t vertex_offset = static_cast<int32_t>(draw_params.base_vertex);
cmdbuf.DrawMultiIndexedEXT(1, &multi_draw_info, draw_params.num_instances,
draw_params.base_instance,
sizeof(VkMultiDrawIndexedInfoEXT), &vertex_offset);
} else {
// Use multi-draw with single draw
const VkMultiDrawInfoEXT multi_draw_info{
.firstVertex = draw_params.base_vertex,
.vertexCount = draw_params.num_vertices,
};
cmdbuf.DrawMultiEXT(1, &multi_draw_info, draw_params.num_instances,
draw_params.base_instance,
sizeof(VkMultiDrawInfoEXT));
}
});
} else {
// Fallback to standard draw calls
scheduler.Record([draw_params](vk::CommandBuffer cmdbuf) {
if (draw_params.is_indexed) {
cmdbuf.DrawIndexed(draw_params.num_vertices, draw_params.num_instances,
draw_params.first_index, draw_params.base_vertex,
draw_params.base_instance);
} else {
cmdbuf.Draw(draw_params.num_vertices, draw_params.num_instances,
draw_params.base_vertex, draw_params.base_instance);
}
});
}
scheduler.Record([draw_params](vk::CommandBuffer cmdbuf) {
if (draw_params.is_indexed) {
cmdbuf.DrawIndexed(draw_params.num_vertices, draw_params.num_instances,
draw_params.first_index, draw_params.base_vertex,
draw_params.base_instance);
} else {
cmdbuf.Draw(draw_params.num_vertices, draw_params.num_instances,
draw_params.base_vertex, draw_params.base_instance);
}
});
// Log draw call
if (Settings::values.gpu_logging_enabled.GetValue() &&
@@ -368,6 +359,7 @@ void RasterizerVulkan::DrawTexture() {
UpdateDynamicStates();
query_cache.NotifySegment(true);
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64,
maxwell3d->regs.zpass_pixel_count_enable);
const auto& draw_texture_state = maxwell3d->draw_manager->GetDrawTextureState();
@@ -607,11 +599,17 @@ void RasterizerVulkan::DispatchCompute() {
}
void RasterizerVulkan::ResetCounter(VideoCommon::QueryType type) {
if (type != VideoCommon::QueryType::ZPassPixelCount64) {
switch (type) {
case VideoCommon::QueryType::ZPassPixelCount64:
case VideoCommon::QueryType::StreamingByteCount:
case VideoCommon::QueryType::StreamingPrimitivesSucceeded:
case VideoCommon::QueryType::VtgPrimitivesOut:
query_cache.CounterReset(type);
return;
default:
LOG_DEBUG(Render_Vulkan, "Unimplemented counter reset={}", type);
return;
}
query_cache.CounterReset(type);
}
void RasterizerVulkan::Query(GPUVAddr gpu_addr, VideoCommon::QueryType type,
@@ -798,6 +796,9 @@ void RasterizerVulkan::ReleaseFences(bool force) {
void RasterizerVulkan::FlushAndInvalidateRegion(DAddr addr, u64 size,
VideoCommon::CacheType which) {
if (Settings::IsGPULevelHigh()) {
FlushRegion(addr, size, which);
}
InvalidateRegion(addr, size, which);
}
@@ -862,6 +863,10 @@ bool RasterizerVulkan::AccelerateConditionalRendering() {
return query_cache.AccelerateHostConditionalRendering();
}
bool RasterizerVulkan::HasDrawTransformFeedback() {
return device.IsTransformFeedbackDrawSupported();
}
bool RasterizerVulkan::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src,
const Tegra::Engines::Fermi2D::Surface& dst,
const Tegra::Engines::Fermi2D::Config& copy_config) {
@@ -1008,6 +1013,12 @@ bool AccelerateDMA::BufferToImage(const Tegra::DMA::ImageCopy& copy_info,
void RasterizerVulkan::UpdateDynamicStates() {
auto& regs = maxwell3d->regs;
auto& flags = maxwell3d->dirty.flags;
const auto topology = maxwell3d->draw_manager->GetDrawState().topology;
if (state_tracker.ChangePrimitiveTopology(topology)) {
flags[Dirty::DepthBiasEnable] = true;
flags[Dirty::PrimitiveRestartEnable] = true;
}
// Core Dynamic States (Vulkan 1.0) - Always active regardless of dyna_state setting
UpdateViewportsState(regs);
@@ -1116,6 +1127,9 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg
if (!state_tracker.TouchViewports()) {
return;
}
maxwell3d->dirty.flags[Dirty::Scissors] = true;
if (!regs.viewport_scale_offset_enabled) {
float x = static_cast<float>(regs.surface_clip.x);
float y = static_cast<float>(regs.surface_clip.y);
@@ -1133,8 +1147,12 @@ void RasterizerVulkan::UpdateViewportsState(Tegra::Engines::Maxwell3D::Regs& reg
.minDepth = 0.0f,
.maxDepth = 1.0f,
};
scheduler.Record([viewport](vk::CommandBuffer cmdbuf) {
cmdbuf.SetViewport(0, viewport);
scheduler.Record([this, viewport](vk::CommandBuffer cmdbuf) {
const u32 num_viewports = std::min<u32>(device.GetMaxViewports(), Maxwell::NumViewports);
std::array<VkViewport, Maxwell::NumViewports> viewport_list{};
viewport_list.fill(viewport);
const vk::Span<VkViewport> viewports(viewport_list.data(), num_viewports);
cmdbuf.SetViewport(0, viewports);
});
return;
}
@@ -1174,8 +1192,12 @@ void RasterizerVulkan::UpdateScissorsState(Tegra::Engines::Maxwell3D::Regs& regs
scissor.offset.y = static_cast<int32_t>(y);
scissor.extent.width = width;
scissor.extent.height = height;
scheduler.Record([scissor](vk::CommandBuffer cmdbuf) {
cmdbuf.SetScissor(0, scissor);
scheduler.Record([this, scissor](vk::CommandBuffer cmdbuf) {
const u32 num_scissors = std::min<u32>(device.GetMaxViewports(), Maxwell::NumViewports);
std::array<VkRect2D, Maxwell::NumViewports> scissor_list{};
scissor_list.fill(scissor);
const vk::Span<VkRect2D> scissors(scissor_list.data(), num_scissors);
cmdbuf.SetScissor(0, scissors);
});
return;
}
@@ -1420,7 +1442,17 @@ void RasterizerVulkan::UpdatePrimitiveRestartEnable(Tegra::Engines::Maxwell3D::R
if (!state_tracker.TouchPrimitiveRestartEnable()) {
return;
}
scheduler.Record([enable = regs.primitive_restart.enabled](vk::CommandBuffer cmdbuf) {
bool enable = regs.primitive_restart.enabled != 0;
if (device.IsMoltenVK()) {
enable = true;
} else if (enable) {
const auto topology =
MaxwellToVK::PrimitiveTopology(device, maxwell3d->draw_manager->GetDrawState().topology);
enable = IsPrimitiveRestartSupported(device, topology);
}
scheduler.Record([enable](vk::CommandBuffer cmdbuf) {
cmdbuf.SetPrimitiveRestartEnableEXT(enable);
});
}
@@ -1759,7 +1791,9 @@ void RasterizerVulkan::UpdateStencilTestEnable(Tegra::Engines::Maxwell3D::Regs&
void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs) {
auto& dirty{maxwell3d->dirty.flags};
if (!dirty[Dirty::VertexInput]) {
const bool vertex_input_dirty = dirty[Dirty::VertexInput];
const bool vertex_buffers_dirty = dirty[VideoCommon::Dirty::VertexBuffers];
if (!vertex_input_dirty && !vertex_buffers_dirty) {
return;
}
dirty[Dirty::VertexInput] = false;
@@ -1767,38 +1801,31 @@ void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs)
boost::container::static_vector<VkVertexInputBindingDescription2EXT, 32> bindings;
boost::container::static_vector<VkVertexInputAttributeDescription2EXT, 32> attributes;
// There seems to be a bug on Nvidia's driver where updating only higher attributes ends up
// generating dirty state. Track the highest dirty attribute and update all attributes until
// that one.
size_t highest_dirty_attr{};
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
if (dirty[Dirty::VertexAttribute0 + index]) {
highest_dirty_attr = index;
}
}
for (size_t index = 0; index < highest_dirty_attr; ++index) {
const u32 max_attributes =
static_cast<u32>(std::min<size_t>(Maxwell::NumVertexAttributes,
device.GetMaxVertexInputAttributes()));
const u32 max_bindings =
static_cast<u32>(std::min<size_t>(Maxwell::NumVertexArrays,
device.GetMaxVertexInputBindings()));
for (u32 index = 0; index < max_attributes; ++index) {
const Maxwell::VertexAttribute attribute{regs.vertex_attrib_format[index]};
const u32 binding{attribute.buffer};
dirty[Dirty::VertexAttribute0 + index] = false;
dirty[Dirty::VertexBinding0 + static_cast<size_t>(binding)] = true;
if (!attribute.constant) {
attributes.push_back({
.sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT,
.pNext = nullptr,
.location = static_cast<u32>(index),
.binding = binding,
.format = MaxwellToVK::VertexFormat(device, attribute.type, attribute.size),
.offset = attribute.offset,
});
}
}
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
if (!dirty[Dirty::VertexBinding0 + index]) {
if (attribute.constant || binding >= max_bindings) {
continue;
}
dirty[Dirty::VertexBinding0 + index] = false;
attributes.push_back({
.sType = VK_STRUCTURE_TYPE_VERTEX_INPUT_ATTRIBUTE_DESCRIPTION_2_EXT,
.pNext = nullptr,
.location = index,
.binding = binding,
.format = MaxwellToVK::VertexFormat(device, attribute.type, attribute.size),
.offset = attribute.offset,
});
}
const u32 binding{static_cast<u32>(index)};
for (u32 binding = 0; binding < max_bindings; ++binding) {
const auto& input_binding{regs.vertex_streams[binding]};
const bool is_instanced{regs.vertex_stream_instances.IsInstancingEnabled(binding)};
bindings.push_back({
@@ -1810,6 +1837,14 @@ void RasterizerVulkan::UpdateVertexInput(Tegra::Engines::Maxwell3D::Regs& regs)
.divisor = is_instanced ? input_binding.frequency : 1,
});
}
for (size_t index = 0; index < Maxwell::NumVertexAttributes; ++index) {
dirty[Dirty::VertexAttribute0 + index] = false;
}
for (size_t index = 0; index < Maxwell::NumVertexArrays; ++index) {
dirty[Dirty::VertexBinding0 + index] = false;
}
scheduler.Record([bindings, attributes](vk::CommandBuffer cmdbuf) {
cmdbuf.SetVertexInputEXT(bindings, attributes);
});
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
@@ -122,6 +122,7 @@ public:
void FlushCommands() override;
void TickFrame() override;
bool AccelerateConditionalRendering() override;
bool HasDrawTransformFeedback() override;
bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src,
const Tegra::Engines::Fermi2D::Surface& dst,
const Tegra::Engines::Fermi2D::Config& copy_config) override;
@@ -324,6 +324,8 @@ void Scheduler::EndRenderPass()
return;
}
query_cache->CounterClose(VideoCommon::QueryType::StreamingByteCount);
// Log render pass end
if (Settings::values.gpu_logging_enabled.GetValue() &&
Settings::values.gpu_log_vulkan_calls.GetValue()) {
@@ -63,6 +63,11 @@ public:
/// of a renderpass.
void RequestOutsideRenderPassOperationContext();
/// Returns true when a render pass is currently active in the scheduler state.
bool IsRenderPassActive() const {
return state.renderpass != VK_NULL_HANDLE;
}
/// Update the pipeline to the current execution context.
bool UpdateGraphicsPipeline(GraphicsPipeline* pipeline);
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
@@ -87,6 +87,7 @@ Flags MakeInvalidationFlags() {
void SetupDirtyViewports(Tables& tables) {
FillBlock(tables[0], OFF(viewport_transform), NUM(viewport_transform), Viewports);
FillBlock(tables[0], OFF(viewports), NUM(viewports), Viewports);
FillBlock(tables[1], OFF(surface_clip), NUM(surface_clip), Viewports);
tables[0][OFF(viewport_scale_offset_enabled)] = Viewports;
tables[1][OFF(window_origin)] = Viewports;
}
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
@@ -65,8 +65,10 @@ static VkPresentModeKHR ChooseSwapPresentMode(bool has_imm, bool has_mailbox,
return mode;
}
}();
if (setting == Settings::VSyncMode::Immediate && !has_imm) {
setting = Settings::VSyncMode::Mailbox;
}
if ((setting == Settings::VSyncMode::Mailbox && !has_mailbox) ||
(setting == Settings::VSyncMode::Immediate && !has_imm) ||
(setting == Settings::VSyncMode::FifoRelaxed && !has_fifo_relaxed)) {
setting = Settings::VSyncMode::Fifo;
}
@@ -176,7 +176,18 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
.pViewFormats = view_formats.data(),
};
if (view_formats.size() > 1) {
image_ci.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
image_ci.flags |=
VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
const bool has_storage_compatible_view =
std::any_of(view_formats.begin(), view_formats.end(), [&device](VkFormat view_format) {
return device.IsFormatSupported(view_format, VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT,
FormatType::Optimal);
});
if (has_storage_compatible_view) {
image_ci.usage |= VK_IMAGE_USAGE_STORAGE_BIT;
}
if (device.IsKhrImageFormatListSupported()) {
image_ci.pNext = &image_format_list;
}
@@ -275,6 +286,19 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
return VK_COMPONENT_SWIZZLE_ZERO;
}
void SanitizeDepthStencilSwizzle(std::array<SwizzleSource, 4>& swizzle,
bool supports_depth_stencil_swizzle_one) {
if (supports_depth_stencil_swizzle_one) {
return;
}
std::replace_if(swizzle.begin(), swizzle.end(),
[](SwizzleSource value) {
return value == SwizzleSource::OneFloat ||
value == SwizzleSource::OneInt;
},
SwizzleSource::Zero);
}
[[nodiscard]] VkImageViewType ImageViewType(Shader::TextureType type) {
switch (type) {
case Shader::TextureType::Color1D:
@@ -655,11 +679,16 @@ void CopyBufferToImage(vk::CommandBuffer cmdbuf, VkBuffer src_buffer, VkImage im
}
void TryTransformSwizzleIfNeeded(PixelFormat format, std::array<SwizzleSource, 4>& swizzle,
bool emulate_a4b4g4r4) {
bool emulate_bgr565, bool emulate_a4b4g4r4) {
switch (format) {
case PixelFormat::A1B5G5R5_UNORM:
std::ranges::transform(swizzle, swizzle.begin(), SwapBlueRed);
break;
case PixelFormat::B5G6R5_UNORM:
if (emulate_bgr565) {
std::ranges::transform(swizzle, swizzle.begin(), SwapBlueRed);
}
break;
case PixelFormat::A5B5G5R1_UNORM:
std::ranges::transform(swizzle, swizzle.begin(), SwapSpecial);
break;
@@ -2106,21 +2135,21 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
if (!info.IsRenderTarget()) {
swizzle = info.Swizzle();
TryTransformSwizzleIfNeeded(format, swizzle,
!device->IsExt4444FormatsSupported());
device->MustEmulateBGR565(),
!device->IsExt4444FormatsSupported());
if ((aspect_mask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != 0) {
std::ranges::transform(swizzle, swizzle.begin(), ConvertGreenRed);
SanitizeDepthStencilSwizzle(swizzle, device->SupportsDepthStencilSwizzleOne());
}
}
const auto format_info = MaxwellToVK::SurfaceFormat(*device, FormatType::Optimal, true, format);
if (ImageUsageFlags(format_info, format) != image.UsageFlags()) {
LOG_WARNING(Render_Vulkan,
"Image view format {} has different usage flags than image format {}", format,
image.info.format);
}
const VkImageUsageFlags requested_view_usage = ImageUsageFlags(format_info, format);
const VkImageUsageFlags image_usage = image.UsageFlags();
const VkImageUsageFlags clamped_view_usage = requested_view_usage & image_usage;
const VkImageViewUsageCreateInfo image_view_usage{
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO,
.pNext = nullptr,
.usage = ImageUsageFlags(format_info, format),
.usage = clamped_view_usage,
};
const VkImageViewCreateInfo create_info{
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
@@ -2286,23 +2315,18 @@ vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_
Sampler::Sampler(TextureCacheRuntime& runtime, const Tegra::Texture::TSCEntry& tsc) {
const auto& device = runtime.device;
// Check if custom border colors are supported
const bool has_custom_border_colors = runtime.device.IsCustomBorderColorsSupported();
const bool has_format_undefined = runtime.device.IsCustomBorderColorWithoutFormatSupported();
const bool has_custom_border_extension = runtime.device.IsExtCustomBorderColorSupported();
const bool has_format_undefined =
has_custom_border_extension && runtime.device.IsCustomBorderColorWithoutFormatSupported();
const bool has_custom_border_colors =
has_format_undefined && runtime.device.IsCustomBorderColorsSupported();
const auto color = tsc.BorderColor();
// Determine border format based on available features:
// - If customBorderColorWithoutFormat is available: use VK_FORMAT_UNDEFINED (most flexible)
// - If only customBorderColors is available: use concrete format (R8G8B8A8_UNORM)
// - If neither is available: use standard border colors (handled by ConvertBorderColor)
const VkFormat border_format = has_format_undefined ? VK_FORMAT_UNDEFINED
: VK_FORMAT_R8G8B8A8_UNORM;
const VkSamplerCustomBorderColorCreateInfoEXT border_ci{
.sType = VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT,
.pNext = nullptr,
.customBorderColor = std::bit_cast<VkClearColorValue>(color),
.format = border_format,
.format = VK_FORMAT_UNDEFINED,
};
const void* pnext = nullptr;
if (has_custom_border_colors) {

Some files were not shown because too many files have changed in this diff Show More