Compare commits

...
442 Commits
Author SHA1 Message Date
Connor McLaughlinandrefractionpcsx2 1b81825218 x86/microVU: Fix typo in VI CRC
Doesn't actually affect anything, only for debugging.
2023-04-30 06:12:01 +01:00
Stenzekandrefractionpcsx2 b3e6e28827 x86/iR5900: Fast forward timeout loops 2023-04-30 04:52:50 +01:00
Stenzekandrefractionpcsx2 eaceb27879 x86/microVU: Remove redundant cmp in mVUtestCycles 2023-04-29 18:24:49 +01:00
Stenzekandrefractionpcsx2 cd9b6c7ac3 x86/microVU: Pack VF cycles into bitfields
The VF cycle count doesn't go above 4, across 32 registers that saves 64
bytes.

Also gets rid of blockhasmbit, since save states are getting invalidated
anyway, it was never used.

[SAVEVERSION+] VU struct changes.
2023-04-29 18:24:49 +01:00
TellowKrinkleandrefractionpcsx2 d3e527f2a4 GS:MTL: Always end all encoders on FlushEncoders
Previously, texture upload encoders weren't submitted if no rendering had been done, which would result in an assertion failure if the device was destroyed in that state, as the encoders would be released without calling `endEncoding` on them.
2023-04-29 17:37:24 +01:00
TellowKrinkleandrefractionpcsx2 b47fdcdfab GS: Fix crash when looking up color textures with depth lookups 2023-04-29 17:02:16 +01:00
Stenzekandrefractionpcsx2 2550ad7fd1 GS/HW: Detect clears spanning multiple sprites
Fixes GT4 rendering to >1000x1000 targets.
2023-04-29 17:01:15 +01:00
Stenzekandrefractionpcsx2 1717f584a0 GS/HW: Add flush reason to draw tracing 2023-04-29 17:01:15 +01:00
Stenzekandrefractionpcsx2 0822d3e3e5 GS/HW: Cache possible mem clear value 2023-04-29 17:01:15 +01:00
Stenzekandrefractionpcsx2 ec41af760a GS/Vulkan: Make primid not require barycentric extension 2023-04-29 16:23:09 +01:00
Stenzekandrefractionpcsx2 a5ed24ca88 Perf: Support instruction-level profiling with jitdump on Linux 2023-04-29 16:22:37 +01:00
Stenzekandrefractionpcsx2 b3697579c0 GS/Vulkan: Simplify GPU selection
Hopefully stops a crash on broken drivers.
2023-04-29 16:20:01 +01:00
JordanTheToasterandrefractionpcsx2 388da2058b GameDB: FFXII texture fixes
Fixes for broken textures on player model.
2023-04-29 08:01:59 +01:00
Stenzekandlightningterror aa9a0dca4b GS/HW: Fix HW move debug message 2023-04-28 13:34:45 +02:00
Stenzekandlightningterror 2a892da0da GS/HW: Improve split shuffle detection
Fixes transition effects in DBZ BT3 PAL.
2023-04-28 13:34:45 +02:00
Stenzekandlightningterror 9237bf9429 GS/HW: Relax PSM match requirement for move targets
Fixes broken car preview in Tokyo Xtreme Racer Zero.
2023-04-28 13:34:45 +02:00
Stenzekandlightningterror 10533dce02 GS/HW: Swap xyxy() for upld()
In theory more efficient.
2023-04-28 13:34:45 +02:00
Stenzekandlightningterror b5ebc19eff GS/HW: Don't mess with ZMSK for no_ds
Fixes broken depth in Superman Returns.
2023-04-28 13:34:45 +02:00
Stenzekandrefractionpcsx2 6535e7e43a GS: Add natvis for vector types 2023-04-28 10:22:45 +01:00
Ty Lamontagneandrefractionpcsx2 5f9473ef02 ci: Update labeler debugger directories 2023-04-28 06:15:27 +01:00
Stenzekandrefractionpcsx2 fbb1c7cb8e GS/OGL: Don't reuse targets when they're the texture
I don't trust drivers to insert a barrier here. At least one of them
gets it wrong.

Also moves the masking of depth/colour to the common renderer for
consistency.
2023-04-27 23:22:09 +01:00
lightningterror 2d97d85ca5 GS-hw: Use correct format specifier for blend log, use constants for mergesprite log. 2023-04-27 21:20:31 +02:00
Stenzekandrefractionpcsx2 ecd7d0fc35 GS/HW: Fix pipeline/shader duplication 2023-04-27 12:01:34 +01:00
Stenzekandrefractionpcsx2 0c389789f3 GS: Fix hang when switching renderer while fullscreen 2023-04-27 09:17:27 +01:00
Stenzekandrefractionpcsx2 d8239664a8 GS/Vulkan: Re-enable async presentation 2023-04-27 09:17:16 +01:00
rayanHappyandrefractionpcsx2 c06d4f477a Misc: remove unneeded file and clean up a 32bit check 2023-04-27 09:09:04 +01:00
refractionpcsx2 cdd88a6e5c GS-HW: Fix std::sort comparator for purging hash cache 2023-04-27 09:07:21 +01:00
refractionpcsx2 5a73fa2d23 GS-TC: Update dirty read overlap on local mem invalidate 2023-04-27 09:07:05 +01:00
Stenzekandrefractionpcsx2 0367851b8e GS: Make TEXFLUSH a flag instead 2023-04-26 16:00:59 +01:00
Stenzekandrefractionpcsx2 33b2f6331c GS/HW: Allow auto flush to be applied only to sprites 2023-04-26 16:00:59 +01:00
Stenzekandrefractionpcsx2 befbf57191 GS: Refactor exclusive fullscreen yet again
Also acquire render window as late as possible.
Limits the duration that the main window isn't displaying anything.
2023-04-26 16:00:39 +01:00
JordanTheToasterandrefractionpcsx2 20d040d5d1 GameDB: Disney Golf Fixes
Fixes for grass rendering to match software with mipmapping and trilinear filtering.
2023-04-26 02:07:15 +01:00
TellowKrinkleandrefractionpcsx2 06fdc75945 CMake: Properly fail on windeployqt failure 2023-04-26 02:06:58 +01:00
refractionpcsx2 ded971a3ec Build: Fix Qtdir for windows build workdflows 2023-04-25 22:57:05 +01:00
Stenzekandrefractionpcsx2 abc0f99ddd Qt: Move themes to its own file
It's getting a bit out of hand.
2023-04-25 21:53:30 +01:00
Stenzekandrefractionpcsx2 b3a88d6ea7 Qt: Migrate to 6.5.0 on Windows 2023-04-25 21:53:30 +01:00
refractionpcsx2 76014b7cb9 GS-TC: Use the expected rect to expand the target when Tex is RT. 2023-04-25 20:53:31 +01:00
Stenzekandrefractionpcsx2 0ab6eb6587 GS: Rework texture pooling behavior
- Split into texture/target pools.
 - Keep textures around when they're used recently regardless of size
   (saves work in the backend/driver).
 - Don't boot textures out of the pool when it's an idle frame.
2023-04-25 20:53:21 +01:00
Stenzekandrefractionpcsx2 a4e99366fb GS/HW: Put a cap on the hash cache count
As well as VRAM usage. Stops Corvette allocating 16,000+ textures.

Also reduce max age for hash cache sources, since they get kept around
in the latter for another 30 frames.
2023-04-25 20:53:21 +01:00
Stenzekandrefractionpcsx2 a32ab4cc97 GS: Refactor ResizeTexture() to ResizeRenderTarget() 2023-04-25 20:53:21 +01:00
JordanTheToasterandrefractionpcsx2 e7f3c42f9d GameDB: Various FIFA 2001-2004 fixes
Fixes for broken player textures and some missing fixes.
2023-04-25 20:53:05 +01:00
Ty Lamontagneandrefractionpcsx2 d76a0d7416 Debugger: Implement BC0XY branches & their condition evaluation 2023-04-25 17:28:31 +01:00
Stuart Kennyandrefractionpcsx2 79f4af8ab5 Qt: Delete SDLRawInput on non win32 builds 2023-04-25 15:05:30 +01:00
Stuart Kennyandrefractionpcsx2 a5f83329cb FullscreenUI: Only show SDL Raw on win32 builds. 2023-04-25 15:05:30 +01:00
rayanHappyandrefractionpcsx2 267479f31d Misc: Cmake and GCC compiler flags cleanups 2023-04-25 15:04:39 +01:00
rayanHappyandrefractionpcsx2 164462e510 Misc: Remove ICC compiler support 2023-04-25 15:04:39 +01:00
TellowKrinkleandrefractionpcsx2 6331df306f qt:resources: Use black and white icon for forum menu entry 2023-04-25 15:04:26 +01:00
TellowKrinkleandrefractionpcsx2 027ceebcbd qt:resources: Use black and white icons for discord menu icon 2023-04-25 15:04:26 +01:00
TellowKrinkleandrefractionpcsx2 edb2c0080c qt:resources: Use separate black/white github icon 2023-04-25 15:04:26 +01:00
TellowKrinkleandrefractionpcsx2 caafc87b29 qt:resources: Sort qrc filenames
Many filesystems (e.g. btrfs, apfs) return results in some internal non-alphabetical ordering, which isn't great for minimizing changes to files
2023-04-25 15:04:26 +01:00
TellowKrinkleandrefractionpcsx2 5d37cac4a0 qt:resources: Skip dotfiles when generating qrc 2023-04-25 15:04:26 +01:00
Stenzekandrefractionpcsx2 8f68e096d4 GS/HW: Avoid render pass restarts to turn off RT
Significantly reduces render passes in Sly 2.
2023-04-24 22:17:25 +01:00
Stenzekandrefractionpcsx2 430cad48e3 GS/Metal: Get rid of redundant pointer 2023-04-24 22:17:04 +01:00
Stenzekandrefractionpcsx2 757a9532e6 GS: Add Render Pass stats 2023-04-24 22:17:04 +01:00
KamFretoZandlightningterror f26f8cafa9 Qt: Even more fixes to the Cobalt Theme 2023-04-24 19:24:19 +02:00
KamFretoZandlightningterror 128a79e355 Qt: Help menu icon fix for macOS user 2023-04-24 19:24:19 +02:00
PCSX2 Botandlightningterror cc2d99db3a PAD: Update to latest controller database. 2023-04-24 19:21:18 +02:00
KamFretoZandrefractionpcsx2 30a31d931a Qt: Add extra icons to the help menu 2023-04-23 03:56:36 +01:00
KamFretoZandrefractionpcsx2 1c30d449bf Tools: Fix filename lookup error on the python glyph updater script 2023-04-23 03:56:36 +01:00
refractionpcsx2 dc4ce58248 VU-JIT: Avoid writeReg stealing loadReg GPR 2023-04-23 03:54:53 +01:00
Mrlinkwiiandrefractionpcsx2 dc93e861c7 GameDB: various fixes 2023-04-22 23:58:58 +01:00
refractionpcsx2 960daf27e2 GameDB: Add FullVU0SyncHack to the linter 2023-04-22 23:38:05 +01:00
Goatman13andrefractionpcsx2 844f21344d GameDB: Add patch for Michigan: Report from Hell 2023-04-22 16:55:27 +01:00
refractionpcsx2 535ad110e3 VU-JIT: Backup non cached VI before writing to it when load != write 2023-04-22 15:15:25 +01:00
JordanTheToasterandrefractionpcsx2 0e0d7a5441 GameDB: Various fixes
Fixes for vertical lines in Ring of Red and invisible text in Dynasty Warriors 2.
2023-04-22 03:03:27 +01:00
SeruranBlueandGitHub ed63221c7e GameDB: Fixes for Air Ranger: Rescue Helicopter (#8711) 2023-04-22 03:02:46 +01:00
seta-sanandrefractionpcsx2 f9c2d7767d CDVD: Fix Error Message in InputIsoFile.cpp 2023-04-21 10:53:48 +01:00
Berylskidandrefractionpcsx2 cb91478590 UI: Correct Recommended Value for Show Indicators 2023-04-20 10:18:25 +01:00
Mrlinkwiiandrefractionpcsx2 5dec7fe27d GameDB : fixes for Hanjuku Hero 4 2023-04-19 23:30:31 +01:00
BerylskidandGitHub 575d487c65 GameDB: Fix Armored Core water and game names (#8702) 2023-04-19 19:14:37 +01:00
Stenzekandrefractionpcsx2 2b9289f402 GS/HW: Fix missing init of non-CLUT replacement textures 2023-04-19 13:38:20 +01:00
Mrlinkwiiandrefractionpcsx2 9273683d3c GameDB: fixes for Dark cloud 2023-04-17 21:06:48 +01:00
PCSX2 Botandlightningterror 88f8465e7e PAD: Update to latest controller database. 2023-04-17 20:02:50 +02:00
refractionpcsx2 f26031cada Vif: Fix up Instant DMA behaviour 2023-04-16 21:15:26 +01:00
JordanTheToasterandlightningterror 3352d71515 GameDB: Various fixes
Fixes for a potential slowdown in Super Robot Taisen and replace disabling Instant VU with InstantDMA in MGS 3 Subsistence.
2023-04-16 21:10:31 +02:00
Connor McLaughlinandrefractionpcsx2 999f9532ee GS: Warning fix 2023-04-16 06:43:22 +01:00
Stenzekandrefractionpcsx2 d1f62ca9bf GS: Remove GSVertexList
It doesn't appear to be used anywhere.
2023-04-16 06:35:05 +01:00
Stenzekandrefractionpcsx2 ef9f0cf635 GS: Replace magic alignment number with constant
And ensure it gets used in None preloading.
2023-04-16 06:35:05 +01:00
Stenzekandrefractionpcsx2 d745564451 GS/HW: Adjust Black/Burnout sky CRC hack
Apparently some stages use a sky height of 128 instead of 256?
2023-04-15 22:01:38 +01:00
Stenzekandrefractionpcsx2 d37ac992fc GS/HW: Use bitfield extract for VS expand (GL/VK) 2023-04-15 20:10:25 +01:00
Stenzekandrefractionpcsx2 e7fc3de90c GS/HW: Ensure region texture mipmaps don't go out of bounds 2023-04-15 20:10:15 +01:00
Stenzekandrefractionpcsx2 bde81380c3 GS/SW: Stop C rasterizer crashing with AA1 2023-04-15 20:10:03 +01:00
Stenzekandrefractionpcsx2 839b482cb5 GS: Use 16-bit indices instead of 32-bit
Save some bandwidth.
2023-04-15 20:10:03 +01:00
Stenzekandrefractionpcsx2 72f70d4789 GS/Vulkan: Clear textures/RTs at end of frame
Prevents us from updating potentially changed-state descriptors.
2023-04-15 20:09:48 +01:00
Stenzekandrefractionpcsx2 d646bbf5c1 GS/Vulkan: Prioritize VK_EXT_rasterization_order_attachment_access
.. over the ARM version. But continue to support both.
2023-04-15 20:09:48 +01:00
Stenzekandrefractionpcsx2 e68aaf6540 GS/Vulkan: Saturate ImGui scissor to zero 2023-04-15 20:09:48 +01:00
Stenzekandrefractionpcsx2 20ab5ed0fa GS/Vulkan: Don't assume opaque composite alpha is supported 2023-04-15 20:09:48 +01:00
Stenzekandrefractionpcsx2 8590e390a2 GS/Vulkan: Don't enable geometryShader 2023-04-15 20:09:48 +01:00
Stenzekandrefractionpcsx2 ab1d558420 GS/Vulkan: Make provoking vertex consistent across pipelines 2023-04-15 20:09:48 +01:00
Stenzekandrefractionpcsx2 53c9021455 GS/HW: Don't attempt to colour copy into depth target 2023-04-15 20:09:26 +01:00
Stenzekandrefractionpcsx2 8bd00e2433 GS: Remove unused scissor variables 2023-04-15 18:01:52 +01:00
Stenzekandrefractionpcsx2 c045feae50 GS/HW: Skip draws on reset until scissor is set 2023-04-15 18:01:52 +01:00
Stenzekandrefractionpcsx2 7531080e51 GS/HW: Only force shader sampling for non-32bit targets
Not sources.
2023-04-15 17:37:34 +01:00
TellowKrinkleandrefractionpcsx2 bf57ab3e39 GS:OGL: Support vs expand on older GL with SSBO extension 2023-04-15 04:29:10 +01:00
JordanTheToasterandrefractionpcsx2 dfcb96a4b6 GameDB: Various fixes
Fixes for bloom alignment in Dogz and Catz and broken sun in Ace Combat 4.
2023-04-14 23:01:26 +01:00
refractionpcsx2 5c4fad6725 GameDB: Remove no longer needed Spyro patches 2023-04-14 18:17:44 +01:00
refractionpcsx2 988b1ad03b SPU2: Don't make end IRQ positions inclusive 2023-04-14 18:17:44 +01:00
refractionpcsx2 79705a2514 SPU2: Increase maximum ADSR rate from 0x3FFF to 0x4000 2023-04-14 18:17:44 +01:00
JordanTheToasterandrefractionpcsx2 0919b15183 GameDB: Various fixes
Fixes for Dogz and Catz vertical lines and black squares and a workaround for FMVs causing screen shaking in NFS U2.
2023-04-14 13:13:35 +01:00
kenshen112andrefractionpcsx2 8162c87884 GameIndex: Added Boss Hang Fix to more regions.
Added Kirie hang fix to Fatal Frame Korea and Asia.
2023-04-14 09:23:35 +01:00
Stuart Kennyandrefractionpcsx2 09394ee4b7 Qt: Hide SDL Raw option on non win32 builds 2023-04-13 12:14:15 +01:00
Stenzekandrefractionpcsx2 7f7dd60587 GS/HW: VS expand instead of GS for DX/GL/Vulkan 2023-04-13 11:12:11 +01:00
Stenzekandrefractionpcsx2 6877abb2ec GS/HW: Remove FFXII CRC hack
No longer needed, and it causes issues with splitting point draws.
2023-04-13 11:12:11 +01:00
Stenzekandrefractionpcsx2 ce5dd88790 GS/OGL: Fix GL error on shutdown 2023-04-13 11:12:11 +01:00
Stenzekandrefractionpcsx2 5bc9d625e7 GL/StreamBuffer: Align CPU side fallback buffers 2023-04-13 11:12:11 +01:00
Connor McLaughlinandrefractionpcsx2 1d7a69ad40 AppImage: Include libxcb-cursor 2023-04-13 10:51:09 +01:00
JordanTheToasterandrefractionpcsx2 f7d87076a3 Qt: Adjust MTVU core count text
The wording here was causing confusion and unneeded arguments over what it actually means.
2023-04-13 09:39:02 +01:00
JordanTheToasterandrefractionpcsx2 9d20b4d6a6 GameDB: Soulcalibur 2&3 blending recommendations
Fixes menu transparency when using high blending.
2023-04-13 09:39:02 +01:00
TellowKrinkleandrefractionpcsx2 128cf9b57d 3rdparty:macOS: Update to Qt 6.4.3
Gives us 5 more months to decide whether we want to use 6.2 LTS or drop macOS 10.14 and macOS 10.15 support
2023-04-13 08:27:49 +01:00
TellowKrinkleandrefractionpcsx2 e5b7adb228 3rdparty:linux: Update to Qt 6.5.0 2023-04-13 08:27:49 +01:00
TellowKrinkleandrefractionpcsx2 bd5ae66fbe 3rdparty: Update SDL to 2.26.5 2023-04-13 08:27:49 +01:00
Romain Tisserandandrefractionpcsx2 a3af4155f8 3rdparty: Bump libchdr to support raw DVD ISO as CHD 2023-04-12 09:37:46 +01:00
refractionpcsx2 1ec83dc790 SPU2: Fix savestate loading setting incorrect variable 2023-04-11 18:45:27 +01:00
Stenzekandrefractionpcsx2 f26cc38b80 SPU2: Store DMA pointers as offsets in save state
[SAVEVERSION+] Sadly need to bump save state, don't want to have a mess
of different version handling here.
2023-04-11 15:30:54 +01:00
lightningterror d9f537e9dc GS-hw: Fix Wsign-compare warning. 2023-04-11 01:06:15 +02:00
PCSX2 Botandlightningterror 94c75df0d0 PAD: Update to latest controller database. 2023-04-10 20:35:28 +02:00
Stenzekandrefractionpcsx2 423a8884e8 GS/Vulkan: Don't try to render out of bounds in Interlace() 2023-04-10 16:51:01 +01:00
Stenzekandrefractionpcsx2 1f26502c64 GS/HW: Always convert float depth to integer on readback
Even if it's been reinterpreted as a colour format.
2023-04-10 16:51:01 +01:00
dependabot[bot]andlightningterror f61f7bb711 Bump peter-evans/create-pull-request from 4 to 5
Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 4 to 5.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](https://github.com/peter-evans/create-pull-request/compare/v4...v5)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-10 16:13:04 +02:00
KamFretoZandrefractionpcsx2 971acd3fdb Qt: Fills in the settings help description fields 2023-04-09 19:13:09 +01:00
JordanTheToasterandrefractionpcsx2 bba070bdbf GameDB: PAL ZoE 2 Text fix
Fixes cut off text in PAL versions of Zone of the Enders 2
2023-04-09 19:12:56 +01:00
Connor McLaughlinandrefractionpcsx2 6c4152a7e0 GS/HW: Update 32-bit flag for depth buffers too
Jackie Chan Adventures re-uses a previous C32 target pointer as a Z16S
depth buffer, but it does clear it inbetween. So we need to remove the
32-bit flag on the clear.
2023-04-09 17:56:49 +01:00
Stenzekandrefractionpcsx2 f569ad0970 GS/HW: Allow translating targets for depth sources
Fixes broken half screen in Miami Vice and 10 Pin - Champions Alley.
2023-04-09 17:56:49 +01:00
Stenzekandrefractionpcsx2 f16a291412 GS/HW: Adjust TextureMinMax end coordinate when point sampling 2023-04-09 17:56:49 +01:00
refractionpcsx2 e0cfa2dff3 EE/COP2: Increase likely clear sync 2023-04-09 17:23:09 +01:00
Stenzekandrefractionpcsx2 bf9d087e74 GS/HW: Adjust Burnout CRC to fully skip broken post effect 2023-04-09 16:28:57 +01:00
JordanTheToasterandrefractionpcsx2 b245dd55d6 Github: Change emu bug report template
Missed when changing the other template.
2023-04-09 16:26:23 +01:00
JordanTheToasterandrefractionpcsx2 1e3f429169 GameDB: Various fixes
Alieviates high VU % usage in Pilot Down Behind Enemy Lines and sets max blending level to minimum for other Monster Hunter games to fix heavy GPU usage for no reason.
2023-04-09 16:26:23 +01:00
refractionpcsx2 8d429c7e5a GameDB: Update the VU clamp mode on Ultimate Spider-Man 2023-04-09 16:24:46 +01:00
Stenzekandrefractionpcsx2 b9be3ad3b8 GS/HW: Tiny optimization in source lookup
Don't want to do divides per-target.
2023-04-09 06:01:54 +01:00
refractionpcsx2 3099090e6a GameDB: Add InstantDMA to Jak 3 for holes in face geometry 2023-04-09 05:56:58 +01:00
refractionpcsx2 5e27c65615 EE/COP2: Check for likely zero clears in COP2 synced ops 2023-04-09 05:55:15 +01:00
refractionpcsx2 8b32382e1b GameDB: Add Autoflush and HPO Special to Ultimate Spider-Man 2023-04-09 03:31:41 +01:00
arcum42andrefractionpcsx2 60047e8029 common: Remove some unneeded includes. 2023-04-08 20:26:39 +01:00
arcum42andrefractionpcsx2 e37fff1213 common: Remove SafeList and SafeAllignedArray as unused. 2023-04-08 20:26:39 +01:00
JordanTheToasterandrefractionpcsx2 64a6d8027b GS: Reset performance counters on renderer switch
Resets performance counters on renderer switch.
2023-04-08 13:37:21 +01:00
Stenzekandrefractionpcsx2 cd4434135e GSRunner: Don't skip dumps with dots in their filename 2023-04-08 13:36:45 +01:00
Stenzekandrefractionpcsx2 747e11d7dd GS/HW: Allow region targets for half-right fix 2023-04-08 12:44:33 +01:00
Stenzekandlightningterror 3cae728aba Qt: Recreate new window immediately when switching APIs 2023-04-08 12:42:34 +02:00
Stenzekandrefractionpcsx2 7f24a5cf82 GS: Fix crash when resizing window 2023-04-08 04:05:45 +01:00
refractionpcsx2 1b8f5f232a GS-HW: Fix bug with looping invalidation 2023-04-08 00:08:08 +01:00
refractionpcsx2 77d37de18c GameDB: Add mipmapping to Hasbro Family Game Night 2023-04-07 20:34:03 +01:00
Mrlinkwiiandrefractionpcsx2 5ea3fb8e1e Github: Update issue template 2023-04-07 19:52:50 +01:00
refractionpcsx2 d683aa43d8 GS: Clean up Host->Local code 2023-04-07 17:18:33 +01:00
refractionpcsx2 d4c3501bb8 GS: Retool downloads to buffer full read 2023-04-07 17:18:33 +01:00
Stenzekandrefractionpcsx2 f2229a0007 GS/OGL: Don't leak shader objects when compiling 2023-04-07 17:18:21 +01:00
Stenzekandrefractionpcsx2 2a06bb6e2c GS/OGL: Use VS/GS selectors from base class 2023-04-07 17:18:21 +01:00
lightningterror a06f890ab9 GS: Fix Wunused-variable warning. 2023-04-07 01:26:00 +02:00
refractionpcsx2 bbe22f95d1 GS: Avoid modifying single QW downloads as they go to a register
Also avoid downloading more than requested
2023-04-06 23:26:59 +01:00
Stenzekandrefractionpcsx2 631f75a79c GS/HW: Don't break out of target search loop on dirty target 2023-04-06 14:28:19 +01:00
Stenzekandrefractionpcsx2 c121aae8f1 GS: Add VS natvis files for FastList and TC Targets 2023-04-06 14:27:36 +01:00
refractionpcsx2 fed7629632 GS: Fix typo in ResizeTexture which was causing a crash 2023-04-06 14:27:08 +01:00
Stenzekandrefractionpcsx2 0825ca736f GS/HW: Add other StretchRect() calls to texture copies counter
Better reflects GPU work.
2023-04-06 14:20:20 +01:00
Stenzekandrefractionpcsx2 660974c9d1 GS/HW: Update target in new format when reinterpreting
Fixes block scrambling in Budokai 3 during screen transitions.
2023-04-06 14:20:20 +01:00
Stenzekandrefractionpcsx2 4404b06d2a Qt: Fix lockup when cancelling shutdown and fullscreen 2023-04-06 08:48:07 +01:00
Stenzekandrefractionpcsx2 daef69099b Qt: Fix improper shutdown with CTRL+C 2023-04-06 08:48:07 +01:00
Stenzekandrefractionpcsx2 6362994fd8 GS: Default to Vulkan for suitable GPUs on Linux 2023-04-06 08:48:07 +01:00
Stenzekandrefractionpcsx2 398cf43782 GS: Combine HostDisplay with GSDevice
GS/DX11: Don't throw bad_alloc on surface creation fail

GS: Link device and host display construction/destruction

FullscreenUI: Replace HostDisplayTexture with GSTexture

GS: Purge HostDisplayTexture

GS: Move everything in HostDisplay to GSDevice

GS: Move ImGui rendering to GSDevice

GS: Get rid of reset/store API state
2023-04-06 08:48:07 +01:00
refractionpcsx2 77f8a0f5f6 Counters: Retool UpdateVSyncRate 2023-04-06 08:47:35 +01:00
lightningterror d7e54ccbed CDVD: Fix struct member variables not used.
Codacy.
2023-04-05 20:15:18 +02:00
lightningterror 53a8855696 INISettingsInterface: Fix scope of variable warning.
Codacy.
2023-04-05 20:15:18 +02:00
lightningterror bd16ed1340 iR5900: Fix scope of variable warning.
Codacy.
2023-04-05 20:15:18 +02:00
lightningterror dd365fe334 GS-hw/tc: Fix Wsign-compare warnings. 2023-04-05 20:15:18 +02:00
refractionpcsx2 2a6ba739bc GS-HW: Fix stretch rects errantly discarding data 2023-04-05 16:29:36 +01:00
refractionpcsx2 a863466f70 GS-HW: Better handle double half clears + masked channels + invalidate
Also add Auto Flush to Power Drome US, apparently it wasn't there.
2023-04-05 16:29:36 +01:00
refractionpcsx2 32f07f4aae GS-HW: Read back TC on GS CSR Reset 2023-04-05 16:29:36 +01:00
refractionpcsx2 3ed0e010be GS-TC: Improve handing of wrapping targets in tex in rt 2023-04-05 16:29:36 +01:00
GiladNirandrefractionpcsx2 fb3c0c8138 GameDB: Added fixes for Fatal Frame and Siren 2023-04-05 15:10:48 +01:00
Stenzekandrefractionpcsx2 58ded2e0d0 GS/HW: Fix incorrect hashing of non-palette textures 2023-04-05 15:01:42 +01:00
Stenzekandrefractionpcsx2 369b9a4808 Misc: Fix up a few recent clang warnings 2023-04-05 12:43:45 +01:00
Stenzekandrefractionpcsx2 0bd57986a9 GS/HW: Don't try to use forced trilinear on shuffles 2023-04-05 12:43:45 +01:00
refractionpcsx2 559b88438b GS: Fix some Scanmask situations in PCRTC 2023-04-04 17:33:32 +01:00
refractionpcsx2 5d140f7db3 GS: Fix missing PSM references. 2023-04-04 17:32:59 +01:00
Stenzekandrefractionpcsx2 7b512ce296 GS/HW: Fix Final Fantasy XII CRC hack 2023-04-04 17:27:57 +01:00
refractionpcsx2 ada291c0f6 GS: Remove redundant PSM enum naming 2023-04-04 13:56:44 +01:00
refractionpcsx2 857cb36707 GS-HW: Add CRC hack for NFS Undercover to handle weird shuffle 2023-04-04 13:56:44 +01:00
refractionpcsx2 4a702e0585 EE: Clear reset required status on JIT overflow reset 2023-04-04 11:16:31 +01:00
refractionpcsx2 eac420f205 GameDB: Replace Tex in RT with Partial Target Invalidation, Dark Cloud 2 2023-04-03 21:54:31 +01:00
TellowKrinkleandrefractionpcsx2 23d4fa9d9e GS:MTL: Process uv in place
The separate uv_out made it easy to make mistakes, especially when copying code from other renderers
2023-04-03 20:21:15 +01:00
From: TellowKrinkleandrefractionpcsx2 f6523f34d8 GS:MTL: Implement region rect 2023-04-03 20:21:15 +01:00
TellowKrinkleandrefractionpcsx2 82971d3ef7 GS:MTL: Test and sample depth should be supported
Untested, but we restart the render pass if it's detected, which should be accurate, even if it's not the most efficient.
2023-04-03 20:21:15 +01:00
PCSX2 Botandlightningterror 8d9a5111a1 PAD: Update to latest controller database. 2023-04-03 18:10:16 +02:00
Stenzekandrefractionpcsx2 e8dac0051c GS: Move expanded dither storage to software renderer
Hardware doesn't use it.
2023-04-03 14:19:46 +01:00
Stenzekandrefractionpcsx2 72802aa125 GS/HW: Move channel shuffle test to top of Draw() 2023-04-03 14:19:46 +01:00
Stenzekandrefractionpcsx2 f77a5c23fc GS/HW: Get rid of GSFrameInfo 2023-04-03 14:19:46 +01:00
Stenzekandrefractionpcsx2 cf772fcdd6 GS: Reuse backup environment instead of copying 2023-04-03 14:19:46 +01:00
Stenzekandrefractionpcsx2 4313c64d9d GS: Remove unused offsets (tex/fzb) 2023-04-03 14:19:46 +01:00
refractionpcsx2 38bf916231 GS: Update fixes for Sacred Blaze 2023-04-02 19:44:11 +01:00
refractionpcsx2 cf59c0b854 GS/Counters: Catch SMODE changes and update VSync rate 2023-04-02 16:19:11 +01:00
refractionpcsx2 10e192deed GS/Counters: Use progressive check, not GSSetCRT for interlace mode 2023-04-02 16:19:11 +01:00
refractionpcsx2andlightningterror b3fb6e7822 GS: Don't reset CRT mode on reset 2023-04-02 13:11:27 +02:00
Stenzekandlightningterror 3f640ed7eb GS/HW: Fix blue screen in GT4 transitions 2023-04-02 13:10:08 +02:00
Stenzekandrefractionpcsx2 cc814585ee GS/OGL: Fix incorrect binding in multi stretch rect 2023-04-02 04:29:56 +01:00
refractionpcsx2 b0d26c8242 EE: Correct FPU_MUL_HACK result value 2023-04-02 04:09:47 +01:00
Stuart Kennyandrefractionpcsx2 4133be28c6 USB: Remove force feedback logspam 2023-04-02 01:56:00 +01:00
JordanTheToasterandrefractionpcsx2 6e81879436 GameDB: Various fixes
Fixes for Driv3r and VP2.
2023-04-01 23:45:10 +01:00
refractionpcsx2 5ea670ece4 GS-HW: Handle triangle memory clears 2023-04-01 16:47:29 +01:00
Stenzekandrefractionpcsx2 e8e9702d7e GS/HW: Swap Crash WoC CRC hack for native palette draws 2023-04-01 15:45:14 +01:00
Stenzekandrefractionpcsx2 4cbdbaabdb GS/HW: Add NativePaletteDraw upscaling fix 2023-04-01 15:45:14 +01:00
Stenzekandrefractionpcsx2 f332d4f880 GS/HW: Set no_ds if Z tests are disabled and masked 2023-04-01 15:45:14 +01:00
Stenzekandrefractionpcsx2 5ce418cdaf GS/HW: Set m_channel_shuffle if late tests succeed 2023-04-01 15:45:14 +01:00
Stenzekandrefractionpcsx2 81ab2b9cd1 GS/HW: Minor texture cache cleanups 2023-04-01 15:45:14 +01:00
Stenzekandrefractionpcsx2 c441d76b7b GS/HW: Fix some asserts tripping in debug builds 2023-04-01 15:45:14 +01:00
Stenzekandrefractionpcsx2 fcbc027abc GS: Unify D3D device creation paths
Also makes Vulkan the device for Intel Arc GPUs.
2023-04-01 14:15:18 +01:00
Stenzekandrefractionpcsx2 8989b69ce8 GS: Fix crash on shutdown when using software renderer 2023-04-01 14:14:19 +01:00
Stenzekandrefractionpcsx2 e9a624ab54 Qt: Fix main window closing on fullscreen shutdown 2023-04-01 14:14:00 +01:00
Stuart Kennyandrefractionpcsx2 8a9df89bf6 SDLInputSource: SDL raw input as config option. 2023-04-01 02:32:01 +01:00
JordanTheToasterandrefractionpcsx2 e95d75e01f GameDB: Fix missing Tekken 5 demo
Fixes for missing Tekken 5 demo that caused camera issues.
2023-04-01 01:44:17 +01:00
Mrlinkwiiandrefractionpcsx2 bbe58b07a8 GameDB: fixes for Super Trucks Racing 2023-03-31 21:29:46 +01:00
tangomike99andrefractionpcsx2 7886c9ea27 GameDB: Fix fog line in Over the Hedge 2023-03-31 21:29:34 +01:00
tangomike99andrefractionpcsx2 1c072f38bb GameDB: Fix blurriness in Sitting Ducks 2023-03-31 21:29:34 +01:00
KamFretoZandrefractionpcsx2 6c2bbdef1f Qt: Theme Polishes for Pizza and Cobalt 2023-03-31 20:16:33 +01:00
Stenzekandrefractionpcsx2 a5ebb388a0 CMake: Enable RAIntegration on Windows builds 2023-03-31 15:46:33 +01:00
Buzzardsoulandrefractionpcsx2 9c91c700ac GameDB: Add roundsprite 2 to Samurai Warriors 2 2023-03-31 11:59:44 +01:00
Stenzekandrefractionpcsx2 28b111b669 x86/iFPU: Inline FPU_MUL_HACK to dynarec
Fixes Tales of Destiny crashing on clang builds (clang was using r8,
which was allocated by a caller, msvc was not).
2023-03-31 11:39:46 +01:00
Stenzekandrefractionpcsx2 1be6e1f374 Misc: Fix a bunch of warnings 2023-03-31 11:39:46 +01:00
Stenzekandrefractionpcsx2 fff8592b4e GS/HW: Fix GT4/T5 CRC hacks in DirectX renderers 2023-03-31 11:24:31 +01:00
lightningterrorandrefractionpcsx2 4af3856d15 GS: Bump shader cache version. 2023-03-31 10:18:27 +01:00
lightningterrorandrefractionpcsx2 8a06fb1840 GS: Fix fxaa bad shader on opengl. 2023-03-31 10:18:27 +01:00
Stuart Kennyandrefractionpcsx2 e2e2ab62f4 MSBuild: Enable DirectX in cmake SDL build 2023-03-31 10:12:14 +01:00
Ty Lamontagneandrefractionpcsx2 e7e3f30fce 3rdparty: Update SDL2 2023-03-31 02:06:32 +01:00
Stenzekandrefractionpcsx2 affc45e752 GSDumpReplayer: Fix crash when downloading Z24 targets
e.g. Lego Racers 2
2023-03-30 21:55:50 +01:00
Stenzekandrefractionpcsx2 d70334ee57 GS/HW: Slight shader simplification
- Don't declare texture if it's not read from. Stops Vulkan validation
   layers whinging.

 - Get rid of OpenGL common_header.glsl, and use name linking instead of
   leftovers from separate shader objects.
2023-03-30 21:55:50 +01:00
Stenzekandrefractionpcsx2 1c600c7068 GS/HW: Remove m_used from SourceMap
Not used anymore, since we don't age the TC when there's no draws.
2023-03-30 21:55:50 +01:00
Stenzekandrefractionpcsx2 7a93f1fc23 GS/HW: Remove KOF2002/SVCChaos CRC hacks
10 Pin - Champions Alley needs texture-inside-RT in LookupDepthSource(),
but otherwise nothing else appears to break if we fall back to normal
lookup for Z sources.

Relaxes the page alignment requirement for split texture shuffle
detection, Psi-Ops does an A->A copy with coordinates offset by +8.
2023-03-30 21:55:50 +01:00
Stenzekandrefractionpcsx2 9c2f7aeb6a GS/HW: Get rid of reset-32bits-fmt flag hack
Doesn't appear to be needed anymore.
2023-03-30 21:55:50 +01:00
Stenzekandrefractionpcsx2 8af2d17d1f GS/HW: Cache target widths as well as heights
Avoids redundant resizes.

Also align widths to page sizes, like heights.
2023-03-30 21:55:50 +01:00
Stenzekandrefractionpcsx2 65d78eff57 GS/HW: Sample depth buffer instead copying when safe
OpenGL and Vulkan only.
2023-03-30 21:55:50 +01:00
Stenzekandrefractionpcsx2 8be9e2dc71 GameDB: Remove preload/CPU FB for Crash WoC
Fog effect works correctly now (at least at 1x).
2023-03-30 21:55:50 +01:00
Stenzekandrefractionpcsx2 faecc6913b GS/HW: Texture cache improvements
GS/HW: Only use temporary source for recursive draw

.. and don't insert it into the page map.

GS/HW: Lookup page list for depth sources

GS/HW: Avoid target copies by using shader sampling

GS/HW: Make texture cache a global pointer

GS/HW: Remove GetID() from GSTexture

It only made sense for OpenGL, was always zero in Vulkan.

GS/HW: Rewrite texture sampling hazard detection

Also avoid redundant channel shuffle setup.

GS/HW: Turn Haunting Ground CRC into an OI fix
2023-03-30 21:55:50 +01:00
Stenzekandrefractionpcsx2 ed90c8868f GS/HW: Don't leave ZBUF_TEX0 partially uninitialized 2023-03-30 21:55:50 +01:00
Stenzekandrefractionpcsx2 71edce43ca GS/HW: Fix incorrect condition for continuing channel shuffle 2023-03-30 21:55:50 +01:00
Stenzekandrefractionpcsx2 4e9ef34f58 GS/HW: Fix incorrect end block computation in Overlaps() 2023-03-30 21:55:50 +01:00
Stenzekandrefractionpcsx2 de55596926 GS/Vulkan: Include source code in shader debug info 2023-03-30 21:55:50 +01:00
JordanTheToasterandrefractionpcsx2 316bc422bc GameDB: Various fixes
Fixes lack of sun intensity in WRC texture distortion in Ultimate Spiderman and missing serials and fixes for those serials for Sakura Taisen.
2023-03-30 20:40:03 +01:00
Stenzekandrefractionpcsx2 c73ae3dfb3 x86/iR5900: Get rid of eeRecIsReset
It was preventing the rec being reset inbetween launching different games.
2023-03-30 19:45:11 +01:00
Stenzekandrefractionpcsx2 27b45276ae SPU2: Remove GetLongName() from SndOutModule
Unused since WX.
2023-03-30 16:55:17 +01:00
JordanTheToasterandrefractionpcsx2 b00852fada GameDB: More WWE text fixes
Adds the text fix to WWE 2007 to 2010
2023-03-30 11:03:29 +01:00
refractionpcsx2 663f61f4e1 GS-TC: only escape Local Mem Invalidate early on exact BP match 2023-03-30 11:03:10 +01:00
refractionpcsx2 110bc64ee4 GS-TC: Fix up page translation logic, clean up variables 2023-03-30 11:03:10 +01:00
refractionpcsx2 3764e773b3 GS-HW: Check what channel is being read during a possible split shuffle 2023-03-30 11:03:01 +01:00
icup321andrefractionpcsx2 682f0c7984 GameDB: Add Mipmap/Trilinear to SpongeBob Movie & Incredibles
Update settings for The Incredibles + ROTU and The SpongeBob Movie Game
2023-03-30 09:46:43 +01:00
JordanTheToasterandrefractionpcsx2 93014bfede CI: Switch Windows Qt builds to Clang
Switches the Qt builds over to using Clang by default which should be a bit faster overall.
2023-03-30 09:27:10 +01:00
JordanTheToasterandTellowKrinkle 4dd946bc8a CI: Remove separate Windows builds
Removes the AVX2 and SSE4 builds in favour of the unified Qt build.
2023-03-29 20:00:51 -05:00
JordanTheToasterandrefractionpcsx2 2222007516 GameDB: WWE 2011 Text fixes
Fixes for the broken text in WWE 2011.
2023-03-29 17:28:55 +01:00
refractionpcsx2 b09e3b0613 GS: Split ModXY in to its own function 2023-03-29 17:08:41 +01:00
refractionpcsx2 3a193956ff GS: Provide HPO Normal offsets when there is no RT. 2023-03-29 17:08:41 +01:00
Mrlinkwiiandrefractionpcsx2 786eedf2f2 GameDB: fixes for various games 2023-03-29 15:18:16 +01:00
Stuart Kennyandrefractionpcsx2 f217519e97 GameDB: Fix WRC 4 car discolouration 2023-03-29 11:50:13 +01:00
Buzzardsoulandrefractionpcsx2 4caaa70726 GameDB: Add Mipmap and Trilinear to The Incredibles 2023-03-28 21:54:57 +01:00
JordanTheToasterandlightningterror 02a27a6974 GameDB: Rogue Galaxy character fix
Fixes broken characters in Rogue Galaxy.
2023-03-28 19:52:17 +02:00
Stenzekandrefractionpcsx2 6d7eceb4f1 GS/HW: Remove JakGames/JakX CRC hack 2023-03-28 11:21:47 +01:00
Stenzekandrefractionpcsx2 f52e72b026 GS/HW: Swap OI_JakGames CRC hack for CPU sprite render 2023-03-28 11:21:47 +01:00
Stenzekandrefractionpcsx2 ebeb646e4d GS/HW: Relax CPU sprite render requirements further via levels 2023-03-28 11:21:47 +01:00
refractionpcsx2 70c1620a87 GameDB: Add Partial Target Invalidation for Fatal Frame III
aka Project Zero 3
2023-03-28 11:09:44 +01:00
refractionpcsx2 d45964d0c7 GS-HW: improve dirty handling with expanded tex is rt's 2023-03-28 11:09:44 +01:00
refractionpcsx2 e67aa73e75 GS-HW: Round up rect for hardware draws 2023-03-28 11:09:44 +01:00
refractionpcsx2 cb2fe3792a GS-HW: Resize RT used as larger source 2023-03-28 11:09:44 +01:00
Stenzekandlightningterror 2b94cfe782 GS/HW: Allow strip channel shuffles to be detected
Fixes fog wall in WRC 4.
2023-03-27 18:29:01 +02:00
PCSX2 Botandlightningterror a1c99f3e7a PAD: Update to latest controller database. 2023-03-27 18:28:13 +02:00
Stenzekandrefractionpcsx2 57fa3ac653 ChdFileReader: Prefer using TOC for file size over header
The header is incorrect, and pads each track to 4 frames.
2023-03-27 10:21:10 +01:00
refractionpcsx2 01b6e1b88d CDVD: Add missing TOC information 2023-03-27 10:21:10 +01:00
refractionpcsx2 294aca82c4 GS-TC: Give option to match target on exact memory addresses
Chances of it being the wrong thing but having the same start/end address is pretty slim. Hopefully
2023-03-26 22:28:23 +01:00
refractionpcsx2 d080e7e7bd VTLB: Show rough EE PC when a TLB miss happens 2023-03-26 22:14:28 +01:00
refractionpcsx2 66a13d4c3a GS-TC: Only stop checking for RT's if whole read is inside that RT. 2023-03-26 15:28:14 +01:00
JordanTheToasterandrefractionpcsx2 87c76ad010 GameDB: Various fixes
Helps alleviate some issues in Shrek 2 and removes round sprite and merge sprite from Driv3r as they cause issues
2023-03-25 06:16:25 +00:00
Dreadmothandrefractionpcsx2 822d292e2f GameDB: Ratchet & Clank 1&2
Fixes broken pause menu.
2023-03-25 06:06:24 +00:00
KamFretoZandGitHub 42155dd11b Qt: Add a New Light Theme and Cobalt Theme Fix (#8471) 2023-03-24 12:03:05 +00:00
Stenzekandrefractionpcsx2 9b1a2d9eaf GS/DX11: Fix incorrect UBO for P8 conversion 2023-03-24 11:43:51 +00:00
TellowKrinkleandTellowKrinkle 8d0307cedd UI: Fix build with achievements disabled 2023-03-23 23:48:40 -05:00
refractionpcsx2 72b38ce712 CDVD: Don't auto mount disc again if game ejects it. 2023-03-23 20:40:45 +00:00
refractionpcsx2 caf8eedd76 CDVD: Correct SCMD error states and init SCMD result 2023-03-23 20:40:45 +00:00
refractionpcsx2 181b05daf0 CDVD: Don't let it try to close the tray if it isn't open 2023-03-23 20:40:45 +00:00
refractionpcsx2 92b21ac9c2 CDVD: Correct status sequence during disc swap. 2023-03-23 20:40:45 +00:00
BerylskidandGitHub ad12a3f735 UI: Correct Recommended Values for a few items (#8465) 2023-03-22 13:25:31 +00:00
Stenzekandrefractionpcsx2 badca7c20b GS/HW: Fix texture replacement precaching option 2023-03-22 10:03:31 +00:00
Stenzekandrefractionpcsx2 7cdcfd4b1a Qt: Remove backup AppImage on next launch 2023-03-21 13:48:50 +00:00
Stenzekandrefractionpcsx2 b02af117f8 CMake: Swap -g for -g1 in Linux Release builds
-g tends to blow the AppImage sizes up a bit too much...
2023-03-21 13:48:16 +00:00
Stenzekandrefractionpcsx2 87d269512e GS/HW: Compiler warning fixes 2023-03-21 13:15:31 +00:00
Stenzekandrefractionpcsx2 3346349bba GS: Remove GSDeviceNull
It hasn't been used in a while, we just use a normal device
and null renderer instead.
2023-03-21 13:15:31 +00:00
Mrlinkwiiandrefractionpcsx2 280a41806f GameDB: fixes for Metal Gear Solid 3 Snake Eater 2023-03-20 21:27:03 +00:00
Ikko Eltociear Ashimineandrefractionpcsx2 134937082d Counters: fix typo
recieve -> receive
2023-03-20 15:46:56 +00:00
Stenzekandrefractionpcsx2 1499994143 CI: Update Linux to Qt 6.4.3 and SDL2 2.26.4 2023-03-20 15:46:32 +00:00
Stenzekandrefractionpcsx2 5805142fd7 CrashHandler: Print backtrace on Linux 2023-03-20 15:46:32 +00:00
Stenzekandrefractionpcsx2 5fc855e519 CMake: Add libbacktrace module 2023-03-20 15:46:32 +00:00
Stenzekandrefractionpcsx2 8c8bf22892 CI: Build libbacktrace in Linux deps 2023-03-20 15:46:32 +00:00
Stenzekandrefractionpcsx2 ec927e5dd9 CMake: Force debug symbols in Linux Release builds 2023-03-20 15:46:32 +00:00
refractionpcsx2 3a042d8c14 GS: Compensate for misaligned 24bit partial local->host transfers 2023-03-20 14:35:31 +00:00
JordanTheToasterandrefractionpcsx2 fc88d1de85 GameDB: From Soft game fixes
Adds partial target invalidation to every From Soft game because they used way too much glue.
2023-03-20 11:19:49 +00:00
JordanTheToasterandrefractionpcsx2 6cf48e9e2b GameDB: Various fixes
Fixes R&C 3 broken pause menu and broken textures in AC Last Raven.
2023-03-20 10:05:00 +00:00
refractionpcsx2 db22377a0d GS: Remove ExpandTarget on EE Write 2023-03-19 23:32:17 +00:00
Silentandrefractionpcsx2 443cc08229 VMManager: Fix "X widescreen patches loaded" text when loading from files 2023-03-19 23:31:52 +00:00
Stenzekandrefractionpcsx2 6ad222117d GS: Reduce MAD buffering draw size
It's silly to draw to the whole double-sized render target, but discard
half the pixels.

Also centralizes the constant setup, get rid of the duplication.
2023-03-19 23:31:37 +00:00
Stenzekandrefractionpcsx2 b26acad721 GS: Sample LOD 0 explicitly in interlace shaders
Can't use normal sampling because the derivates are undefined in
non-uniform control flow (in MAD).
2023-03-19 23:31:37 +00:00
refractionpcsx2 76e8bfe42f GS-TC: Make sure drawn/target coords match for adjusting drawn rect 2023-03-19 15:18:54 +00:00
refractionpcsx2 1f6704dbda GS-TC: mask target rect with drawn area before download. 2023-03-19 15:18:54 +00:00
Toastarrrandrefractionpcsx2 33ea4e6225 Debugger: fix memory search crash 2023-03-19 13:44:11 +00:00
Toastarrrandrefractionpcsx2 d9cecbde7d Debugger: use unsigned long long for memory search 2023-03-19 13:44:11 +00:00
JordanTheToasterandrefractionpcsx2 84fab9ccd3 ImGuiOverlays: Fix incorrect fix naming
Fixes incorrect target partial invalidation overlay name and makes autoflush more distinct from anisotropic filtering.
2023-03-19 13:18:37 +00:00
JordanTheToasterandrefractionpcsx2 137dfc20fa GameDB: Various fixes
Fixes for Smash Cars This is Football 2002 and Champions Return to Arms.
2023-03-19 13:18:37 +00:00
TellowKrinkleandrefractionpcsx2 f39e856fee iR5900: Don't limit block sizes to 16 bits 2023-03-19 11:40:51 +00:00
Connor McLaughlinandrefractionpcsx2 e91aabc843 Qt: Fix graphics settings opening to other pages
Regression from 2b49614df9
2023-03-19 11:15:53 +00:00
Mrlinkwiiandrefractionpcsx2 f85a99b6f0 GameDB: fixes for True Crime - Streets of L.A. 2023-03-19 00:15:29 +00:00
TellowKrinkleandTellowKrinkle a59f95317a Core: Use auto for ryml noderefs
The return type switched between 0.4 and 0.5, so this will be compatible with both
2023-03-18 17:28:30 -05:00
Mrlinkwiiandrefractionpcsx2 6923000b52 GameDB: remove SoftwareRendererFMVHack from Siren 2 2023-03-18 22:26:41 +00:00
Víctor "IlDucciandGitHub 83471bdacd Qt:i18n: Adding I18N comments for translators, minor typo fixes (#8048) 2023-03-18 16:14:55 -05:00
refractionpcsx2 18045c195a GameDB: Readd Tex in RT for Xenosaga Ep.III 2023-03-18 17:07:29 +00:00
refractionpcsx2 b1edadfe3a GameDB: Add partial target invalidation to Ratchet Gladiator/Deadlocked 2023-03-18 17:07:29 +00:00
refractionpcsx2 ed5984aa3a GS-TC: Update draw rect on draw + invalidate bad match old targets 2023-03-18 17:07:29 +00:00
refractionpcsx2 bfca8b8461 GS-HW: Update dirty PCRTC framebuffer on output 2023-03-18 17:07:29 +00:00
refractionpcsx2 63cb0f3577 GameDB: Add partial target invalidation to ZoE 2nd Runner + MGS2 2023-03-18 17:07:29 +00:00
refractionpcsx2 2b49614df9 GS-HW: Don't bilinear dirty rects by default, added as upscale hack. 2023-03-18 17:07:29 +00:00
refractionpcsx2 fa439a465d GS-TC: Fix dirty rect sizes and merging. 2023-03-18 17:07:29 +00:00
refractionpcsx2 11a74c2c05 GS: Fix up some dirty behaviour, allow dirtying by page 2023-03-18 17:07:29 +00:00
refractionpcsx2 a693efad1e GameDB: Correct Dog's Life fixes 2023-03-18 17:07:29 +00:00
refractionpcsx2 75357a2f0a GS-TC: Remove uses of Surface Offsets where possible. 2023-03-18 17:07:29 +00:00
refractionpcsx2 a70f5ebc08 GS-TC: Rewrite rect translation 2023-03-18 17:07:29 +00:00
refractionpcsx2 b161df69e1 GS-TC: Fix up expand targets when mixing 24 and 32bit. 2023-03-18 17:07:29 +00:00
refractionpcsx2 85a0e75e28 GameDB: Add needed updates for Siren 2 and Legion 2023-03-18 17:07:29 +00:00
refractionpcsx2 56022a9af3 GS-TC: Remove uses of Surface Offsets where possible. 2023-03-18 17:07:29 +00:00
refractionpcsx2 5cbcf706e9 GS-HW: use page aligned rects for inexact matches when possible 2023-03-18 17:07:29 +00:00
refractionpcsx2 500b449422 GS-HW: Correct region size when source is in render target 2023-03-18 15:36:18 +00:00
Mrlinkwiiandrefractionpcsx2 8b78388834 GameDB: various fixes 2023-03-18 13:49:37 +00:00
Mrlinkwiiandrefractionpcsx2 b44d40d919 GameDB: remove not needed game fix for Yakuza 2023-03-18 13:49:17 +00:00
Mrlinkwiiandrefractionpcsx2 f8310e0a35 GS/CRC : purge Yakuza CRC hack 2023-03-18 13:49:17 +00:00
refractionpcsx2 59dc0e2cbf GS-SW: Fix rects for sw dumps 2023-03-18 12:49:15 +00:00
refractionpcsx2 6a4a7b1a3b HW-CRC: Draw glass smash on CPU in Burnout 3 2023-03-18 12:49:15 +00:00
lightningterror d62a7999fb GS-hw: Clean up Wunused-variable warnings. 2023-03-17 20:20:10 +01:00
TellowKrinkleandlightningterror 0ba1a42867 CI:macOS: Use xz for distribution
macOS 10.14 fixed a bug where Archive Utility couldn't decompress .tar.xz and is now our minimum version
2023-03-17 03:18:02 +01:00
JordanTheToasterandrefractionpcsx2 68ef49aef5 GameDB: SMT DS Fixes
Fixes broken effects when using lower than high blending.
2023-03-17 00:55:51 +00:00
Buzzardsoulandrefractionpcsx2 d0a65153df GameDB: Add Mipmap and Trilinear to Spyro: Enter the Dragonfly 2023-03-17 00:55:36 +00:00
refractionpcsx2 ac113b48e7 COP2: Mask R register on CFC2 reads 2023-03-17 00:43:23 +00:00
Mrlinkwiiandrefractionpcsx2 6e14680ac7 GameDB: add fixes for Lupin III - Columbus no Isan wa Akenisomaru and fix game names 2023-03-16 13:23:09 +00:00
Mrlinkwiiandrefractionpcsx2 ba03a533d8 GameDB: fixes for Biker Mice from Mars 2023-03-15 23:21:34 +00:00
JordanTheToasterandrefractionpcsx2 9abbecb286 GameDB: Various fixes
Fixes for incorrect region codes and adding merge sprite to Zone of Enders 2 to fix beeg bloom.
2023-03-15 20:39:44 +00:00
refractionpcsx2 9a20ea5c21 GS: Detect double width texture shuffles 2023-03-14 18:13:07 +00:00
refractionpcsx2 8ac4b125d2 UI: Fix masking of Target Partial Invalidation with Tex in RT 2023-03-14 15:04:10 +00:00
refractionpcsx2 f9b682ad10 GS: Fix integer scaling when using Bilinear (Sharp) 2023-03-14 14:51:00 +00:00
TellowKrinkleandrefractionpcsx2 58959b6114 CMake: Output test logs on failure 2023-03-13 20:45:12 +00:00
TellowKrinkleandrefractionpcsx2 b90405a7d2 GHActions:Windows: Add CMake clang-cl build 2023-03-13 20:45:12 +00:00
TellowKrinkleandrefractionpcsx2 e0a1613ad9 CMake: Allow overriding the exe name 2023-03-13 20:45:12 +00:00
TellowKrinkleandrefractionpcsx2 11930ed7a2 CMake: Clang-cl support 2023-03-13 20:45:12 +00:00
JordanTheToasterandrefractionpcsx2 f3ff1cec54 Documentation: Remove unused files
Removes old or unused files from the docs folder.
2023-03-13 20:29:27 +00:00
Stenzekandrefractionpcsx2 435e73d838 GS/HW: Texture cache improvements
Change texture scale from vector to scalar

 - Independent X and Y scaling is long gone.
 - Also separate size and scale in TC lookup

Move clear value for texture to base class

Align heights to page size

 - Since FRAME and Z are in page units, we can't have two targets
 - overlapping within the same page.
 - Stops some small resizes too.
 - Test cases: Genji and Spider-Man 2 shadows.

Don't modify target TEX0 on shuffle/clear

Move upscale multiplier to uniform

Make P8 conversion page-aware

Fix incorrect depth preload shader

Improve HLE of texture shuffles

When a texture shuffle is split into two half-screen draws, we skip the
first, and draw the whole thing in the second, taking care of when both
the texture and framebuffer are offset.
2023-03-13 20:29:05 +00:00
Stenzekandrefractionpcsx2 2fdea258fa GS/HW: Fix incorrect depth preload shader 2023-03-13 20:29:05 +00:00
Stenzekandrefractionpcsx2 b453a6a46d GS/Vulkan: Actually disable shader cache when requested 2023-03-13 20:29:05 +00:00
Stenzekandrefractionpcsx2 5b88e637d8 GS/Vulkan: Fix clear order in Merge/Interlace
Fixes blank frame when changing resolutions.
2023-03-13 20:29:05 +00:00
Stenzekandrefractionpcsx2 ac02bcbe33 GSRunner: Default to window but surfaceless when scripted 2023-03-13 20:29:05 +00:00
Stenzekandrefractionpcsx2 9efdeae3ac GSRunner: Reduce log spam 2023-03-13 20:29:05 +00:00
Stenzekandrefractionpcsx2 54e59e2f7b GSRunner: Support upscale parameter 2023-03-13 20:29:05 +00:00
PCSX2 Botandlightningterror 2c4e02ff34 PAD: Update to latest controller database. 2023-03-13 17:56:18 +01:00
BerylskidandGitHub 2a306cbd91 GS-OGL: Remove available_vram (#8389) 2023-03-13 09:07:34 +00:00
Víctor "IlDucciandGitHub b244136179 GUI/Qt: Minor text corrections, nitpicks (#8213)
- Adding the actual corrections from #8048 that were not added by #8119.
 - Fixing typos and missing ending periods.
 - Unifying the writing of certain terms:
   - Memory Card uppercased following Sony's writing (taken from PS2 manual).
   - gamefixes/game fixes -> game fixes
   - fast forward/fastforward/fast-forward -> fast-forward (taken from Oxford)
   - slowmotion/slow motion/slow-motion -> slow-motion (following the same convention as before, as I could not find this in Oxford's)
   - framebuffer/frame buffer -> framebuffer
   - Xbox name properly uppercased (for Controller settings)
 - Correcting RA's Rich Presence to separate it from Discord's Rich Presence (after discussions in the Translations channel).
 - Unification of option names in the option area and the hint area.
 - Adding a fix for the (currently broken) Stretch Height/Vertical Stretch tooltip.
2023-03-12 19:34:20 -05:00
Stenzekandrefractionpcsx2 b897f367ce FullscreenUI: Mirror Qt graphics settings changes 2023-03-12 16:21:36 +00:00
refractionpcsx2 6c46418f68 CI: Remove WrapGS from GameDB Schema 2023-03-12 15:11:29 +00:00
refractionpcsx2 f0d5d21e64 GS-Config: Remove remnants of the WrapMem setting. 2023-03-12 15:11:29 +00:00
Stenzekandrefractionpcsx2 93490876c9 Qt: Fix crash when changing renderer 2023-03-12 15:11:16 +00:00
Stenzekandrefractionpcsx2 74763d2156 Qt: Hide manual hardware fixes from global settings 2023-03-12 14:27:20 +00:00
Stenzekandrefractionpcsx2 b849d9862d Qt: Move CRC Fix Level to HW Fixes 2023-03-12 14:27:20 +00:00
Stenzekandrefractionpcsx2 cd575e0ed8 Qt: Move GPU Palette Conversion to HW Fixes 2023-03-12 14:27:20 +00:00
Stenzekandrefractionpcsx2 b5fbd88c34 GS/HW: Move old-target invalidation to after draw
Fixes crash in Radiata Stories.
2023-03-12 14:25:45 +00:00
refractionpcsx2 6003673165 GS-HW: Correct page aligned end blocks 2023-03-12 12:52:53 +00:00
refractionpcsx2 4555667554 GS: Rename bad_shader files to pcsx2_bad_shader for linux clarity 2023-03-12 00:07:52 +00:00
TellowKrinkleandrefractionpcsx2 c0db6d49f4 GS:MTL: Fix wrong function constant type 2023-03-11 23:34:56 +00:00
Buzzardsoulandrefractionpcsx2 6630066f0b GameDB: Add missing Tony Hawk's Underground 2 fixes. 2023-03-11 21:43:54 +00:00
Buzzardsoulandrefractionpcsx2 20e6a55dd1 GameDB: Add blending level 3 to Tony Hawk's Underground 2 2023-03-11 21:22:35 +00:00
Mrlinkwiiandrefractionpcsx2 d3f82c800f GameDB: add fixes to Crouching Tiger, Hidden Dragon 2023-03-11 21:06:08 +00:00
JordanTheToasterandrefractionpcsx2 e0e525d9ae ImGuiOverlays: Add missing fix to status bar
Adds Estimate Texture Region and GPU CLUT to the status bar as well as amends the names of CPU CLUT and GPU CLUT.
2023-03-11 20:41:19 +00:00
BuzzardsoulandGitHub 12f4d6f872 GameDB: Add Mipmap and Trilinear to Tony Hawk's Underground 2 (#8372) 2023-03-11 20:40:39 +00:00
lightningterror 0668e9bad9 GS: Bump shader cache version. 2023-03-11 20:44:11 +01:00
lightningterror 06aed8491c GS-hw: Separate the Alpha masked Ad case from blend hw bit.
Allows for cleaner code.
2023-03-11 20:44:11 +01:00
lightningterror df2d11e70d GS-hw: Blend table formatting. 2023-03-11 20:44:11 +01:00
lightningterror 2dde8a5e90 GS-hw: No need to set both BLEND_NO_REC and BLEND_A_MAX in table.
Setting only BLEND_NO_REC is enough as blending is free.
2023-03-11 20:44:11 +01:00
lightningterror 674b13fb3f GS-hw: Cleanup BLEND_C_CLR blend flags.
Rename BLEND_C_CLR to BLEND_HW_CLR.
Merge CLR2_AF and CLR2_AS to CLR2, don't need to be separate as we rely on PS_BLEND_C in shader.
2023-03-11 20:44:11 +01:00
lightningterror ab17c3693f Gs-hw: Clean up blend flags.
Re arrange them from hw to sw.
2023-03-11 20:44:11 +01:00
lightningterror a6c372de46 GS-hw: Rename clr_hw to blend_hw PSSampler bit. 2023-03-11 20:44:11 +01:00
lightningterror 62497b9300 GS-hw: Rename PS_CLR_HW to PS_BLEND_HW shader macro. 2023-03-11 20:44:11 +01:00
YiaysandGitHub 1461a3f8d7 Readme: Update cpubenchmark links (#8331) 2023-03-11 16:40:37 +00:00
JordanTheToasterandrefractionpcsx2 686b31765d GameDB: Various fixes
Adds estimate texture region to Combat Elite WWII Paratroopers and round sprite half to Champions Return To Arms to fix lines in HUD and menus.
2023-03-11 16:34:06 +00:00
lightningterror 05e4e98e64 GS: Bump shader cache version. 2023-03-09 21:08:52 +01:00
lightningterror e95b60d527 GS-hw: Cleanup hw blend clr cases.
Cleanup redundant Blend C sets, they are already set properly beforehand.
Cleanup multiple barrier sets for Ad cases, set one at the end instead.
Cleanup conditions, reduce and cleanup the code.
2023-03-09 21:08:52 +01:00
lightningterror 59aba9f757 GS-hw: Support Ad masked alpha on blend mix 1 and 2 clr cases. 2023-03-09 21:08:52 +01:00
BuzzardsoulandGitHub 248e94dc4c GameDB: Add autoflush to Dirge of Cerberus: Final Fantasy VII (#8351) 2023-03-09 16:09:53 +00:00
kamfretozandrefractionpcsx2 a7d574cff0 Qt: Fix description for Trigger & Button Deadzone 2023-03-09 16:04:35 +00:00
Stenzekandlightningterror ad05193916 GameDatabase: Fix recommended blending message
It was reading from the GS thread copy instead of the CPU thread config.
2023-03-09 12:44:21 +01:00
Stenzekandlightningterror b24b353b2d Qt: Change Profile label to Editing Profile
Hopefully less confusing this way.
2023-03-09 08:40:35 +01:00
Stenzekandlightningterror 18e4a04dba PAD: Add pressure option to macros 2023-03-09 08:40:35 +01:00
Stenzekandlightningterror 30989761e2 Qt: Fix sensitivity/deadzone showing for shift-click macro trigger 2023-03-09 08:40:35 +01:00
Stenzekandlightningterror b219ee9049 GS/Metal: Align texture upload pitch to 32 bytes 2023-03-09 08:40:09 +01:00
TellowKrinkleandlightningterror 98c611e404 GS:MTL: Don't start render passes with no targets 2023-03-09 08:37:57 +01:00
TellowKrinkleandlightningterror 7a4ef32210 Qt: Restore main menu settings button
Required for expected behavior on macOS
2023-03-09 08:36:48 +01:00
lightningterror c3359cea1f Qt: Disable framebuffer fetch option on d3d. 2023-03-08 20:23:01 +01:00
JordanTheToasterandrefractionpcsx2 f73a2d571f GameDB: Add missing Ponkotsu Roman Fixes
Adds missing JP fixes for Ponkotsu Roman Daikatsugeki Bumpy Trot.
2023-03-07 18:59:59 +00:00
JordanTheToasterandlightningterror 6dfb02c826 GSDumpReplayer: Fix widescreen patch crashing
Fixes a regression which caused PCSX2 to crash if you loaded a dump with widescreen patches enabled.
2023-03-07 14:19:55 +01:00
lightningterror 6c093fc81e GS: Bump shader cache version. 2023-03-06 23:36:54 +01:00
lightningterror 911d35e800 GS-hw: Fix invert rounding for accumulation blend on gl.
Also make the checks consistent for all renderers.
2023-03-06 23:36:54 +01:00
lightningterror 084fdc0a65 GS: Bump shader cache version. 2023-03-06 19:49:27 +01:00
lightningterror 1382fe9c6c GS-metal: Automatically adjust color compensation based on rgb value for hw blend clr3 case.
Auto adjust when any color is higher than 128 ( 1.0f) to get more accurate color results.
2023-03-06 19:49:27 +01:00
lightningterror b33242830e GS-vk: Automatically adjust color compensation based on rgb value for hw blend clr3 case.
Auto adjust when any color is higher than 128 ( 1.0f) to get more accurate color results.
2023-03-06 19:49:27 +01:00
lightningterror 8c0ee33c4c GS-ogl: Automatically adjust color compensation based on rgb value for hw blend clr3 case.
Auto adjust when any color is higher than 128 ( 1.0f) to get more accurate color results.
2023-03-06 19:49:27 +01:00
lightningterror e8cf4822b1 GS-d3d: Automatically adjust color compensation based on rgb value for hw blend clr3 case.
Auto adjust when any color is higher than 128 ( 1.0f) to get more accurate color results.
2023-03-06 19:49:27 +01:00
PCSX2 Botandlightningterror 3462f02ce2 PAD: Update to latest controller database. 2023-03-06 17:07:54 +01:00
Stenzekandrefractionpcsx2 1a67b2146a GS/HW: Fix incorrect condition in DX11/OGL 2023-03-06 09:11:51 +00:00
Stenzekandrefractionpcsx2 eb0d18f484 GSDumpReplayer: Fix resetting
And get rid of memory reset, it's never used.
2023-03-06 09:11:08 +00:00
Stenzekandrefractionpcsx2 c783fc0f59 GSDumpReplayer: Update serial on dump load
Fixes title and HW fixes not applying when dragging a new GS dump onto a
running PCSX2.
2023-03-05 15:41:42 +00:00
refractionpcsx2 31d02c1278 GS-TC: Allow TBW expansion 2023-03-05 11:17:33 +00:00
JordanTheToasterandrefractionpcsx2 85f96bb248 GameDB: Various recommendations and fixes
Adds a variety of fixes and recommendation's for users to ignore.
2023-03-05 10:06:51 +00:00
Stenzekandrefractionpcsx2 229cf908b7 GS/HW: Use multi stretch for preloading 2023-03-05 10:03:15 +00:00
Stenzekandrefractionpcsx2 89b18275c0 GS/DX11: Get rid of runtime blend state creation 2023-03-05 10:03:15 +00:00
Stenzekandrefractionpcsx2 b8a86baec7 GS/HW: Implement multi stretch for DX11/DX12/OpenGL 2023-03-05 10:03:15 +00:00
Stenzekandrefractionpcsx2 8505e9203a Qt: Support changing running GS dump by drag/dropping 2023-03-03 16:43:16 +00:00
Stenzekandrefractionpcsx2 5d95a503bf Qt: Fix crash when spamming shutdown button 2023-03-03 16:43:16 +00:00
Stenzekandrefractionpcsx2 36c7f96a1e GS/HW: Get rid of GetOutputSize()
And use PCRTCDisplays instead.
2023-03-03 16:42:54 +00:00
Mrlinkwiiandrefractionpcsx2 b40b606608 GameDB: update Oneechanbara2Special 2023-03-03 16:42:24 +00:00
Mrlinkwiiandrefractionpcsx2 03764a624f GS/CRC: purge Oneechanbara2Special CRC 2023-03-03 16:42:24 +00:00
RedDevilusandrefractionpcsx2 962cfa9441 GameDB: Steambot Chronicles + typo fix
- Steambot Chronicles has quite an extensive hack for a game doing weird stuff with their Z-buffer, it does mess with the sea being green which is incorrect but the game also looks off for rest of the cutscene.

- misalgined typo to misaligned
2023-03-03 16:42:09 +00:00
lightningterror b2f30ab080 GS: Bump shader cache version. 2023-03-03 16:35:10 +01:00
lightningterror 24c42ae2d9 GS-hw: Replace alpha factor/alpha source1 with source 1 color.
Output 1 will be used since we want to modify each color channel based on overflow value.
2023-03-03 16:35:10 +01:00
lightningterror af9353298c GS-metal: Add clr3 case for blend mix 2.
When Cs*(Alpha + 1) overflows compensate with adjusting Alpha output for Cd*Alpha.
2023-03-03 16:35:10 +01:00
lightningterror a3ecf0b0bd GS-vk: Add clr3 case for blend mix 2.
When Cs*(Alpha + 1) overflows compensate with adjusting Alpha output for Cd*Alpha.
2023-03-03 16:35:10 +01:00
lightningterror 58cb6ab728 GS-ogl: Add clr3 case for blend mix 2.
When Cs*(Alpha + 1) overflows compensate with adjusting Alpha output for Cd*Alpha.
2023-03-03 16:35:10 +01:00
lightningterror f478b3959c GS-d3d: Add clr3 case for blend mix 2.
When Cs*(Alpha + 1) overflows compensate with adjusting Alpha output for Cd*Alpha.
2023-03-03 16:35:10 +01:00
Stenzekandrefractionpcsx2 35ce680859 GameDB: Add PCRTCOffsets to Xiaolin Showdown
Stops screen shaking.
2023-03-03 15:33:47 +00:00
Stenzekandrefractionpcsx2 7df189ced4 GameDB: Add PCRTC and blending HW fixes 2023-03-03 15:33:47 +00:00
Stenzekandrefractionpcsx2 c35092504c GS/HW: Avoid copying an empty rectangle
Fixes a possible validation error in Ultraman Fighting Evolution -
Rebirth.
2023-03-03 14:59:07 +00:00
Stenzekandrefractionpcsx2 0bff6f7ad9 GS/HW: Require FBW=1 for Jak OI fix
The legit palette draws all seem to use FBW 1.

There's a couple of draws which use the alpha channel of the FB which
are currently falsely triggering.
2023-03-03 14:04:43 +00:00
JordanTheToasterandrefractionpcsx2 805f985144 GameDB: Gun fixes
Fixes for rainbowing at the edges of the screen missing bloom intensity and alignment and reflections on water and ground textures.
2023-03-02 21:16:57 +00:00
Stenzekandrefractionpcsx2 12e578b93c GS/Vulkan: Don't skip barrier with colclip+readwrite date
Value written from HDR setup must be visible for any DATE reads. Fixes
flickering in DBZ BT2.
2023-03-02 17:01:50 +00:00
JordanTheToasterandrefractionpcsx2 1312952305 GameDB: Various fixes
Adds Tex In RT 2 to Armoured Core 2 to fix texture corruption in future and adds merge sprite to Destroy All Humans 1&2 to further fix misaligned bloom.
2023-03-02 15:50:02 +00:00
Stenzekandrefractionpcsx2 6118b94f9e GS/Vulkan: Fix a bunch of validation warnings
None of these were errors, but it's still good to have clean output.
2023-03-02 15:49:13 +00:00
Stenzekandrefractionpcsx2 520320535e Qt: Clear all keyboard bind states when focus is lost 2023-03-02 15:49:04 +00:00
Mrlinkwiiandrefractionpcsx2 262b5f1dc0 GameDB: add fixes to Knight Rider - The Game 2023-03-02 11:07:28 +00:00
Mrlinkwiiandrefractionpcsx2 ac36162ddc GameDB: upscaling fixes for Springdale 2023-03-02 09:50:38 +00:00
Stenzekandrefractionpcsx2 9b813f4ae3 Qt: Fix skipdraw not being hidden globally again
And slience a warning in TC.
2023-03-02 09:34:41 +00:00
JordanTheToasterandrefractionpcsx2 35d05b8653 GameDB: DAH 1&2 Fixes
Fixes for misaligned bloom and sun occlusion and intensity in Destroy All Humans 1 and 2.
2023-03-02 09:18:18 +00:00
Mrlinkwiiandrefractionpcsx2 e4d6b87e5d GameDB: add textureInsideRT to NBA '07 featuring The Life Vol.2 2023-03-02 01:34:39 +00:00
Stenzekandrefractionpcsx2 64b38e5a4a GS/HW: Add "Merge Targets" texture-in-RT mode
Can take several targets from the cache, and create a combined/merged
source from them.

Fixes shadow maps in Destroy All Humans.
2023-03-01 21:13:37 +00:00
Stenzekandrefractionpcsx2 75957c84e3 GS: Add "multi stretch rect" drawing to device 2023-03-01 21:13:37 +00:00
Silentandrefractionpcsx2 c33fb2adbd Qt: Add a context menu to the toolbar's Settings button when the game is running
A new small context menu that allows to select between global settings
and game settings.
2023-03-01 20:38:42 +00:00
Silentandrefractionpcsx2 97d3baba35 Qt: Move "Game Properties" from View to Settings 2023-03-01 20:38:42 +00:00
Stenzekandrefractionpcsx2 e91f9925f8 Qt: Display a slightly more helpful error on display create failure 2023-03-01 20:37:18 +00:00
Stenzekandrefractionpcsx2 b484f7aef0 Context/Vulkan: Handle VK_INCOMPLETE return from vkEnumeratePhysicalDevices() 2023-03-01 20:37:18 +00:00
355 changed files with 19235 additions and 17924 deletions
+4 -1
View File
@@ -20,11 +20,14 @@ body:
### Please Avoid Issues Pertaining to the Following:
- We are **not** accepting bug reports for **PSX mode** at this time
- If you are interested in helping contribute to PSX mode please do so on the forums. Otherwise our recommendation is that you use a [proper PSX emulator](https://emulation.gametechwiki.com/index.php/PlayStation_emulators)
- If you are interested in helping contribute to PSX mode please do so on the forums. Otherwise our recommendation is that you use [Duckstation](https://github.com/stenzek/duckstation/releases/tag/latest)
- We do **not** accept issues relating to **upscaling** at this time
- We are aware of the various problems with upscaling. The issue spans many games and having hundreds of issues for the same fundamental issues isn't particularly helpful. There are several workarounds for graphical problems that come as a result of upscaling
- Please try your game at native resolution before creating an issue
- If your bug is the result of upscaling please use the forums or discord for assistance with various upscaling workarounds. Additionally, the unofficial PCSX2 [Wiki](https://wiki.pcsx2.net/Main_Page) often lists various fixes for upscaling issues
- We do **not** accept issues relating to Widescreen/no-interlace patches at this time
- Any issues pertaining to Widescreen/no-interlace patches please forward them to the [patches repository](https://github.com/PCSX2/pcsx2_patches).
- type: textarea
id: desc
attributes:
+4 -1
View File
@@ -20,11 +20,14 @@ body:
### Please Avoid Issues Pertaining to the Following:
- We are **not** accepting bug reports for **PSX mode** at this time
- If you are interested in helping contribute to PSX mode please do so on the forums. Otherwise our recommendation is that you use a [proper PSX emulator](https://emulation.gametechwiki.com/index.php/PlayStation_emulators)
- If you are interested in helping contribute to PSX mode please do so on the forums. Otherwise our recommendation is that you use [Duckstation](https://github.com/stenzek/duckstation/releases/tag/latest)
- We do **not** accept issues relating to **upscaling** at this time
- We are aware of the various problems with upscaling. The issue spans many games and having hundreds of issues for the same fundamental issues isn't particularly helpful. There are several workarounds for graphical problems that come as a result of upscaling
- Please try your game at native resolution before creating an issue
- If your bug is the result of upscaling please use the forums or discord for assistance with various upscaling workarounds. Additionally, the unofficial PCSX2 [Wiki](https://wiki.pcsx2.net/Main_Page) often lists various fixes for upscaling issues
- We do **not** accept issues relating to Widescreen/no-interlace patches at this time
- Any issues pertaining to Widescreen/no-interlace patches please forward them to the [patches repository](https://github.com/PCSX2/pcsx2_patches).
- type: textarea
id: desc
attributes:
+2 -2
View File
@@ -39,8 +39,8 @@
'Debugger':
- 'pcsx2/DebugTools/*'
- 'pcsx2/DebugTools/**/*'
- 'pcsx2/gui/Debugger/*'
- 'pcsx2/gui/Debugger/**/*'
- 'pcsx2-qt/Debugger/*'
- 'pcsx2-qt/Debugger/**/*'
'IPC':
- 'pcsx2/IPC*'
- 'pcsx2/**/IPC*'
@@ -19,7 +19,7 @@ jobs:
mv ./game_controller_db.txt ${{github.workspace}}/bin/resources/game_controller_db.txt
- name: Create Pull Request
uses: peter-evans/create-pull-request@v4
uses: peter-evans/create-pull-request@v5
with:
title: "PAD: Update to latest controller database"
commit-message: "PAD: Update to latest controller database."
+3 -3
View File
@@ -144,12 +144,12 @@ jobs:
APPNAME="PCSX2-$TAG"
fi
mv build/pcsx2*/PCSX2.app "$APPNAME.app"
tar cvzf "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.gz" "$APPNAME.app"
tar --options xz:compression-level=9 -cvJf "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.xz" "$APPNAME.app"
mkdir ci-artifacts
cp "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.gz" ci-artifacts/macOS-${{ inputs.gui }}.tar.gz
cp "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.xz" ci-artifacts/macOS-${{ inputs.gui }}.tar.xz
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
path: "*.tar.gz"
path: "*.tar.xz"
+1 -21
View File
@@ -28,25 +28,7 @@ jobs:
jobName: Qt
configuration: CMake
buildSystem: cmake
secrets: inherit
build_qt_sse4:
if: github.repository == 'PCSX2/pcsx2'
name: "Windows - SSE4"
uses: ./.github/workflows/windows_build_qt.yml
with:
jobName: Qt
configuration: Release
simd: "SSE4"
secrets: inherit
build_qt_avx2:
if: github.repository == 'PCSX2/pcsx2'
name: "Windows - AVX2"
uses: ./.github/workflows/windows_build_qt.yml
with:
jobName: Qt
configuration: Release AVX2
cmakeFlags: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
secrets: inherit
# MacOS
@@ -65,8 +47,6 @@ jobs:
needs:
- build_linux_qt
- build_windows_qt
- build_qt_sse4
- build_qt_avx2
- build_macos_qt
name: "Upload Artifacts"
runs-on: ubuntu-latest
@@ -87,6 +87,7 @@ declare -a SYSLIBS=(
"libvorbis.so.0"
"libvorbisenc.so.2"
"libxcb.so.1"
"libxcb-cursor.so.0"
"libxcb-render.so.0"
"libxcb-shm.so.0"
"libxkbcommon.so.0"
@@ -206,6 +207,9 @@ mkdir "$OUTDIR/usr"
echo "Copying binary and resources..."
cp -a "$BUILDDIR/bin" "$OUTDIR/usr"
# Get rid of unit tests, we don't want them bloating the squashfs.
rm -fv "$OUTDIR"/usr/bin/*_test
# Patch RPATH so the binary goes hunting for shared libraries in the AppDir instead of system.
echo "Patching RPATH in ${BINARY}..."
patchelf --set-rpath '$ORIGIN/../lib' "$OUTDIR/usr/bin/$BINARY"
@@ -4,23 +4,26 @@ set -e
INSTALLDIR="$HOME/deps"
NPROCS="$(getconf _NPROCESSORS_ONLN)"
SDL=SDL2-2.26.0
QT=6.3.1
SDL=SDL2-2.26.5
QT=6.5.0
LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
mkdir -p deps-build
cd deps-build
cat > SHASUMS <<EOF
8000d7169febce93c84b6bdf376631f8179132fd69f7015d4dadb8b9c2bdb295 $SDL.tar.gz
0a64421d9c2469c2c48490a032ab91d547017c9cc171f3f8070bc31888f24e03 qtbase-everywhere-src-$QT.tar.xz
7b19f418e6f7b8e23344082dd04440aacf5da23c5a73980ba22ae4eba4f87df7 qtsvg-everywhere-src-$QT.tar.xz
c412750f2aa3beb93fce5f30517c607f55daaeb7d0407af206a8adf917e126c1 qttools-everywhere-src-$QT.tar.xz
d7bdd55e2908ded901dcc262157100af2a490bf04d31e32995f6d91d78dfdb97 qttranslations-everywhere-src-$QT.tar.xz
6f14fea2d172a5b4170be3efcb0e58535f6605b61bcd823f6d5c9d165bb8c0f0 qtwayland-everywhere-src-$QT.tar.xz
ad8fea3da1be64c83c45b1d363a6b4ba8fd60f5bde3b23ec73855709ec5eabf7 $SDL.tar.gz
fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.zip
fde1aa7b4fbe64ec1b4fc576a57f4688ad1453d2fab59cbadd948a10a6eaf5ef qtbase-everywhere-src-$QT.tar.xz
64ca7e61f44d51e28bcbb4e0509299b53a9a7e38879e00a7fe91643196067a4f qtsvg-everywhere-src-$QT.tar.xz
49c33d96b0a44988be954269b8ce3d1a495b439726e03a6be7c0d50a686369c4 qttools-everywhere-src-$QT.tar.xz
fc85d0fd8393f518653ccada1014177a56df6e73f30f3b64eea0c2e4a0067a3d qttranslations-everywhere-src-$QT.tar.xz
ccc57fa277fc5f1c1c2c4733eae80a60996b67a067233c47809e542aa31759a3 qtwayland-everywhere-src-$QT.tar.xz
EOF
curl -L \
-O "https://libsdl.org/release/$SDL.tar.gz" \
-O "https://github.com/ianlancetaylor/libbacktrace/archive/$LIBBACKTRACE.zip" \
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
@@ -37,6 +40,14 @@ make "-j$NPROCS"
make install
cd ..
echo "Building libbacktrace..."
unzip "$LIBBACKTRACE.zip"
cd "libbacktrace-$LIBBACKTRACE"
./configure --prefix="$HOME/deps"
make
make install
cd ..
# Couple notes:
# -fontconfig is needed otherwise Qt Widgets render only boxes.
# -qt-doubleconversion avoids a dependency on libdouble-conversion.
@@ -65,19 +76,6 @@ cd ../../
echo "Building Qt Wayland..."
tar xf "qtwayland-everywhere-src-$QT.tar.xz"
cd "qtwayland-everywhere-src-$QT"
# qtwayland does not build without qml/qtdeclarative in 6.3.1. Work around it.
patch -u src/compositor/CMakeLists.txt <<EOF
--- src/compositor/CMakeLists.txt 2022-06-08 13:44:30.000000000 +1000
+++ src/compositor/CMakeLists.txt 2022-07-17 20:05:25.461881785 +1000
@@ -46,7 +46,6 @@
global/qtwaylandcompositorglobal.h
global/qtwaylandqmlinclude.h
global/qwaylandcompositorextension.cpp global/qwaylandcompositorextension.h global/qwaylandcompositorextension_p.h
- global/qwaylandquickextension.cpp global/qwaylandquickextension.h
global/qwaylandutils_p.h
hardware_integration/qwlclientbufferintegration.cpp hardware_integration/qwlclientbufferintegration_p.h
wayland_wrapper/qwlbuffermanager.cpp wayland_wrapper/qwlbuffermanager_p.h
EOF
mkdir build
cd build
cmake -G Ninja -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=Release ..
@@ -103,6 +101,30 @@ patch -u src/linguist/CMakeLists.txt <<EOF
add_subdirectory(linguist)
endif()
EOF
# Also force disable clang scanning, it gets very confused.
patch -u configure.cmake <<EOF
--- configure.cmake
+++ configure.cmake
@@ -14,12 +14,12 @@
# Presumably because 6.0 ClangConfig.cmake files are not good enough?
# In any case explicitly request a minimum version of 8.x for now, otherwise
# building with CMake will fail at compilation time.
-qt_find_package(WrapLibClang 8 PROVIDED_TARGETS WrapLibClang::WrapLibClang)
+#qt_find_package(WrapLibClang 8 PROVIDED_TARGETS WrapLibClang::WrapLibClang)
# special case end
-if(TARGET WrapLibClang::WrapLibClang)
- set(TEST_libclang "ON" CACHE BOOL "Required libclang version found." FORCE)
-endif()
+#if(TARGET WrapLibClang::WrapLibClang)
+# set(TEST_libclang "ON" CACHE BOOL "Required libclang version found." FORCE)
+#endif()
EOF
mkdir build
cd build
cmake -G Ninja -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=Release -DFEATURE_assistant=OFF -DFEATURE_clang=OFF -DFEATURE_designer=OFF -DFEATURE_kmap2qmap=OFF -DFEATURE_pixeltool=OFF -DFEATURE_pkg_config=OFF -DFEATURE_qev=OFF -DFEATURE_qtattributionsscanner=OFF -DFEATURE_qtdiag=OFF -DFEATURE_qtplugininfo=OFF ..
@@ -6,11 +6,11 @@ export MACOSX_DEPLOYMENT_TARGET=10.14
INSTALLDIR="$HOME/deps"
NPROCS="$(getconf _NPROCESSORS_ONLN)"
SDL=SDL2-2.26.0
SDL=SDL2-2.26.5
PNG=1.6.37
JPG=9e
SOUNDTOUCH=soundtouch-2.3.1
QT=6.3.1
QT=6.4.3
mkdir deps-build
cd deps-build
@@ -21,14 +21,14 @@ export CFLAGS="-I$INSTALLDIR/include -Os $CFLAGS"
export CXXFLAGS="-I$INSTALLDIR/include -Os $CXXFLAGS"
cat > SHASUMS <<EOF
8000d7169febce93c84b6bdf376631f8179132fd69f7015d4dadb8b9c2bdb295 $SDL.tar.gz
ad8fea3da1be64c83c45b1d363a6b4ba8fd60f5bde3b23ec73855709ec5eabf7 $SDL.tar.gz
505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca libpng-$PNG.tar.xz
4077d6a6a75aeb01884f708919d25934c93305e49f7e3f36db9129320e6f4f3d jpegsrc.v$JPG.tar.gz
6900996607258496ce126924a19fe9d598af9d892cf3f33d1e4daaa9b42ae0b1 $SOUNDTOUCH.tar.gz
0a64421d9c2469c2c48490a032ab91d547017c9cc171f3f8070bc31888f24e03 qtbase-everywhere-src-$QT.tar.xz
7b19f418e6f7b8e23344082dd04440aacf5da23c5a73980ba22ae4eba4f87df7 qtsvg-everywhere-src-$QT.tar.xz
c412750f2aa3beb93fce5f30517c607f55daaeb7d0407af206a8adf917e126c1 qttools-everywhere-src-$QT.tar.xz
d7bdd55e2908ded901dcc262157100af2a490bf04d31e32995f6d91d78dfdb97 qttranslations-everywhere-src-$QT.tar.xz
5087c9e5b0165e7bc3c1a4ab176b35d0cd8f52636aea903fa377bdba00891a60 qtbase-everywhere-src-$QT.tar.xz
88315f886cf81898705e487cedba6e6160724359d23c518c92c333c098879a4a qtsvg-everywhere-src-$QT.tar.xz
867df829cd5cd3ae8efe62e825503123542764b13c96953511e567df70c5a091 qttools-everywhere-src-$QT.tar.xz
79e56b7800d49649a8a8010818538c367a829e0b7a09d5f60bd3aecf5abe972c qttranslations-everywhere-src-$QT.tar.xz
EOF
curl -L \
@@ -4,7 +4,7 @@ import shutil
tag = os.environ['TAG'].split("refs/tags/")[1]
scan_dir = os.environ['SCAN_DIR']
output_dir = os.environ['OUT_DIR']
accepted_exts = ["AppImage", "tar.gz", "7z"]
accepted_exts = ["AppImage", "tar.xz", "7z"]
for dir_name in os.listdir(scan_dir):
+12 -2
View File
@@ -38,8 +38,8 @@ jobs:
configuration: Release AVX2
secrets: inherit
build_qt_sse4_cmake:
name: "CMake SSE4"
build_qt_cmake:
name: "CMake"
uses: ./.github/workflows/windows_build_qt.yml
with:
jobName: Qt
@@ -65,3 +65,13 @@ jobs:
jobName: Qt Clang
configuration: Release Clang AVX2
secrets: inherit
build_qt_cmake_clang:
name: "CMake"
uses: ./.github/workflows/windows_build_qt.yml
with:
jobName: Qt Clang
configuration: CMake
buildSystem: cmake
cmakeFlags: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DPCSX2_EXE_NAME=pcsx2-qt-clang
secrets: inherit
+7 -3
View File
@@ -25,14 +25,18 @@ on:
required: false
type: string
default: msbuild
cmakeFlags:
required: false
type: string
default: ""
qt_binary_url:
required: false
type: string
default: https://github.com/PCSX2/pcsx2-windows-dependencies/releases/download/2022-11-20/qt-6.4.0-x64.7z
default: https://github.com/PCSX2/pcsx2-windows-dependencies/releases/download/2023-04-25/qt-6.5.0-x64.7z
qt_dir:
required: false
type: string
default: 3rdparty\qt\6.4.0\msvc2022_64
default: 3rdparty\qt\6.5.0\msvc2022_64
cheats_url:
required: false
type: string
@@ -92,7 +96,7 @@ jobs:
shell: cmd
run: |
call "%ProgramFiles%\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
cmake . -B build "-DCMAKE_PREFIX_PATH=%cd%\${{ inputs.qt_dir }}" -DQT_BUILD=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DDISABLE_ADVANCE_SIMD=ON -G Ninja
cmake . -B build ${{ inputs.cmakeFlags }} "-DCMAKE_PREFIX_PATH=%cd%\${{ inputs.qt_dir }}" -DQT_BUILD=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DDISABLE_ADVANCE_SIMD=ON -G Ninja
- name: Build PCSX2
shell: cmd
+10
View File
@@ -0,0 +1,10 @@
add_library(rainterface
RA_Consoles.h
RA_Emulators.h
RA_Interface.cpp
RA_Interface.h
)
target_include_directories(rainterface PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
target_include_directories(rainterface INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
+1 -1
View File
@@ -18,7 +18,7 @@ set(SDL_X11 OFF CACHE BOOL "")
set(SDL_WAYLAND OFF CACHE BOOL "")
set(SDL_RPI OFF CACHE BOOL "")
set(SDL_COCOA ON CACHE BOOL "")
set(SDL_DIRECTX OFF CACHE BOOL "")
set(SDL_DIRECTX ON CACHE BOOL "")
set(SDL_WASAPI OFF CACHE BOOL "")
set(SDL_RENDER_D3D OFF CACHE BOOL "")
set(SDL_RENDER_METAL OFF CACHE BOOL "")
+2 -2
View File
@@ -22,7 +22,7 @@ Installers and binaries for both stable and development builds are available fro
| Operating System | CPU | GPU | RAM |
| ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
| - Windows 10 21H2 (1809 or later) (64-bit) <br/> - Ubuntu 20.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports SSE4.1 <br/> - [PassMark Single Thread Performance](https://www.cpubenchmark.net/singleThread.html) rating near or greater than 1800 <br/> - Two physical cores, with hyperthreading | - Direct3D10 support <br/> - OpenGL 3.x support <br/> - Vulkan 1.1 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 3000 (Geforce GTX 750 Radeon RX 560 Intel Arc A380) <br/> - 2 GB Video Memory | 4 GB |
| - Windows 10 21H2 (1809 or later) (64-bit) <br/> - Ubuntu 20.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports SSE4.1 <br/> - [PassMark Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 1800<br/> - Two physical cores, with hyperthreading | - Direct3D10 support <br/> - OpenGL 3.x support <br/> - Vulkan 1.1 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 3000 (Geforce GTX 750, Radeon RX 560, Intel Arc A380) <br/> - 2 GB Video Memory | 4 GB |
_Note: Recommended Single Thread Performance is based on moderately complex games. Games that pushed the PS2 hardware to its limits will struggle on CPUs at this level. Some release titles and 2D games which underutilized the PS2 hardware may run on CPUs rated as low as 1200. A quick reference for CPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:CPU_intensive_games), [Forum](https://forums.pcsx2.net/Thread-LIST-The-Most-CPU-Intensive-Games) and CPU **light** games: [Forum](https://forums.pcsx2.net/Thread-LIST-Games-that-don-t-need-a-strong-CPU-to-emulate)_
@@ -30,7 +30,7 @@ _Note: Recommended Single Thread Performance is based on moderately complex game
| Operating System | CPU | GPU | RAM |
| ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
| - Windows 10 21H2 (1809 or later) (64-bit) <br/> - Ubuntu 22.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports AVX2 <br/> - [PassMark Single Thread Performance](https://www.cpubenchmark.net/singleThread.html) rating near or greater than 2600 <br/> - Four physical cores, with or without hyperthreading | - Direct3D12 support <br/> - OpenGL 4.6 support <br/> - Vulkan 1.3 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 6000 (GeForce GTX 1650 Radeon RX 570) <br/> - 4 GB Video Memory | 8 GB |
| - Windows 10 21H2 (1809 or later) (64-bit) <br/> - Ubuntu 22.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports AVX2 <br/> - [PassMark Single Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 2600<br/> - Four physical cores, with or without hyperthreading | - Direct3D12 support <br/> - OpenGL 4.6 support <br/> - Vulkan 1.3 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 6000 (GeForce GTX 1650, Radeon RX 570) <br/> - 4 GB Video Memory | 8 GB |
_Note: Recommended GPU is based on 3x Internal, ~1080p resolution requirements. Higher resolutions will require stronger cards; 6x Internal, ~4K resolution will require a [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 12000 (GeForce RTX 2060 Radeon RX 6600 Intel Arc A750). Just like CPU requirements, this is also highly game dependent. A quick reference for GPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:GPU_intensive_games)_
-189
View File
@@ -1,189 +0,0 @@
.\" Copyright 2002-2017 PCSX2 Dev Team
.\"
.\" This is free documentation; you can redistribute it and/or
.\" modify it under the terms of the GNU General Public License as
.\" published by the Free Software Foundation; either version 3 of
.\" the License, or (at your option) any later version.
.\"
.\" The GNU General Public License's references to "object code"
.\" and "executables" are to be interpreted as the output of any
.\" document formatting or typesetting system, including
.\" intermediate and printed output.
.\"
.\" This manual is distributed in the hope that it will be useful,
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
.\" GNU General Public License for more details.
.\"
.\" You should have received a copy of the GNU General Public
.\" License along with this manual; if not, see
.\" http://www.gnu.org/licenses.
.Dd January 10, 2017
.Dt PCSX2 1
.Os
.Sh NAME
.Nm PCSX2
.Nd PlayStation(R)2 Console Emulator
.Sh SYNOPSIS
.Nm
.Op Fl h
.Op Fl \-cfg Ns = Ns Ar file
.Op Fl \-cfgpath Ns = Ns Ar path
.Op Fl \-console
.Op Fl \-forcewiz
.Op Fl \-portable
.Op Fl \-profiling
.Op Fl \-elf Ns = Ns Ar file
.Op Fl \-irx Ns = Ns Ar file
.Op Fl \-nogui
.Op Fl \-noguiprompt
.Op Fl \-nodisc
.Op Fl \-usecd
.Op Fl \-fullscreen
.Op Fl \-windowed
.Op Fl \-nohacks
.Op Fl \-fullboot
.Op Fl \-gamefixes Ns = Ns Ar string
.Op Fl \-gs Ns = Ns Ar file
.Op Fl \-pad Ns = Ns Ar file
.Op Fl \-spu2 Ns = Ns Ar file
.Op Fl \-cdvd Ns = Ns Ar file
.Op Fl \-usb Ns = Ns Ar file
.Op Fl \-fw Ns = Ns Ar file
.Op Fl \-dev9 Ns = Ns Ar file
.Op Ar iso
.Sh DESCRIPTION
.Nm
is an open-source PlayStation 2 (AKA PS2) emulator.
Its purpose is to emulate the PS2 hardware, using a combination of MIPS CPU
interpreters, recompilers and a virtual machine that manages hardware states and
PS2 memory.
This allows you to play PS2 games on your PC, with many additional features and
benefits.
.Sh GENERAL OPTIONS
.Bl -tag -width Ds
.It Fl h , Fl \-help
Displays the list of available command line options.
.It Fl \-cfg Ns = Ns Ar file
Uses
.Ar file
instead of PCSX2_vm.ini as the configuration file.
It does not affect plugins.
.It Fl \-cfgpath Ns = Ns Ar path
Specifies
.Ar path
as the configuration file path.
It affects both
.Nm
and the plugins.
.It Fl \-console
Forces the program log to be visible.
.It Fl \-forcewiz
Forces the First-Time Wizard to run.
.It Fl \-portable
Runs
.Nm
in portable mode.
.It Fl \-profiling
Makes it easier to use profiling tools.
.El
.Sh AUTO-RUN OPTIONS
.Bl -tag -width Ds
.It Ar iso
Loads and runs
.Ar iso
at startup using the
.Nm
internal ISO loader.
.It Fl \-elf Ns = Ns Ar file
Executes
.Ar file
as an ELF image.
.It Fl \-irx Ns = Ns Ar file
Executes
.Ar file
as an IRX image.
.It Fl \-nogui
Disables display of the GUI while running games.
.Nm
will terminate when the game window is closed.
.It Fl \-noguiprompt
Prompt before exiting when
.Fl \-nogui
is used.
.It Fl \-nodisc
Boots with an empty DVD tray.
Use this to boot into the PS2 system menu.
.It Fl \-usecd
Boots using the configured CDVD plugin instead of booting
.Ar iso .
.It Fl \-fullscreen
Runs the game in fullscreen mode.
.It Fl \-windowed
Runs the game in windowed mode.
.El
.Sh COMPATIBILITY OPTIONS
.Bl -tag -width Ds
.It Fl \-nohacks
Disables all speedhacks.
.It Fl \-fullboot
Disables the fast boot feature.
.It Fl \-gamefixes= Ns Ar string
Enable specific gamefixes for this session.
.Ar string
is a comma-separated list of gamefixes.
.Pp
Valid gamefixes: VuAddSub, VuClipFlag, FpuCompare, FpuMul, FpuNegDiv, XGKick,
IpuWait, EETiming, SkipMpeg, OPHFlag, DMABusy,VIFFIFO, VIF1Stall, GIFFIFO,
FMVinSoftware, GoemonTlb, ScarfaceIbit.
.El
.Sh PLUGIN OVERRIDES
.Bl -tag -width Ds
.It Fl \-gs Ns = Ns Ar file
Uses
.Ar file
as the GS plugin.
.It Fl \-pad Ns = Ns Ar file
Uses
.Ar file
as the PAD plugin.
.It Fl \-spu2 Ns = Ns Ar file
Uses
.Ar file
as the SPU2 plugin.
.It Fl \-cdvd Ns = Ns Ar file
Uses
.Ar file
as the CDVD plugin.
.It Fl \-usb Ns = Ns Ar file
Uses
.Ar file
as the USB plugin.
.It Fl \-fw Ns = Ns Ar file
Uses
.Ar file
as the FW plugin.
.It Fl \-dev9 Ns = Ns Ar file
Uses
.Ar file
as the DEV9 plugin.
.El
.Sh FILES
.Bl -tag -width Ds
.It $XDG_CONFIG_DIR/PCSX2 or $HOME/PCSX2
User configuration and data directory.
.El
.Sh AUTHORS
.An PCSX2 Dev Team and many other contributors
.Sh BUGS
Bugs can be reported by submitting an issue at the
.Lk https://github.com/PCSX2/pcsx2/issues "PCSX2 GitHub issue tracker" .
.Sh PCSX2 RELATED WEBSITES
.Bl -bullet
.It
.Lk http://github.com/PCSX2/pcsx2 "PCSX2 git repository"
.It
.Lk http://pcsx2.net "PCSX2 website"
.It
.Lk http://forums.pcsx2.net "PCSX2 forums"
.El
Binary file not shown.
+2371 -878
View File
File diff suppressed because it is too large Load Diff
+35 -14
View File
@@ -66,12 +66,12 @@
03000000c82d00000021000000000000,8BitDo SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000160000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000161000000000000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000121000000000000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000261000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00001130000000000000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001230000000000000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001330000000000000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00000121000000000000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000a00500003232000000000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001890000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00003032000000000000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
@@ -105,6 +105,8 @@
03000000a30c00002800000000000000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
03000000050b00000579000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000050b00000679000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,start:b3,platform:Windows,
03000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
03000000e4150000103f000000000000,Batarang,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000d6200000e557000000000000,Batarang PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000c01100001352000000000000,Battalife Joystick,a:b6,b:b7,back:b2,leftshoulder:b0,leftx:a0,lefty:a1,rightshoulder:b1,start:b3,x:b4,y:b5,platform:Windows,
@@ -184,13 +186,14 @@
03000000ad1b000028f0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000ad1b00002ef0000000000000,Fightpad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000ad1b000038f0000000000000,Fightpad TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
03005036852100000000000000000000,Final Fantasy XIV Online Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000f806000001a3000000000000,Firestorm,a:b9,b:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b0,leftstick:b10,lefttrigger:b1,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,start:b12,x:b8,y:b4,platform:Windows,
03000000b50700000399000000000000,Firestorm 2,a:b2,b:b4,back:b10,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b9,start:b11,x:b3,y:b5,platform:Windows,
03000000b50700001302000000000000,Firestorm D3,a:b0,b:b2,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,x:b1,y:b3,platform:Windows,
03000000b40400001024000000000000,Flydigi Apex,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000151900004000000000000000,Flydigi Vader 2,a:b11,b:b10,back:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,leftstick:b1,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b0,righttrigger:b4,rightx:a3,righty:a4,start:b2,x:b9,y:b8,platform:Windows,
03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows,
03000000b40400001224000000000000,Flydigi Vader 2 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,paddle3:b17,paddle4:b18,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
03000000151900004000000000000000,Flydigi Vader 2,a:b27,b:b26,back:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b23,leftstick:b17,lefttrigger:b21,leftx:a0,lefty:a1,misc1:b15,paddle1:b11,paddle2:b10,paddle3:b13,paddle4:b12,rightshoulder:b22,rightstick:b16,righttrigger:b20,rightx:a3,righty:a4,start:b18,x:b25,y:b24,platform:Windows,
03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b14,paddle1:b4,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows,
03000000b40400001224000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows,
0300000066f700000100000000000000,Game VIB Joystick,a:b2,b:b3,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b11,x:b0,y:b1,platform:Windows,
03000000260900002625000000000000,GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,lefttrigger:a4,leftx:a0,lefty:a1,righttrigger:a5,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Windows,
@@ -302,6 +305,7 @@
03000000242e00000b20000000000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Windows,
03000000242e0000ff0b000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Windows,
03000000790000004e95000000000000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows,
03000000242e00006a38000000000000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Windows,
03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows,
03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000d81d00001000000000000000,iBuffalo BSGP1204P Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
@@ -374,7 +378,7 @@
030000009f000000adbb000000000000,MaxJoypad Virtual Controller,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
03000000250900000128000000000000,Mayflash Arcade Stick,a:b1,b:b2,back:b8,leftshoulder:b0,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b3,righttrigger:b7,start:b9,x:b5,y:b6,platform:Windows,
030000008f0e00001330000000000000,Mayflash Controller Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
03000000242f00003700000000000000,Mayflash F101,a:b1,b:b2,back:b8,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
03000000242f00003700000000000000,Mayflash F101,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
03000000790000003018000000000000,Mayflash F300 Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
03000000242f00003900000000000000,Mayflash F300 Elite Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000790000004418000000000000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Windows,
@@ -533,6 +537,7 @@
030000009b2800003200000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
030000009b2800006000000000000000,Raphnet GC and N64 Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:+a5,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:+a2,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Windows,
030000009b2800001800000000000000,Raphnet Jaguar Adapter,a:b2,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b10,start:b3,x:b11,y:b12,platform:Windows,
030000009b2800006300000000000000,Raphnet N64 Adapter,a:b0,b:b1,start:b3,lefttrigger:b2,dpup:b10,dpleft:b12,dpdown:b11,dpright:b13,leftx:a0,lefty:a1,-rightx:b8,+rightx:b9,-righty:b6,+righty:b7,leftshoulder:b4,rightshoulder:b5,platform:Windows,
030000009b2800000200000000000000,Raphnet NES Adapter,a:b7,b:b6,back:b5,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,start:b4,platform:Windows,
030000009b2800004400000000000000,Raphnet PS1 and PS2 Adapter,a:b1,b:b2,back:b5,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b9,rightx:a3,righty:a4,start:b4,x:b0,y:b3,platform:Windows,
030000009b2800004300000000000000,Raphnet Saturn,a:b0,b:b1,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
@@ -545,6 +550,7 @@
030000009b2800002c00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows,
030000009b2800008000000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows,
03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000f8270000bf0b000000000000,Razer Kishi,a:b6,b:b7,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b18,leftshoulder:b12,leftstick:b19,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b13,rightstick:b20,righttrigger:b15,rightx:a2,righty:a5,start:b17,x:b9,y:b10,platform:Windows,
03000000321500000204000000000000,Razer Panthera PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000321500000104000000000000,Razer Panthera PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
03000000321500000010000000000000,Razer Raiju,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
@@ -657,6 +663,8 @@
03000000ba2200000701000000000000,Technology Innovation PS2 Adapter,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b2,platform:Windows,
03000000c61100001000000000000000,Tencent Xianyou Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows,
03000000790000002601000000000000,TGZ,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows,
03000000591c00002400000000000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
03000000591c00002600000000000000,THEGamepad,a:b2,b:b1,back:b6,leftx:a0,lefty:a1,start:b7,x:b3,y:b0,platform:Windows,
030000004f04000015b3000000000000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
030000004f04000023b3000000000000,Thrustmaster Dual Trigger PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f0400000ed0000000000000,ThrustMaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
@@ -812,6 +820,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000050b00000579000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b42,paddle1:b9,paddle2:b11,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
03000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b23,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
03000000503200000110000047010000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X,
03000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Mac OS X,
03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000d62000002a79000000010000,BDA PS4 Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
@@ -824,8 +834,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000791d00000103000009010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X,
030000006e0500000720000010020000,Elecom JC-W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Mac OS X,
030000006f0e00008401000003010000,Faceoff Premiere Wired Pro Controller for Nintendo Switch,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b4,paddle2:b5,paddle3:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Mac OS X,
03000000151900004000000001000000,Flydigi Vader 2,a:b14,b:b15,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b0,y:b1,platform:Mac OS X,
03000000b40400001124000001040000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000b40400001224000003030000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000790000004618000000010000,GameCube Controller Adapter,a:b4,b:b0,dpdown:b56,dpleft:b60,dpright:b52,dpup:b48,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X,
03000000ac0500001a06000002020000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000ad1b000001f9000000000000,Gamestop BB070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
@@ -889,6 +900,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000790000000018000000000000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,
03000000790000000018000000010000,Mayflash Wii U Pro Adapter,a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X,
030000005e0400002800000002010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Mac OS X,
030000005e0400000300000006010000,Microsoft SideWinder,a:b0,b:b1,back:b9,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Mac OS X,
030000005e0400000700000006010000,Microsoft SideWinder,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Mac OS X,
030000005e0400002700000001010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Mac OS X,
03000000d62000007162000001000000,Moga Pro 2,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,
03000000c62400002a89000000010000,MOGA XP5A Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
@@ -971,6 +984,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000000d0f0000f600000000010000,Switch Hori Pad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000457500002211000000010000,SZMY Power PC Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000790000001c18000003100000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000591c00002400000021000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X,
03000000591c00002600000021000000,THEGamepad,a:b2,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Mac OS X,
030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X,
030000004f0400000ed0000000020000,ThrustMaster eSwap Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X,
@@ -1063,8 +1078,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00001290000011010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00006228000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000121000011010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Linux,
05000000c82d00000121000000010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,x:b3,y:b4,back:b10,guide:b12,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,platform:Linux,
03000000c82d00000260000011010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
@@ -1072,6 +1085,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00000760000011010000,8BitDo Ultimate Wireless,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00001230000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001330000011010000,8BitDo Ultimate Wireless,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b23,paddle2:b19,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00000121000011010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000c82d00000121000000010000,8BitDo Xbox One SN30 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
05000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
@@ -1129,8 +1144,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006e0500000720000010010000,Elecom W01U,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux,
030000007d0400000640000010010000,Eliminator AfterShock,a:b1,b:b2,back:b9,dpdown:+a3,dpleft:-a5,dpright:+a5,dpup:-a3,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a4,righty:a2,start:b8,x:b0,y:b3,platform:Linux,
03000000430b00000300000000010000,EMS Production PS2 Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a5,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03005036852100000201000010010000,Final Fantasy XIV Online Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000b40400001224000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
030000007e0500003703000000000000,GameCube Adapter,a:b0,b:b1,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b2,platform:Linux,
19000000030000000300000002030000,GameForce Controller,a:b1,b:b0,back:b8,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a1,lefty:a0,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
03000000ac0500005b05000010010000,GameSir G3w,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
@@ -1191,6 +1208,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000341a000005f7000010010000,HuiJia GameCube Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
05000000242e00000b20000001000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Linux,
03000000242e0000ff0b000011010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Linux,
03000000242e00006a38000010010000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Linux,
03000000242e00008816000001010000,Hyperkin X91,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000f00300008d03000011010000,HyperX Clutch,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000830500006020000010010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,
@@ -1255,10 +1273,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000790000000318000011010000,Mayflash Wii DolphinBar,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux,
03000000790000000018000011010000,Mayflash Wii U Pro Adapter,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000b50700001203000010010000,Mega World Logic 3 Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
03000000b50700004f00000000010000,Mega World Logic 3 Controller,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b1,platform:Linux,
03000000780000000600000010010000,Microntek Joystick,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
030000005e0400002800000000010000,Microsoft Dual Strike,a:b3,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,rightshoulder:b7,rightx:a0,righty:a1~,start:b5,x:b1,y:b0,platform:Linux,
030000005e0400000e00000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,
030000005e0400000700000000010000,Microsoft SideWinder Gamepad,a:b0,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux,
030000005e0400000300000000010000,Microsoft SideWinder,a:b0,b:b1,back:b9,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux,
030000005e0400000700000000010000,Microsoft SideWinder,a:b0,b:b1,back:b8,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Linux,
030000005e0400000e00000000010000,Microsoft SideWinder Freestyle Pro,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Linux,
030000005e0400002700000000010000,Microsoft SideWinder Plug and Play,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,righttrigger:b5,x:b2,y:b3,platform:Linux,
030000005e0400008502000000010000,Microsoft Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
030000005e0400008902000021010000,Microsoft Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
@@ -1315,6 +1335,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000007e0500003003000001000000,Nintendo Wii U Pro Controller,a:b0,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
030000000d0500000308000010010000,Nostromo n45 Dual Analog,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b12,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b2,y:b3,platform:Linux,
050000007e0500001920000001000000,NSO N64 Controller,+rightx:b8,+righty:b7,-rightx:b3,-righty:b2,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,righttrigger:b10,start:b9,platform:Linux,
050000007e0500001920000001800000,NSO N64 Controller,+rightx:b10,+righty:b8,-rightx:b9,-righty:b7,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b3,lefttrigger:b2,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b4,righttrigger:b5,start:b6,platform:Linux,
050000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b12,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b13,righttrigger:b8,rightx:a2,righty:a3,start:b10,x:b3,y:b2,platform:Linux,
03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000550900001472000011010000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
@@ -1559,10 +1580,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000005e040000130b000009050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000130b000011050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000130b000013050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
060000005e040000120b000007050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
050000005e040000200b000013050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000450c00002043000010010000,XEOX SL6556 BK,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
05000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b20,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Linux,
03000000c0160000e105000001010000,XinMo Dual Arcade,a:b4,b:b3,back:b6,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b9,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b1,y:b0,platform:Linux,
+1
View File
@@ -28,6 +28,7 @@
in vec2 PSin_t;
layout(location = 0) out vec4 SV_Target0;
layout(binding = 0) uniform sampler2D TextureSampler;
#elif (FXAA_GLSL_VK == 1)
+14 -10
View File
@@ -1,9 +1,5 @@
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
#ifndef PS_SCALE_FACTOR
#define PS_SCALE_FACTOR 1
#endif
struct VS_INPUT
{
float4 p : POSITION;
@@ -24,7 +20,6 @@ cbuffer cb0 : register(b0)
int EMODA;
int EMODC;
int DOFFSET;
int cb0_pad;
};
static const float3x3 rgb2yuv =
@@ -274,16 +269,25 @@ PS_OUTPUT ps_convert_rgba_8i(PS_INPUT input)
uint2 subblock = pos & uint2(7u, 1u);
uint2 coord = block | subblock;
// Compensate for potentially differing page pitch.
uint SBW = uint(EMODA);
uint DBW = uint(EMODC);
uint2 block_xy = coord / uint2(64, 32);
uint block_num = (block_xy.y * (DBW / 128)) + block_xy.x;
uint2 block_offset = uint2((block_num % (SBW / 64)) * 64, (block_num / (SBW / 64)) * 32);
coord = (coord % uint2(64, 32)) + block_offset;
// Apply offset to cols 1 and 2
uint is_col23 = pos.y & 4u;
uint is_col13 = pos.y & 2u;
uint is_col12 = is_col23 ^ (is_col13 << 1);
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
if (floor(PS_SCALE_FACTOR) != PS_SCALE_FACTOR)
coord = uint2(float2(coord) * PS_SCALE_FACTOR);
float ScaleFactor = BGColor.x;
if (floor(ScaleFactor) != ScaleFactor)
coord = uint2(float2(coord) * ScaleFactor);
else
coord *= PS_SCALE_FACTOR;
coord *= uint(ScaleFactor);
float4 pixel = Texture.Load(int3(int2(coord), 0));
float2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
@@ -295,7 +299,7 @@ PS_OUTPUT ps_convert_rgba_8i(PS_INPUT input)
PS_OUTPUT ps_convert_clut_4(PS_INPUT input)
{
// Borrowing the YUV constant buffer.
float2 scale = BGColor.xy;
float scale = BGColor.x;
uint2 offset = uint2(uint(EMODA), uint(EMODC)) + uint(DOFFSET);
// CLUT4 is easy, just two rows of 8x8.
@@ -310,7 +314,7 @@ PS_OUTPUT ps_convert_clut_4(PS_INPUT input)
PS_OUTPUT ps_convert_clut_8(PS_INPUT input)
{
float2 scale = BGColor.xy;
float scale = BGColor.x;
uint2 offset = uint2(uint(EMODA), uint(EMODC));
uint index = min(uint(input.p.x) + uint(DOFFSET), 255u);
+36
View File
@@ -0,0 +1,36 @@
cbuffer vertexBuffer : register(b0)
{
float4x4 ProjectionMatrix;
};
struct VS_INPUT
{
float2 pos : POSITION;
float4 col : COLOR0;
float2 uv : TEXCOORD0;
};
struct PS_INPUT
{
float4 pos : SV_POSITION;
float4 col : COLOR0;
float2 uv : TEXCOORD0;
};
PS_INPUT vs_main(VS_INPUT input)
{
PS_INPUT output;
output.pos = mul(ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));
output.col = input.col;
output.uv = input.uv;
return output;
}
sampler sampler0 : register(s0);
Texture2D texture0 : register(t0);
float4 ps_main(PS_INPUT input) : SV_Target
{
float4 out_col = input.col * texture0.Sample(sampler0, input.uv);
return out_col;
}
+14 -18
View File
@@ -23,7 +23,7 @@ float4 ps_main0(PS_INPUT input) : SV_Target0
const int vpos = int(input.p.y); // vertical position of destination texture
if ((vpos & 1) == field)
return Texture.Sample(Sampler, input.t);
return Texture.SampleLevel(Sampler, input.t, 0);
else
discard;
@@ -34,7 +34,7 @@ float4 ps_main0(PS_INPUT input) : SV_Target0
// Bob shader
float4 ps_main1(PS_INPUT input) : SV_Target0
{
return Texture.Sample(Sampler, input.t);
return Texture.SampleLevel(Sampler, input.t, 0);
}
@@ -42,9 +42,9 @@ float4 ps_main1(PS_INPUT input) : SV_Target0
float4 ps_main2(PS_INPUT input) : SV_Target0
{
float2 vstep = float2(0.0f, ZrH.y);
float4 c0 = Texture.Sample(Sampler, input.t - vstep);
float4 c1 = Texture.Sample(Sampler, input.t);
float4 c2 = Texture.Sample(Sampler, input.t + vstep);
float4 c0 = Texture.SampleLevel(Sampler, input.t - vstep, 0);
float4 c1 = Texture.SampleLevel(Sampler, input.t, 0);
float4 c2 = Texture.SampleLevel(Sampler, input.t + vstep, 0);
return (c0 + c1 * 2 + c2) / 4;
}
@@ -66,15 +66,11 @@ float4 ps_main3(PS_INPUT input) : SV_Target0
const int vres = int(ZrH.z) >> 1; // vertical resolution of source texture
const int lofs = ((((vres + 1) >> 1) << 1) - vres) & bank; // line alignment offset for bank 1
const int vpos = int(input.p.y) + lofs; // vertical position of destination texture
const float2 bofs = float2(0.0f, 0.5f * bank); // vertical offset of the current bank relative to source texture size
const float2 vscale = float2(1.0f, 2.0f); // scaling factor from source to destination texture
const float2 optr = input.t - bofs; // used to check if the current destination line is within the current bank
const float2 iptr = optr * vscale; // pointer to the current pixel in the source texture
// if the index of current destination line belongs to the current fiels we update it, otherwise
// we leave the old line in the destination buffer
if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field))
return Texture.Sample(Sampler, iptr);
if ((vpos & 1) == field)
return Texture.SampleLevel(Sampler, input.t, 0);
else
discard;
@@ -133,13 +129,13 @@ float4 ps_main4(PS_INPUT input) : SV_Target0
// calculating motion, only relevant for missing lines where the "center line" is pointed by p_t1
float4 hn = Texture.Sample(Sampler, p_t0 - lofs); // new high pixel
float4 cn = Texture.Sample(Sampler, p_t1); // new center pixel
float4 ln = Texture.Sample(Sampler, p_t0 + lofs); // new low pixel
float4 hn = Texture.SampleLevel(Sampler, p_t0 - lofs, 0); // new high pixel
float4 cn = Texture.SampleLevel(Sampler, p_t1, 0); // new center pixel
float4 ln = Texture.SampleLevel(Sampler, p_t0 + lofs, 0); // new low pixel
float4 ho = Texture.Sample(Sampler, p_t2 - lofs); // old high pixel
float4 co = Texture.Sample(Sampler, p_t3); // old center pixel
float4 lo = Texture.Sample(Sampler, p_t2 + lofs); // old low pixel
float4 ho = Texture.SampleLevel(Sampler, p_t2 - lofs, 0); // old high pixel
float4 co = Texture.SampleLevel(Sampler, p_t3, 0); // old center pixel
float4 lo = Texture.SampleLevel(Sampler, p_t2 + lofs, 0); // old low pixel
float3 mh = hn.rgb - ho.rgb; // high pixel motion
float3 mc = cn.rgb - co.rgb; // center pixel motion
@@ -164,7 +160,7 @@ float4 ps_main4(PS_INPUT input) : SV_Target0
if ((vpos & 1) == field)
{
// output coordinate present on current field
return Texture.Sample(Sampler, p_t0);
return Texture.SampleLevel(Sampler, p_t0, 0);
}
else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y))
{
+176 -174
View File
@@ -1,5 +1,3 @@
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
#define FMT_32 0
#define FMT_24 1
#define FMT_16 2
@@ -30,12 +28,14 @@
#define PS_ATST 1
#define PS_FOG 0
#define PS_IIP 0
#define PS_CLR_HW 0
#define PS_BLEND_HW 0
#define PS_A_MASKED 0
#define PS_FBA 0
#define PS_FBMASK 0
#define PS_LTF 1
#define PS_TCOFFSETHACK 0
#define PS_POINT_SAMPLER 0
#define PS_REGION_RECT 0
#define PS_SHUFFLE 0
#define PS_READ_BA 0
#define PS_READ16_SRC 0
@@ -45,7 +45,6 @@
#define PS_CHANNEL_FETCH 0
#define PS_TALES_OF_ABYSS_HLE 0
#define PS_URBAN_CHAOS_HLE 0
#define PS_SCALE_FACTOR 1.0
#define PS_HDR 0
#define PS_COLCLIP 0
#define PS_BLEND_A 0
@@ -71,6 +70,7 @@
#define SW_BLEND (PS_BLEND_A || PS_BLEND_B || PS_BLEND_D)
#define SW_BLEND_NEEDS_RT (SW_BLEND && (PS_BLEND_A == 1 || PS_BLEND_B == 1 || PS_BLEND_C == 1 || PS_BLEND_D == 1))
#define SW_AD_TO_HW (PS_BLEND_C == 1 && PS_A_MASKED)
struct VS_INPUT
{
@@ -111,6 +111,8 @@ struct PS_INPUT
#endif
};
#ifdef PIXEL_SHADER
struct PS_OUTPUT
{
#if !PS_NO_COLOR
@@ -134,21 +136,6 @@ Texture2D<float4> RtTexture : register(t2);
Texture2D<float> PrimMinTexture : register(t3);
SamplerState TextureSampler : register(s0);
#ifdef DX12
cbuffer cb0 : register(b0)
#else
cbuffer cb0
#endif
{
float2 VertexScale;
float2 VertexOffset;
float2 TextureScale;
float2 TextureOffset;
float2 PointSize;
uint MaxDepth;
uint pad_cb0;
};
#ifdef DX12
cbuffer cb1 : register(b1)
#else
@@ -169,12 +156,16 @@ cbuffer cb1
float2 TC_OffsetHack;
float2 STScale;
float4x4 DitherMatrix;
float ScaledScaleFactor;
float RcpScaleFactor;
};
float4 sample_c(float2 uv, float uv_w)
{
#if PS_TEX_IS_FB == 1
return RtTexture.Load(int3(int2(uv * WH.zw), 0));
#elif PS_REGION_RECT == 1
return Texture.Load(int3(int2(uv), 0));
#else
if (PS_POINT_SAMPLER)
{
@@ -238,7 +229,15 @@ float4 clamp_wrap_uv(float4 uv)
if(PS_WMS == PS_WMT)
{
if(PS_WMS == 2)
if(PS_REGION_RECT != 0 && PS_WMS == 0)
{
uv = frac(uv);
}
else if(PS_REGION_RECT != 0 && PS_WMS == 1)
{
uv = saturate(uv);
}
else if(PS_WMS == 2)
{
uv = clamp(uv, MinMax.xyxy, MinMax.zwzw);
}
@@ -254,7 +253,15 @@ float4 clamp_wrap_uv(float4 uv)
}
else
{
if(PS_WMS == 2)
if(PS_REGION_RECT != 0 && PS_WMS == 0)
{
uv.xz = frac(uv.xz);
}
else if(PS_REGION_RECT != 0 && PS_WMS == 1)
{
uv.xz = saturate(uv.xz);
}
else if(PS_WMS == 2)
{
uv.xz = clamp(uv.xz, MinMax.xx, MinMax.zz);
}
@@ -265,7 +272,15 @@ float4 clamp_wrap_uv(float4 uv)
#endif
uv.xz = (float2)(((uint2)(uv.xz * tex_size.xx) & asuint(MinMax.xx)) | asuint(MinMax.zz)) / tex_size.xx;
}
if(PS_WMT == 2)
if(PS_REGION_RECT != 0 && PS_WMT == 0)
{
uv.yw = frac(uv.yw);
}
else if(PS_REGION_RECT != 0 && PS_WMT == 1)
{
uv.yw = saturate(uv.yw);
}
else if(PS_WMT == 2)
{
uv.yw = clamp(uv.yw, MinMax.yy, MinMax.ww);
}
@@ -278,6 +293,12 @@ float4 clamp_wrap_uv(float4 uv)
}
}
if(PS_REGION_RECT != 0)
{
// Normalized -> Integer Coordinates.
uv = clamp(uv * WH.zwzw + STRange.xyxy, STRange.xyxy, STRange.zwzw);
}
return uv;
}
@@ -400,9 +421,13 @@ int2 clamp_wrap_uv_depth(int2 uv)
float4 sample_depth(float2 st, float2 pos)
{
float2 uv_f = (float2)clamp_wrap_uv_depth(int2(st)) * (float2)PS_SCALE_FACTOR * (float2)(1.0f / 16.0f);
int2 uv = (int2)uv_f;
float2 uv_f = (float2)clamp_wrap_uv_depth(int2(st)) * (float2)ScaledScaleFactor;
#if PS_REGION_RECT == 1
uv_f = clamp(uv_f + STRange.xy, STRange.xy, STRange.zw);
#endif
int2 uv = (int2)uv_f;
float4 t = (float4)(0.0f);
if (PS_TALES_OF_ABYSS_HLE == 1)
@@ -561,7 +586,7 @@ float4 sample_color(float2 st, float uv_w)
float4x4 c;
float2 dd;
if (PS_LTF == 0 && PS_AEM_FMT == FMT_32 && PS_PAL_FMT == 0 && PS_WMS < 2 && PS_WMT < 2)
if (PS_LTF == 0 && PS_AEM_FMT == FMT_32 && PS_PAL_FMT == 0 && PS_REGION_RECT == 0 && PS_WMS < 2 && PS_WMT < 2)
{
c[0] = sample_c(st, uv_w);
}
@@ -740,10 +765,10 @@ void ps_dither(inout float3 C, float2 pos_xy)
if (PS_DITHER == 2)
fpos = int2(pos_xy);
else
fpos = int2(pos_xy / (float)PS_SCALE_FACTOR);
fpos = int2(pos_xy * RcpScaleFactor);
float value = DitherMatrix[fpos.x & 3][fpos.y & 3];
if (PS_ROUND_INV != 0)
if (PS_ROUND_INV)
C -= value;
else
C += value;
@@ -756,7 +781,7 @@ void ps_color_clamp_wrap(inout float3 C)
// so we need to limit the color depth on dithered items
if (SW_BLEND || PS_DITHER || PS_FBMASK)
{
if (PS_DFMT == FMT_16 && PS_BLEND_MIX == 0 && PS_ROUND_INV != 0)
if (PS_DFMT == FMT_16 && PS_BLEND_MIX == 0 && PS_ROUND_INV)
C += 7.0f; // Need to round up, not down since the shader will invert
// Standard Clamp
@@ -798,9 +823,9 @@ void ps_blend(inout float4 Color, inout float4 As_rgba, float2 pos_xy)
float3 D = (PS_BLEND_D == 0) ? Cs : ((PS_BLEND_D == 1) ? Cd : (float3)0.0f);
// As/Af clamp alpha for Blend mix
// We shouldn't clamp blend mix with clr1 as we want alpha higher
// We shouldn't clamp blend mix with blend hw 1 as we want alpha higher
float C_clamped = C;
if (PS_BLEND_MIX > 0 && PS_CLR_HW != 1)
if (PS_BLEND_MIX > 0 && PS_BLEND_HW != 1)
C_clamped = min(C_clamped, 1.0f);
if (PS_BLEND_A == PS_BLEND_B)
@@ -819,11 +844,10 @@ void ps_blend(inout float4 Color, inout float4 As_rgba, float2 pos_xy)
else
Color.rgb = trunc(((A - B) * C) + D);
if (PS_CLR_HW == 1)
if (PS_BLEND_HW == 1)
{
// Replace Af with As so we can do proper compensation for Alpha.
if (PS_BLEND_C == 2)
As_rgba = (float4)Af;
// As or Af
As_rgba.rgb = (float3)C;
// Subtract 1 for alpha to compensate for the changed equation,
// if c.rgb > 255.0f then we further need to adjust alpha accordingly,
// we pick the lowest overflow from all colors because it's the safest,
@@ -832,7 +856,7 @@ void ps_blend(inout float4 Color, inout float4 As_rgba, float2 pos_xy)
float3 alpha_compensate = max((float3)1.0f, Color.rgb / (float3)255.0f);
As_rgba.rgb -= alpha_compensate;
}
else if (PS_CLR_HW == 2)
else if (PS_BLEND_HW == 2)
{
// Compensate slightly for Cd*(As + 1) - Cs*As.
// The initial factor we chose is 1 (0.00392)
@@ -842,16 +866,26 @@ void ps_blend(inout float4 Color, inout float4 As_rgba, float2 pos_xy)
float color_compensate = 1.0f * (C + 1.0f);
Color.rgb -= (float3)color_compensate;
}
else if (PS_BLEND_HW == 3)
{
// As, Ad or Af clamped.
As_rgba.rgb = (float3)C_clamped;
// Cs*(Alpha + 1) might overflow, if it does then adjust alpha value
// that is sent on second output to compensate.
float3 overflow_check = (Color.rgb - (float3)255.0f) / 255.0f;
float3 alpha_compensate = max((float3)0.0f, overflow_check);
As_rgba.rgb -= alpha_compensate;
}
}
else
{
if (PS_CLR_HW == 1 || PS_CLR_HW == 5)
if (PS_BLEND_HW == 1)
{
// Needed for Cd * (As/Ad/F + 1) blending modes
Color.rgb = (float3)255.0f;
}
else if (PS_CLR_HW == 2 || PS_CLR_HW == 4)
else if (PS_BLEND_HW == 2)
{
// Cd*As,Cd*Ad or Cd*F
@@ -860,12 +894,16 @@ void ps_blend(inout float4 Color, inout float4 As_rgba, float2 pos_xy)
Color.rgb = max((float3)0.0f, (Alpha - (float3)1.0f));
Color.rgb *= (float3)255.0f;
}
else if (PS_CLR_HW == 3)
else if (PS_BLEND_HW == 3)
{
// Needed for Cs*Ad, Cs*Ad + Cd, Cd - Cs*Ad
// Multiply Color.rgb by (255/128) to compensate for wrong Ad/255 value
Color.rgb *= (255.0f / 128.0f);
// Multiply Color.rgb by (255/128) to compensate for wrong Ad/255 value when rgb are below 128.
// When any color channel is higher than 128 then adjust the compensation automatically
// to give us more accurate colors, otherwise they will be wrong.
// The higher the value (>128) the lower the compensation will be.
float max_color = max(max(Color.r, Color.g), Color.b);
float color_compensate = 255.0f / max(128.0f, max_color);
Color.rgb *= (float3)color_compensate;
}
}
}
@@ -930,7 +968,7 @@ PS_OUTPUT ps_main(PS_INPUT input)
}
float4 alpha_blend;
if (PS_BLEND_C == 1 && PS_CLR_HW > 3)
if (SW_AD_TO_HW)
{
float4 RT = trunc(RtTexture.Load(int3(input.p.xy, 0)) * 255.0f + 0.1f);
alpha_blend = (float4)(RT.a / 128.0f);
@@ -1009,10 +1047,29 @@ PS_OUTPUT ps_main(PS_INPUT input)
return output;
}
#endif // PIXEL_SHADER
//////////////////////////////////////////////////////////////////////
// Vertex Shader
//////////////////////////////////////////////////////////////////////
#ifdef VERTEX_SHADER
#ifdef DX12
cbuffer cb0 : register(b0)
#else
cbuffer cb0
#endif
{
float2 VertexScale;
float2 VertexOffset;
float2 TextureScale;
float2 TextureOffset;
float2 PointSize;
uint MaxDepth;
uint BaseVertex; // Only used in DX11.
};
VS_OUTPUT vs_main(VS_INPUT input)
{
// Clamp to max depth, gs doesn't wrap
@@ -1065,156 +1122,101 @@ VS_OUTPUT vs_main(VS_INPUT input)
return output;
}
//////////////////////////////////////////////////////////////////////
// Geometry Shader
//////////////////////////////////////////////////////////////////////
#if VS_EXPAND != 0
#if GS_FORWARD_PRIMID
#define PRIMID_IN , uint primid : SV_PrimitiveID
#define VS2PS(x) vs2ps_impl(x, primid)
PS_INPUT vs2ps_impl(VS_OUTPUT vs, uint primid)
struct VS_RAW_INPUT
{
PS_INPUT o;
o.p = vs.p;
o.t = vs.t;
o.ti = vs.ti;
o.c = vs.c;
o.primid = primid;
return o;
}
float2 ST;
uint RGBA;
float Q;
uint XY;
uint Z;
uint UV;
uint FOG;
};
StructuredBuffer<VS_RAW_INPUT> vertices : register(t0);
VS_INPUT load_vertex(uint index)
{
#ifdef DX12
VS_RAW_INPUT raw = vertices.Load(index);
#else
#define PRIMID_IN
#define VS2PS(x) vs2ps_impl(x)
PS_INPUT vs2ps_impl(VS_OUTPUT vs)
{
PS_INPUT o;
o.p = vs.p;
o.t = vs.t;
o.ti = vs.ti;
o.c = vs.c;
return o;
}
VS_RAW_INPUT raw = vertices.Load(BaseVertex + index);
#endif
#if GS_PRIM == 0
[maxvertexcount(6)]
void gs_main(point VS_OUTPUT input[1], inout TriangleStream<PS_INPUT> stream PRIMID_IN)
{
// Transform a point to a NxN sprite
PS_INPUT Point = VS2PS(input[0]);
// Get new position
float4 lt_p = input[0].p;
float4 rb_p = input[0].p + float4(PointSize.x, PointSize.y, 0.0f, 0.0f);
float4 lb_p = rb_p;
float4 rt_p = rb_p;
lb_p.x = lt_p.x;
rt_p.y = lt_p.y;
// Triangle 1
Point.p = lt_p;
stream.Append(Point);
Point.p = lb_p;
stream.Append(Point);
Point.p = rt_p;
stream.Append(Point);
// Triangle 2
Point.p = lb_p;
stream.Append(Point);
Point.p = rt_p;
stream.Append(Point);
Point.p = rb_p;
stream.Append(Point);
VS_INPUT vert;
vert.st = raw.ST;
vert.c = uint4(raw.RGBA & 0xFFu, (raw.RGBA >> 8) & 0xFFu, (raw.RGBA >> 16) & 0xFFu, raw.RGBA >> 24);
vert.q = raw.Q;
vert.p = uint2(raw.XY & 0xFFFFu, raw.XY >> 16);
vert.z = raw.Z;
vert.uv = uint2(raw.UV & 0xFFFFu, raw.UV >> 16);
vert.f = float4(float(raw.FOG & 0xFFu), float((raw.FOG >> 8) & 0xFFu), float((raw.FOG >> 16) & 0xFFu), float(raw.FOG >> 24)) / 255.0f;
return vert;
}
#elif GS_PRIM == 1
[maxvertexcount(6)]
void gs_main(line VS_OUTPUT input[2], inout TriangleStream<PS_INPUT> stream PRIMID_IN)
VS_OUTPUT vs_main_expand(uint vid : SV_VertexID)
{
// Transform a line to a thick line-sprite
PS_INPUT left = VS2PS(input[0]);
PS_INPUT right = VS2PS(input[1]);
float2 lt_p = input[0].p.xy;
float2 rt_p = input[1].p.xy;
#if VS_EXPAND == 1 // Point
// Potentially there is faster math
float2 line_vector = normalize(rt_p.xy - lt_p.xy);
VS_OUTPUT vtx = vs_main(load_vertex(vid >> 2));
vtx.p.x += ((vid & 1u) != 0u) ? PointSize.x : 0.0f;
vtx.p.y += ((vid & 2u) != 0u) ? PointSize.y : 0.0f;
return vtx;
#elif VS_EXPAND == 2 // Line
uint vid_base = vid >> 2;
bool is_bottom = vid & 2;
bool is_right = vid & 1;
// All lines will be a pair of vertices next to each other
// Since DirectX uses provoking vertex first, the bottom point will be the lower of the two
uint vid_other = is_bottom ? vid_base + 1 : vid_base - 1;
VS_OUTPUT vtx = vs_main(load_vertex(vid_base));
VS_OUTPUT other = vs_main(load_vertex(vid_other));
float2 line_vector = normalize(vtx.p.xy - other.p.xy);
float2 line_normal = float2(line_vector.y, -line_vector.x);
float2 line_width = (line_normal * PointSize) / 2;
// line_normal is inverted for bottom point
float2 offset = (is_bottom ^ is_right) ? line_width : -line_width;
vtx.p.xy += offset;
lt_p -= line_width;
rt_p -= line_width;
float2 lb_p = input[0].p.xy + line_width;
float2 rb_p = input[1].p.xy + line_width;
// Lines will be run as (0 1 2) (1 2 3)
// This means that both triangles will have a point based off the top line point as their first point
// So we don't have to do anything for !IIP
#if GS_IIP == 0
left.c = right.c;
#endif
return vtx;
// Triangle 1
left.p.xy = lt_p;
stream.Append(left);
#elif VS_EXPAND == 3 // Sprite
left.p.xy = lb_p;
stream.Append(left);
// Sprite points are always in pairs
uint vid_base = vid >> 1;
uint vid_lt = vid_base & ~1u;
uint vid_rb = vid_base | 1u;
right.p.xy = rt_p;
stream.Append(right);
stream.RestartStrip();
VS_OUTPUT lt = vs_main(load_vertex(vid_lt));
VS_OUTPUT rb = vs_main(load_vertex(vid_rb));
VS_OUTPUT vtx = rb;
// Triangle 2
left.p.xy = lb_p;
stream.Append(left);
bool is_right = ((vid & 1u) != 0u);
vtx.p.x = is_right ? lt.p.x : vtx.p.x;
vtx.t.x = is_right ? lt.t.x : vtx.t.x;
vtx.ti.xz = is_right ? lt.ti.xz : vtx.ti.xz;
right.p.xy = rt_p;
stream.Append(right);
bool is_bottom = ((vid & 2u) != 0u);
vtx.p.y = is_bottom ? lt.p.y : vtx.p.y;
vtx.t.y = is_bottom ? lt.t.y : vtx.t.y;
vtx.ti.yw = is_bottom ? lt.ti.yw : vtx.ti.yw;
right.p.xy = rb_p;
stream.Append(right);
stream.RestartStrip();
}
#elif GS_PRIM == 3
[maxvertexcount(4)]
void gs_main(line VS_OUTPUT input[2], inout TriangleStream<PS_INPUT> stream PRIMID_IN)
{
PS_INPUT lt = VS2PS(input[0]);
PS_INPUT rb = VS2PS(input[1]);
// flat depth
lt.p.z = rb.p.z;
// flat fog and texture perspective
lt.t.zw = rb.t.zw;
// flat color
lt.c = rb.c;
// Swap texture and position coordinate
PS_INPUT lb = rb;
lb.p.x = lt.p.x;
lb.t.x = lt.t.x;
lb.ti.x = lt.ti.x;
lb.ti.z = lt.ti.z;
PS_INPUT rt = rb;
rt.p.y = lt.p.y;
rt.t.y = lt.t.y;
rt.ti.y = lt.ti.y;
rt.ti.w = lt.ti.w;
stream.Append(lt);
stream.Append(lb);
stream.Append(rt);
stream.Append(rb);
}
return vtx;
#endif
#endif
}
#endif // VS_EXPAND
#endif // VERTEX_SHADER
@@ -1,101 +0,0 @@
//#version 420 // Keep it for editor detection
//////////////////////////////////////////////////////////////////////
// Common Interface Definition
//////////////////////////////////////////////////////////////////////
#ifdef VERTEX_SHADER
#if !pGL_ES
out gl_PerVertex {
vec4 gl_Position;
float gl_PointSize;
#if !pGL_ES
float gl_ClipDistance[1];
#endif
};
#endif
#endif
#ifdef GEOMETRY_SHADER
#if !pGL_ES
in gl_PerVertex {
vec4 gl_Position;
float gl_PointSize;
#if !pGL_ES
float gl_ClipDistance[1];
#endif
} gl_in[];
out gl_PerVertex {
vec4 gl_Position;
float gl_PointSize;
#if !pGL_ES
float gl_ClipDistance[1];
#endif
};
#endif
#endif
//////////////////////////////////////////////////////////////////////
// Constant Buffer Definition
//////////////////////////////////////////////////////////////////////
// Performance note, some drivers (nouveau) will validate all Constant Buffers
// even if only one was updated.
#if defined(VERTEX_SHADER) || defined(GEOMETRY_SHADER)
layout(std140, binding = 1) uniform cb20
{
vec2 VertexScale;
vec2 VertexOffset;
vec2 TextureScale;
vec2 TextureOffset;
vec2 PointSize;
uint MaxDepth;
uint pad_cb20;
};
#endif
#if defined(VERTEX_SHADER) || defined(FRAGMENT_SHADER)
layout(std140, binding = 0) uniform cb21
{
vec3 FogColor;
float AREF;
vec4 WH;
vec2 TA;
float MaxDepthPS;
float Af;
uvec4 FbMask;
vec4 HalfTexel;
vec4 MinMax;
vec4 STRange;
ivec4 ChannelShuffle;
vec2 TC_OffsetHack;
vec2 STScale;
mat4 DitherMatrix;
};
#endif
//////////////////////////////////////////////////////////////////////
// Default Sampler
//////////////////////////////////////////////////////////////////////
#ifdef FRAGMENT_SHADER
layout(binding = 0) uniform sampler2D TextureSampler;
#endif
+19 -7
View File
@@ -35,6 +35,8 @@ in vec4 PSin_p;
in vec2 PSin_t;
in vec4 PSin_c;
layout(binding = 0) uniform sampler2D TextureSampler;
// Give a different name so I remember there is a special case!
#if defined(ps_convert_rgba8_16bits) || defined(ps_convert_float32_32bits)
layout(location = 0) out uint SV_Target1;
@@ -234,6 +236,10 @@ void ps_convert_rgb5a1_float16_biln()
#endif
#ifdef ps_convert_rgba_8i
uniform uint SBW;
uniform uint DBW;
uniform float ScaleFactor;
void ps_convert_rgba_8i()
{
// Convert a RGBA texture into a 8 bits packed texture
@@ -252,16 +258,22 @@ void ps_convert_rgba_8i()
uvec2 subblock = pos & uvec2(7u, 1u);
uvec2 coord = block | subblock;
// Compensate for potentially differing page pitch.
uvec2 block_xy = coord / uvec2(64u, 32u);
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
uvec2 block_offset = uvec2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 32u);
coord = (coord % uvec2(64u, 32u)) + block_offset;
// Apply offset to cols 1 and 2
uint is_col23 = pos.y & 4u;
uint is_col13 = pos.y & 2u;
uint is_col12 = is_col23 ^ (is_col13 << 1);
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
if (floor(PS_SCALE_FACTOR) != PS_SCALE_FACTOR)
coord = uvec2(vec2(coord) * PS_SCALE_FACTOR);
if (floor(ScaleFactor) != ScaleFactor)
coord = uvec2(vec2(coord) * ScaleFactor);
else
coord *= uvec2(PS_SCALE_FACTOR);
coord *= uvec2(ScaleFactor);
vec4 pixel = texelFetch(TextureSampler, ivec2(coord), 0);
vec2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
@@ -316,7 +328,7 @@ void ps_hdr_resolve()
#ifdef ps_convert_clut_4
uniform uvec3 offset;
uniform vec2 scale;
uniform float scale;
void ps_convert_clut_4()
{
@@ -324,14 +336,14 @@ void ps_convert_clut_4()
uint index = uint(gl_FragCoord.x) + offset.z;
uvec2 pos = uvec2(index % 8u, index / 8u);
ivec2 final = ivec2(floor(vec2(offset.xy + pos) * scale));
ivec2 final = ivec2(floor(vec2(offset.xy + pos) * vec2(scale)));
SV_Target0 = texelFetch(TextureSampler, final, 0);
}
#endif
#ifdef ps_convert_clut_8
uniform uvec3 offset;
uniform vec2 scale;
uniform float scale;
void ps_convert_clut_8()
{
@@ -344,7 +356,7 @@ void ps_convert_clut_8()
pos.x = (index % 8u) + ((subgroup >= 2u) ? 8u : 0u);
pos.y = ((index / 32u) * 2u) + (subgroup % 2u);
ivec2 final = ivec2(floor(vec2(offset.xy + pos) * scale));
ivec2 final = ivec2(floor(vec2(offset.xy + pos) * vec2(scale)));
SV_Target0 = texelFetch(TextureSampler, final, 0);
}
#endif
+35
View File
@@ -0,0 +1,35 @@
#ifdef VERTEX_SHADER
layout(location = 0) in vec2 Position;
layout(location = 1) in vec2 UV;
layout(location = 2) in vec4 Color;
uniform mat4 ProjMtx;
out vec2 Frag_UV;
out vec4 Frag_Color;
void vs_main()
{
Frag_UV = UV;
Frag_Color = Color;
gl_Position = ProjMtx * vec4(Position.xy, 0.0, 1.0);
}
#endif
#ifdef FRAGMENT_SHADER
layout(binding = 0) uniform sampler2D Texture;
in vec2 Frag_UV;
in vec4 Frag_Color;
layout(location = 0) out vec4 Out_Color;
void ps_main()
{
Out_Color = Frag_Color * texture(Texture, Frag_UV.st);
}
#endif
+16 -18
View File
@@ -8,6 +8,8 @@ in vec4 PSin_c;
uniform vec4 ZrH;
layout(binding = 0) uniform sampler2D TextureSampler;
layout(location = 0) out vec4 SV_Target0;
@@ -19,7 +21,7 @@ void ps_main0()
int vpos = int(gl_FragCoord.y); // vertical position of destination texture
if ((vpos & 1) == field)
SV_Target0 = texture(TextureSampler, PSin_t);
SV_Target0 = textureLod(TextureSampler, PSin_t, 0);
else
discard;
}
@@ -28,7 +30,7 @@ void ps_main0()
// Bob shader
void ps_main1()
{
SV_Target0 = texture(TextureSampler, PSin_t);
SV_Target0 = textureLod(TextureSampler, PSin_t, 0);
}
@@ -36,9 +38,9 @@ void ps_main1()
void ps_main2()
{
vec2 vstep = vec2(0.0f, ZrH.y);
vec4 c0 = texture(TextureSampler, PSin_t - vstep);
vec4 c1 = texture(TextureSampler, PSin_t);
vec4 c2 = texture(TextureSampler, PSin_t + vstep);
vec4 c0 = textureLod(TextureSampler, PSin_t - vstep, 0);
vec4 c1 = textureLod(TextureSampler, PSin_t, 0);
vec4 c2 = textureLod(TextureSampler, PSin_t + vstep, 0);
SV_Target0 = (c0 + c1 * 2.0f + c2) / 4.0f;
}
@@ -60,15 +62,11 @@ void ps_main3()
int vres = int(ZrH.z) >> 1; // vertical resolution of source texture
int lofs = ((((vres + 1) >> 1) << 1) - vres) & bank; // line alignment offset for bank 1
int vpos = int(gl_FragCoord.y) + lofs; // vertical position of destination texture
vec2 bofs = vec2(0.0f, 0.5f * float(bank)); // vertical offset of the current bank relative to source texture size
vec2 vscale = vec2(1.0f, 2.0f); // scaling factor from source to destination texture
vec2 optr = PSin_t - bofs; // used to check if the current destination line is within the current bank
vec2 iptr = optr * vscale; // pointer to the current pixel in the source texture
// if the index of current destination line belongs to the current fiels we update it, otherwise
// we leave the old line in the destination buffer
if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field))
SV_Target0 = texture(TextureSampler, iptr);
if ((vpos & 1) == field)
SV_Target0 = textureLod(TextureSampler, PSin_t, 0);
else
discard;
}
@@ -126,13 +124,13 @@ void ps_main4()
// calculating motion, only relevant for missing lines where the "center line" is pointed
// by p_t1
vec4 hn = texture(TextureSampler, p_t0 - lofs); // new high pixel
vec4 cn = texture(TextureSampler, p_t1); // new center pixel
vec4 ln = texture(TextureSampler, p_t0 + lofs); // new low pixel
vec4 hn = textureLod(TextureSampler, p_t0 - lofs, 0); // new high pixel
vec4 cn = textureLod(TextureSampler, p_t1, 0); // new center pixel
vec4 ln = textureLod(TextureSampler, p_t0 + lofs, 0); // new low pixel
vec4 ho = texture(TextureSampler, p_t2 - lofs); // old high pixel
vec4 co = texture(TextureSampler, p_t3); // old center pixel
vec4 lo = texture(TextureSampler, p_t2 + lofs); // old low pixel
vec4 ho = textureLod(TextureSampler, p_t2 - lofs, 0); // old high pixel
vec4 co = textureLod(TextureSampler, p_t3, 0); // old center pixel
vec4 lo = textureLod(TextureSampler, p_t2 + lofs, 0); // old low pixel
vec3 mh = hn.rgb - ho.rgb; // high pixel motion
vec3 mc = cn.rgb - co.rgb; // center pixel motion
@@ -158,7 +156,7 @@ void ps_main4()
if ((vpos & 1) == field)
{
// output coordinate present on current field
SV_Target0 = texture(TextureSampler, p_t0);
SV_Target0 = textureLod(TextureSampler, p_t0, 0);
}
else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y))
{
+2
View File
@@ -8,6 +8,8 @@ in vec4 PSin_c;
uniform vec4 BGColor;
layout(binding = 0) uniform sampler2D TextureSampler;
layout(location = 0) out vec4 SV_Target0;
void ps_main0()
@@ -46,6 +46,8 @@ in vec4 PSin_p;
in vec2 PSin_t;
in vec4 PSin_c;
layout(binding = 0) uniform sampler2D TextureSampler;
layout(location = 0) out vec4 SV_Target0;
vec4 sample_c()
@@ -17,6 +17,8 @@ in vec4 PSin_p;
in vec2 PSin_t;
in vec4 PSin_c;
layout(binding = 0) uniform sampler2D TextureSampler;
layout(location = 0) out vec4 SV_Target0;
// For all settings: 1.0 = 100% 0.5=50% 1.5 = 150%
+101 -49
View File
@@ -1,15 +1,9 @@
//#version 420 // Keep it for text editor detection
// Require for bit operation
//#extension GL_ARB_gpu_shader5 : enable
#define FMT_32 0
#define FMT_24 1
#define FMT_16 2
// APITRACE_DEBUG enables forced pixel output to easily detect
// the fragment computed by primitive
#define APITRACE_DEBUG 0
// TEX_COORD_DEBUG output the uv coordinate as color. It is useful
// to detect bad sampling due to upscaling
//#define TEX_COORD_DEBUG
@@ -21,16 +15,41 @@
#define SW_BLEND (PS_BLEND_A || PS_BLEND_B || PS_BLEND_D)
#define SW_BLEND_NEEDS_RT (SW_BLEND && (PS_BLEND_A == 1 || PS_BLEND_B == 1 || PS_BLEND_C == 1 || PS_BLEND_D == 1))
#define SW_AD_TO_HW (PS_BLEND_C == 1 && PS_CLR_HW > 3)
#define SW_AD_TO_HW (PS_BLEND_C == 1 && PS_A_MASKED)
#define PS_PRIMID_INIT (PS_DATE == 1 || PS_DATE == 2)
#define NEEDS_RT_EARLY (PS_TEX_IS_FB == 1 || PS_DATE >= 5)
#define NEEDS_RT (NEEDS_RT_EARLY || (!PS_PRIMID_INIT && (PS_FBMASK || SW_BLEND_NEEDS_RT || SW_AD_TO_HW)))
#define NEEDS_TEX (PS_TFX != 4)
#ifdef FRAGMENT_SHADER
layout(std140, binding = 0) uniform cb21
{
vec3 FogColor;
float AREF;
vec4 WH;
vec2 TA;
float MaxDepthPS;
float Af;
uvec4 FbMask;
vec4 HalfTexel;
vec4 MinMax;
vec4 STRange;
ivec4 ChannelShuffle;
vec2 TC_OffsetHack;
vec2 STScale;
mat4 DitherMatrix;
float ScaledScaleFactor;
float RcpScaleFactor;
};
#if !defined(BROKEN_DRIVER) && (pGL_ES || defined(GL_ARB_enhanced_layouts) && GL_ARB_enhanced_layouts)
layout(location = 0)
#endif
in SHADER
{
vec4 t_float;
@@ -70,7 +89,10 @@ in SHADER
#endif
#endif
#if NEEDS_TEX
layout(binding = 0) uniform sampler2D TextureSampler;
layout(binding = 1) uniform sampler2D PaletteSampler;
#endif
#if !HAS_FRAMEBUFFER_FETCH && NEEDS_RT
layout(binding = 2) uniform sampler2D RtSampler; // note 2 already use by the image below
@@ -94,10 +116,14 @@ vec4 fetch_rt()
#endif
}
#if NEEDS_TEX
vec4 sample_c(vec2 uv)
{
#if PS_TEX_IS_FB == 1
return fetch_rt();
#elif PS_REGION_RECT
return texelFetch(TextureSampler, ivec2(uv), 0);
#else
#if PS_POINT_SAMPLER
@@ -163,7 +189,11 @@ vec4 clamp_wrap_uv(vec4 uv)
#if PS_WMS == PS_WMT
#if PS_WMS == 2
#if PS_REGION_RECT == 1 && PS_WMS == 0
uv_out = fract(uv);
#elif PS_REGION_RECT == 1 && PS_WMS == 1
uv_out = clamp(uv, vec4(0.0f), vec4(1.0f));
#elif PS_WMS == 2
uv_out = clamp(uv, MinMax.xyxy, MinMax.zwzw);
#elif PS_WMS == 3
#if PS_FST == 0
@@ -176,7 +206,13 @@ vec4 clamp_wrap_uv(vec4 uv)
#else // PS_WMS != PS_WMT
#if PS_WMS == 2
#if PS_REGION_RECT == 1 && PS_WMS == 0
uv.xz = fract(uv.xz);
#elif PS_REGION_RECT == 1 && PS_WMS == 1
uv.xz = clamp(uv.xz, vec2(0.0f), vec2(1.0f));
#elif PS_WMS == 2
uv_out.xz = clamp(uv.xz, MinMax.xx, MinMax.zz);
#elif PS_WMS == 3
@@ -187,7 +223,13 @@ vec4 clamp_wrap_uv(vec4 uv)
#endif
#if PS_WMT == 2
#if PS_REGION_RECT == 1 && PS_WMT == 0
uv_out.yw = fract(uv.yw);
#elif PS_REGION_RECT == 1 && PS_WMT == 1
uv_out.yw = clamp(uv.yw, vec2(0.0f), vec2(1.0f));
#elif PS_WMT == 2
uv_out.yw = clamp(uv.yw, MinMax.yy, MinMax.ww);
#elif PS_WMT == 3
@@ -197,6 +239,11 @@ vec4 clamp_wrap_uv(vec4 uv)
uv_out.yw = vec2((uvec2(uv.yw * tex_size.yy) & floatBitsToUint(MinMax.yy)) | floatBitsToUint(MinMax.ww)) / tex_size.yy;
#endif
#endif
#if PS_REGION_RECT == 1
// Normalized -> Integer Coordinates.
uv_out = clamp(uv_out * WH.zwzw + STRange.xyxy, STRange.xyxy, STRange.zwzw);
#endif
return uv_out;
@@ -328,10 +375,15 @@ ivec2 clamp_wrap_uv_depth(ivec2 uv)
vec4 sample_depth(vec2 st)
{
vec2 uv_f = vec2(clamp_wrap_uv_depth(ivec2(st))) * vec2(float(PS_SCALE_FACTOR)) * vec2(1.0f/16.0f);
ivec2 uv = ivec2(uv_f);
vec2 uv_f = vec2(clamp_wrap_uv_depth(ivec2(st))) * vec2(ScaledScaleFactor);
#if PS_REGION_RECT == 1
uv_f = clamp(uv_f + STRange.xy, STRange.xy, STRange.zw);
#endif
ivec2 uv = ivec2(uv_f);
vec4 t = vec4(0.0f);
#if PS_TALES_OF_ABYSS_HLE == 1
// Warning: UV can't be used in channel effect
int depth = fetch_raw_depth();
@@ -473,7 +525,7 @@ vec4 sample_color(vec2 st)
vec2 dd;
// FIXME I'm not sure this condition is useful (I think code will be optimized)
#if (PS_LTF == 0 && PS_AEM_FMT == FMT_32 && PS_PAL_FMT == 0 && PS_WMS < 2 && PS_WMT < 2)
#if (PS_LTF == 0 && PS_AEM_FMT == FMT_32 && PS_PAL_FMT == 0 && PS_REGION_RECT == 0 && PS_WMS < 2 && PS_WMT < 2)
// No software LTF and pure 32 bits RGBA texure without special texture wrapping
c[0] = sample_c(st);
#ifdef TEX_COORD_DEBUG
@@ -542,6 +594,8 @@ vec4 sample_color(vec2 st)
return trunc(t * 255.0f + 0.05f);
}
#endif // NEEDS_TEX
vec4 tfx(vec4 T, vec4 C)
{
vec4 C_out;
@@ -609,7 +663,9 @@ vec4 ps_color()
vec2 st_int = PSin.t_int.zw;
#endif
#if PS_CHANNEL_FETCH == 1
#if !NEEDS_TEX
vec4 T = vec4(0.0);
#elif PS_CHANNEL_FETCH == 1
vec4 T = fetch_red();
#elif PS_CHANNEL_FETCH == 2
vec4 T = fetch_green();
@@ -652,7 +708,7 @@ void ps_dither(inout vec3 C)
#if PS_DITHER == 2
ivec2 fpos = ivec2(gl_FragCoord.xy);
#else
ivec2 fpos = ivec2(gl_FragCoord.xy / float(PS_SCALE_FACTOR));
ivec2 fpos = ivec2(gl_FragCoord.xy * RcpScaleFactor);
#endif
float value = DitherMatrix[fpos.y&3][fpos.x&3];
#if PS_ROUND_INV
@@ -669,8 +725,8 @@ void ps_color_clamp_wrap(inout vec3 C)
// so we need to limit the color depth on dithered items
#if SW_BLEND || PS_DITHER || PS_FBMASK
#if PS_DFMT == FMT_16 && PS_BLEND_MIX == 0
C += 7.f; // Need to round up, not down since the shader will invert
#if PS_DFMT == FMT_16 && PS_BLEND_MIX == 0 && PS_ROUND_INV
C += 7.0f; // Need to round up, not down since the shader will invert
#endif
// Correct the Color value based on the output format
@@ -753,9 +809,9 @@ float As = As_rgba.a;
#endif
// As/Af clamp alpha for Blend mix
// We shouldn't clamp blend mix with clr1 as we want alpha higher
// We shouldn't clamp blend mix with blend hw 1 as we want alpha higher
float C_clamped = C;
#if PS_BLEND_MIX > 0 && PS_CLR_HW != 1
#if PS_BLEND_MIX > 0 && PS_BLEND_HW != 1
C_clamped = min(C_clamped, 1.0f);
#endif
@@ -776,11 +832,9 @@ float As = As_rgba.a;
Color.rgb = trunc((A - B) * C + D);
#endif
#if PS_CLR_HW == 1
// Replace Af with As so we can do proper compensation for Alpha.
#if PS_BLEND_C == 2
As_rgba = vec4(Af);
#endif
#if PS_BLEND_HW == 1
// As or Af
As_rgba.rgb = vec3(C);
// Subtract 1 for alpha to compensate for the changed equation,
// if c.rgb > 255.0f then we further need to adjust alpha accordingly,
// we pick the lowest overflow from all colors because it's the safest,
@@ -788,7 +842,7 @@ float As = As_rgba.a;
// changed alpha should only be done for hw blend.
vec3 alpha_compensate = max(vec3(1.0f), Color.rgb / vec3(255.0f));
As_rgba.rgb -= alpha_compensate;
#elif PS_CLR_HW == 2
#elif PS_BLEND_HW == 2
// Compensate slightly for Cd*(As + 1) - Cs*As.
// The initial factor we chose is 1 (0.00392)
// as that is the minimum color Cd can be,
@@ -796,13 +850,21 @@ float As = As_rgba.a;
// blended value it can be.
float color_compensate = 1.0f * (C + 1.0f);
Color.rgb -= vec3(color_compensate);
#elif PS_BLEND_HW == 3
// As, Ad or Af clamped.
As_rgba.rgb = vec3(C_clamped);
// Cs*(Alpha + 1) might overflow, if it does then adjust alpha value
// that is sent on second output to compensate.
vec3 overflow_check = (Color.rgb - vec3(255.0f)) / 255.0f;
vec3 alpha_compensate = max(vec3(0.0f), overflow_check);
As_rgba.rgb -= alpha_compensate;
#endif
#else
// Needed for Cd * (As/Ad/F + 1) blending modes
#if PS_CLR_HW == 1 || PS_CLR_HW == 5
#if PS_BLEND_HW == 1
Color.rgb = vec3(255.0f);
#elif PS_CLR_HW == 2 || PS_CLR_HW == 4
#elif PS_BLEND_HW == 2
// Cd*As,Cd*Ad or Cd*F
#if PS_BLEND_C == 2
@@ -813,11 +875,15 @@ float As = As_rgba.a;
Color.rgb = max(vec3(0.0f), (Alpha - vec3(1.0f)));
Color.rgb *= vec3(255.0f);
#elif PS_CLR_HW == 3
#elif PS_BLEND_HW == 3
// Needed for Cs*Ad, Cs*Ad + Cd, Cd - Cs*Ad
// Multiply Color.rgb by (255/128) to compensate for wrong Ad/255 value
Color.rgb *= (255.0f / 128.0f);
// Multiply Color.rgb by (255/128) to compensate for wrong Ad/255 value when rgb are below 128.
// When any color channel is higher than 128 then adjust the compensation automatically
// to give us more accurate colors, otherwise they will be wrong.
// The higher the value (>128) the lower the compensation will be.
float max_color = max(max(Color.r, Color.g), Color.b);
float color_compensate = 255.0f / max(128.0f, max_color);
Color.rgb *= vec3(color_compensate);
#endif
#endif
@@ -865,18 +931,6 @@ void ps_main()
#endif
vec4 C = ps_color();
#if (APITRACE_DEBUG & 1) == 1
C.r = 255.0f;
#endif
#if (APITRACE_DEBUG & 2) == 2
C.g = 255.0f;
#endif
#if (APITRACE_DEBUG & 4) == 4
C.b = 255.0f;
#endif
#if (APITRACE_DEBUG & 8) == 8
C.a = 128.0f;
#endif
#if PS_SHUFFLE
uvec4 denorm_c = uvec4(C);
@@ -996,5 +1050,3 @@ void ps_main()
gl_FragDepth = min(gl_FragCoord.z, MaxDepthPS);
#endif
}
#endif
+138 -148
View File
@@ -1,17 +1,20 @@
//#version 420 // Keep it for text editor detection
layout(std140, binding = 1) uniform cb20
{
vec2 VertexScale;
vec2 VertexOffset;
vec2 TextureScale;
vec2 TextureOffset;
vec2 PointSize;
uint MaxDepth;
uint pad_cb20;
};
#ifdef VERTEX_SHADER
layout(location = 0) in vec2 i_st;
layout(location = 2) in vec4 i_c;
layout(location = 3) in float i_q;
layout(location = 4) in uvec2 i_p;
layout(location = 5) in uint i_z;
layout(location = 6) in uvec2 i_uv;
layout(location = 7) in vec4 i_f;
#if !defined(BROKEN_DRIVER) && (pGL_ES || defined(GL_ARB_enhanced_layouts) && GL_ARB_enhanced_layouts)
layout(location = 0)
#endif
out SHADER
{
vec4 t_float;
@@ -25,6 +28,16 @@ out SHADER
const float exp_min32 = exp2(-32.0f);
#if VS_EXPAND == 0
layout(location = 0) in vec2 i_st;
layout(location = 2) in vec4 i_c;
layout(location = 3) in float i_q;
layout(location = 4) in uvec2 i_p;
layout(location = 5) in uint i_z;
layout(location = 6) in uvec2 i_uv;
layout(location = 7) in vec4 i_f;
void texture_coord()
{
vec2 uv = vec2(i_uv) - TextureOffset;
@@ -36,12 +49,12 @@ void texture_coord()
// Integer coordinate => normalized
VSout.t_int.xy = uv * TextureScale;
#if VS_INT_FST == 1
// Some games uses float coordinate for post-processing effect
VSout.t_int.zw = st / TextureScale;
#else
#if VS_FST
// Integer coordinate => integral
VSout.t_int.zw = uv;
#else
// Some games uses float coordinate for post-processing effect
VSout.t_int.zw = st / TextureScale;
#endif
}
@@ -77,173 +90,150 @@ void vs_main()
VSout.t_float.z = i_f.x; // pack for with texture
#if VS_POINT_SIZE
gl_PointSize = float(VS_POINT_SIZE_VALUE);
gl_PointSize = PointSize.x;
#endif
}
#endif
#else // VS_EXPAND
#ifdef GEOMETRY_SHADER
#if !defined(BROKEN_DRIVER) && (pGL_ES || defined(GL_ARB_enhanced_layouts) && GL_ARB_enhanced_layouts)
layout(location = 0)
#endif
in SHADER
struct RawVertex
{
vec4 t_float;
vec4 t_int;
#if GS_IIP != 0
vec4 c;
#else
flat vec4 c;
#endif
} GSin[];
vec2 ST;
uint RGBA;
float Q;
uint XY;
uint Z;
uint UV;
uint FOG;
};
#if !defined(BROKEN_DRIVER) && (pGL_ES || defined(GL_ARB_enhanced_layouts) && GL_ARB_enhanced_layouts)
layout(location = 0)
#endif
out SHADER
{
vec4 t_float;
vec4 t_int;
#if GS_IIP != 0
vec4 c;
#else
flat vec4 c;
#endif
} GSout;
layout(std140, binding = 2) readonly buffer VertexBuffer {
RawVertex vertex_buffer[];
};
struct vertex
struct ProcessedVertex
{
vec4 p;
vec4 t_float;
vec4 t_int;
vec4 c;
};
void out_vertex(in vec4 position, in vertex v)
ProcessedVertex load_vertex(uint index)
{
GSout.t_float = v.t_float;
GSout.t_int = v.t_int;
// Flat output
#if GS_POINT == 1
GSout.c = GSin[0].c;
#if defined(GL_ARB_shader_draw_parameters) && GL_ARB_shader_draw_parameters
RawVertex rvtx = vertex_buffer[index + gl_BaseVertexARB];
#else
GSout.c = GSin[1].c;
RawVertex rvtx = vertex_buffer[index];
#endif
gl_Position = position;
gl_PrimitiveID = gl_PrimitiveIDIn;
EmitVertex();
vec2 i_st = rvtx.ST;
vec4 i_c = vec4(uvec4(bitfieldExtract(rvtx.RGBA, 0, 8), bitfieldExtract(rvtx.RGBA, 8, 8),
bitfieldExtract(rvtx.RGBA, 16, 8), bitfieldExtract(rvtx.RGBA, 24, 8)));
float i_q = rvtx.Q;
uvec2 i_p = uvec2(bitfieldExtract(rvtx.XY, 0, 16), bitfieldExtract(rvtx.XY, 16, 16));
uint i_z = rvtx.Z;
uvec2 i_uv = uvec2(bitfieldExtract(rvtx.UV, 0, 16), bitfieldExtract(rvtx.UV, 16, 16));
vec4 i_f = unpackUnorm4x8(rvtx.FOG);
ProcessedVertex vtx;
uint z = min(i_z, MaxDepth);
vtx.p.xy = vec2(i_p) - vec2(0.05f, 0.05f);
vtx.p.xy = vtx.p.xy * VertexScale - VertexOffset;
vtx.p.w = 1.0f;
#if HAS_CLIP_CONTROL
vtx.p.z = float(z) * exp_min32;
#else
vtx.p.z = min(float(z) * exp2(-23.0f), 2.0f) - 1.0f;
#endif
vec2 uv = vec2(i_uv) - TextureOffset;
vec2 st = i_st - TextureOffset;
vtx.t_float.xy = st;
vtx.t_float.w = i_q;
vtx.t_int.xy = uv * TextureScale;
#if VS_FST
vtx.t_int.zw = uv;
#else
vtx.t_int.zw = st / TextureScale;
#endif
vtx.c = i_c;
vtx.t_float.z = i_f.x;
return vtx;
}
#if GS_POINT == 1
layout(points) in;
void main()
{
ProcessedVertex vtx;
#if defined(GL_ARB_shader_draw_parameters) && GL_ARB_shader_draw_parameters
uint vid = uint(gl_VertexID - gl_BaseVertexARB);
#else
layout(lines) in;
uint vid = uint(gl_VertexID);
#endif
layout(triangle_strip, max_vertices = 4) out;
#if GS_POINT == 1
#if VS_EXPAND == 1 // Point
void gs_main()
{
// Transform a point to a NxN sprite
vertex point = vertex(GSin[0].t_float, GSin[0].t_int, GSin[0].c);
vtx = load_vertex(vid >> 2);
// Get new position
vec4 lt_p = gl_in[0].gl_Position;
vec4 rb_p = gl_in[0].gl_Position + vec4(PointSize.x, PointSize.y, 0.0f, 0.0f);
vec4 lb_p = rb_p;
vec4 rt_p = rb_p;
lb_p.x = lt_p.x;
rt_p.y = lt_p.y;
vtx.p.x += ((vid & 1u) != 0u) ? PointSize.x : 0.0f;
vtx.p.y += ((vid & 2u) != 0u) ? PointSize.y : 0.0f;
out_vertex(lt_p, point);
#elif VS_EXPAND == 2 // Line
out_vertex(lb_p, point);
uint vid_base = vid >> 2;
bool is_bottom = (vid & 2u) != 0u;
bool is_right = (vid & 1u) != 0u;
uint vid_other = is_bottom ? vid_base - 1 : vid_base + 1;
vtx = load_vertex(vid_base);
ProcessedVertex other = load_vertex(vid_other);
out_vertex(rt_p, point);
out_vertex(rb_p, point);
EndPrimitive();
}
#elif GS_LINE == 1
void gs_main()
{
// Transform a line to a thick line-sprite
vertex left = vertex(GSin[0].t_float, GSin[0].t_int, GSin[0].c);
vertex right = vertex(GSin[1].t_float, GSin[1].t_int, GSin[1].c);
vec4 lt_p = gl_in[0].gl_Position;
vec4 rt_p = gl_in[1].gl_Position;
// Potentially there is faster math
vec2 line_vector = normalize(rt_p.xy - lt_p.xy);
vec2 line_vector = normalize(vtx.p.xy - other.p.xy);
vec2 line_normal = vec2(line_vector.y, -line_vector.x);
vec2 line_width = (line_normal * PointSize) / 2.0f;
vec2 line_width = (line_normal * PointSize) / 2;
// line_normal is inverted for bottom point
vec2 offset = ((uint(is_bottom) ^ uint(is_right)) != 0u) ? line_width : -line_width;
vtx.p.xy += offset;
lt_p.xy -= line_width;
rt_p.xy -= line_width;
vec4 lb_p = gl_in[0].gl_Position + vec4(line_width, 0.0f, 0.0f);
vec4 rb_p = gl_in[1].gl_Position + vec4(line_width, 0.0f, 0.0f);
// Lines will be run as (0 1 2) (1 2 3)
// This means that both triangles will have a point based off the top line point as their first point
// So we don't have to do anything for !IIP
out_vertex(lt_p, left);
#elif VS_EXPAND == 3 // Sprite
out_vertex(lb_p, left);
// Sprite points are always in pairs
uint vid_base = vid >> 1;
uint vid_lt = vid_base & ~1u;
uint vid_rb = vid_base | 1u;
out_vertex(rt_p, right);
ProcessedVertex lt = load_vertex(vid_lt);
ProcessedVertex rb = load_vertex(vid_rb);
vtx = rb;
out_vertex(rb_p, right);
bool is_right = ((vid & 1u) != 0u);
vtx.p.x = is_right ? lt.p.x : vtx.p.x;
vtx.t_float.x = is_right ? lt.t_float.x : vtx.t_float.x;
vtx.t_int.xz = is_right ? lt.t_int.xz : vtx.t_int.xz;
EndPrimitive();
}
#else
void gs_main()
{
// left top => GSin[0];
// right bottom => GSin[1];
vertex rb = vertex(GSin[1].t_float, GSin[1].t_int, GSin[1].c);
vertex lt = vertex(GSin[0].t_float, GSin[0].t_int, GSin[0].c);
vec4 rb_p = gl_in[1].gl_Position;
vec4 lb_p = rb_p;
vec4 rt_p = rb_p;
vec4 lt_p = gl_in[0].gl_Position;
// flat depth
lt_p.z = rb_p.z;
// flat fog and texture perspective
lt.t_float.zw = rb.t_float.zw;
// flat color
lt.c = rb.c;
// Swap texture and position coordinate
vertex lb = rb;
lb.t_float.x = lt.t_float.x;
lb.t_int.x = lt.t_int.x;
lb.t_int.z = lt.t_int.z;
lb_p.x = lt_p.x;
vertex rt = rb;
rt_p.y = lt_p.y;
rt.t_float.y = lt.t_float.y;
rt.t_int.y = lt.t_int.y;
rt.t_int.w = lt.t_int.w;
out_vertex(lt_p, lt);
out_vertex(lb_p, lb);
out_vertex(rt_p, rt);
out_vertex(rb_p, rb);
EndPrimitive();
}
bool is_bottom = ((vid & 2u) != 0u);
vtx.p.y = is_bottom ? lt.p.y : vtx.p.y;
vtx.t_float.y = is_bottom ? lt.t_float.y : vtx.t_float.y;
vtx.t_int.yw = is_bottom ? lt.t_int.yw : vtx.t_int.yw;
#endif
#endif
gl_Position = vtx.p;
VSout.t_float = vtx.t_float;
VSout.t_int = vtx.t_int;
VSout.c = vtx.c;
}
#endif // VS_EXPAND
#endif // VERTEX_SHADER
+52 -31
View File
@@ -1,7 +1,3 @@
#ifndef PS_SCALE_FACTOR
#define PS_SCALE_FACTOR 1.0
#endif
#ifdef VERTEX_SHADER
layout(location = 0) in vec4 a_pos;
@@ -23,7 +19,17 @@ layout(location = 0) in vec2 v_tex;
#if defined(ps_convert_rgba8_16bits) || defined(ps_convert_float32_32bits)
layout(location = 0) out uint o_col0;
#else
#elif !defined(ps_datm1) && \
!defined(ps_datm0) && \
!defined(ps_convert_rgba8_float32) && \
!defined(ps_convert_rgba8_float24) && \
!defined(ps_convert_rgba8_float16) && \
!defined(ps_convert_rgb5a1_float16) && \
!defined(ps_convert_rgba8_float32_biln) && \
!defined(ps_convert_rgba8_float24_biln) && \
!defined(ps_convert_rgba8_float16_biln) && \
!defined(ps_convert_rgb5a1_float16_biln) && \
!defined(ps_depth_copy)
layout(location = 0) out vec4 o_col0;
#endif
@@ -69,8 +75,6 @@ void ps_convert_rgba8_16bits()
#ifdef ps_datm1
void ps_datm1()
{
o_col0 = vec4(0, 0, 0, 0);
if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass
discard;
@@ -80,8 +84,6 @@ void ps_datm1()
#ifdef ps_datm0
void ps_datm0()
{
o_col0 = vec4(0, 0, 0, 0);
if((127.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
discard;
}
@@ -238,6 +240,15 @@ void ps_convert_rgb5a1_float16_biln()
#endif
#ifdef ps_convert_rgba_8i
layout(push_constant) uniform cb10
{
uint SBW;
uint DBW;
uvec2 cb_pad1;
float ScaleFactor;
vec3 cb_pad2;
};
void ps_convert_rgba_8i()
{
// Convert a RGBA texture into a 8 bits packed texture
@@ -249,37 +260,45 @@ void ps_convert_rgba_8i()
// 1: 8 R | 8 B
// 2: 8 G | 8 A
// 3: 8 G | 8 A
uvec2 pos = uvec2(gl_FragCoord.xy);
uvec2 pos = uvec2(gl_FragCoord.xy);
// Collapse separate R G B A areas into their base pixel
uvec2 block = (pos & ~uvec2(15u, 3u)) >> 1;
uvec2 subblock = pos & uvec2(7u, 1u);
uvec2 coord = block | subblock;
// Collapse separate R G B A areas into their base pixel
uvec2 block = (pos & ~uvec2(15u, 3u)) >> 1;
uvec2 subblock = pos & uvec2(7u, 1u);
uvec2 coord = block | subblock;
// Apply offset to cols 1 and 2
uint is_col23 = pos.y & 4u;
uint is_col13 = pos.y & 2u;
uint is_col12 = is_col23 ^ (is_col13 << 1);
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
// Compensate for potentially differing page pitch.
uvec2 block_xy = coord / uvec2(64u, 32u);
uint block_num = (block_xy.y * (DBW / 128u)) + block_xy.x;
uvec2 block_offset = uvec2((block_num % (SBW / 64u)) * 64u, (block_num / (SBW / 64u)) * 32u);
coord = (coord % uvec2(64u, 32u)) + block_offset;
if (floor(PS_SCALE_FACTOR) != PS_SCALE_FACTOR)
coord = uvec2(vec2(coord) * PS_SCALE_FACTOR);
else
coord *= uvec2(PS_SCALE_FACTOR);
// Apply offset to cols 1 and 2
uint is_col23 = pos.y & 4u;
uint is_col13 = pos.y & 2u;
uint is_col12 = is_col23 ^ (is_col13 << 1);
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
vec4 pixel = texelFetch(samp0, ivec2(coord), 0);
vec2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
float sel1 = (pos.x & 8u) == 0u ? sel0.x : sel0.y;
o_col0 = vec4(sel1); // Divide by something here?
if (floor(ScaleFactor) != ScaleFactor)
coord = uvec2(vec2(coord) * ScaleFactor);
else
coord *= uvec2(ScaleFactor);
vec4 pixel = texelFetch(samp0, ivec2(coord), 0);
vec2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
float sel1 = (pos.x & 8u) == 0u ? sel0.x : sel0.y;
o_col0 = vec4(sel1); // Divide by something here?
}
#endif
#ifdef ps_convert_clut_4
layout(push_constant) uniform cb10
{
vec2 scale;
uvec2 offset;
uint doffset;
uint cb_pad1;
float scale;
vec3 cb_pad2;
};
void ps_convert_clut_4()
@@ -288,7 +307,7 @@ void ps_convert_clut_4()
uint index = uint(gl_FragCoord.x) + doffset;
uvec2 pos = uvec2(index % 8u, index / 8u);
ivec2 final = ivec2(floor(vec2(offset + pos) * scale));
ivec2 final = ivec2(floor(vec2(offset + pos) * vec2(scale)));
o_col0 = texelFetch(samp0, final, 0);
}
#endif
@@ -296,9 +315,11 @@ void ps_convert_clut_4()
#ifdef ps_convert_clut_8
layout(push_constant) uniform cb10
{
vec2 scale;
uvec2 offset;
uint doffset;
uint cb_pad1;
float scale;
vec3 cb_pad2;
};
void ps_convert_clut_8()
@@ -312,7 +333,7 @@ void ps_convert_clut_8()
pos.x = (index % 8u) + ((subgroup >= 2u) ? 8u : 0u);
pos.y = ((index / 32u) * 2u) + (subgroup % 2u);
ivec2 final = ivec2(floor(vec2(offset + pos) * scale));
ivec2 final = ivec2(floor(vec2(offset + pos) * vec2(scale)));
o_col0 = texelFetch(samp0, final, 0);
}
#endif
+39
View File
@@ -0,0 +1,39 @@
#ifdef VERTEX_SHADER
layout(location = 0) in vec2 Position;
layout(location = 1) in vec2 UV;
layout(location = 2) in vec4 Color;
layout(push_constant) uniform PushConstants
{
vec2 uScale;
vec2 uTranslate;
};
layout(location = 0) out vec2 Frag_UV;
layout(location = 1) out vec4 Frag_Color;
void vs_main()
{
Frag_UV = UV;
Frag_Color = Color;
gl_Position = vec4(Position * uScale + uTranslate, 0.0f, 1.0f);
}
#endif
#ifdef FRAGMENT_SHADER
layout(binding = 0) uniform sampler2D Texture;
layout(location = 0) in vec2 Frag_UV;
layout(location = 1) in vec4 Frag_Color;
layout(location = 0) out vec4 Out_Color;
void ps_main()
{
Out_Color = Frag_Color * texture(Texture, Frag_UV.st);
}
#endif
+14 -18
View File
@@ -35,7 +35,7 @@ void ps_main0()
const int vpos = int(gl_FragCoord.y); // vertical position of destination texture
if ((vpos & 1) == field)
o_col0 = texture(samp0, v_tex);
o_col0 = textureLod(samp0, v_tex, 0);
else
discard;
}
@@ -46,7 +46,7 @@ void ps_main0()
#ifdef ps_main1
void ps_main1()
{
o_col0 = texture(samp0, v_tex);
o_col0 = textureLod(samp0, v_tex, 0);
}
#endif
@@ -56,9 +56,9 @@ void ps_main1()
void ps_main2()
{
vec2 vstep = vec2(0.0f, ZrH.y);
vec4 c0 = texture(samp0, v_tex - vstep);
vec4 c1 = texture(samp0, v_tex);
vec4 c2 = texture(samp0, v_tex + vstep);
vec4 c0 = textureLod(samp0, v_tex - vstep, 0);
vec4 c1 = textureLod(samp0, v_tex, 0);
vec4 c2 = textureLod(samp0, v_tex + vstep, 0);
o_col0 = (c0 + c1 * 2.0f + c2) / 4.0f;
}
@@ -82,15 +82,11 @@ void ps_main3()
const int vres = int(ZrH.z) >> 1; // vertical resolution of source texture
const int lofs = ((((vres + 1) >> 1) << 1) - vres) & bank; // line alignment offset for bank 1
const int vpos = int(gl_FragCoord.y) + lofs; // vertical position of destination texture
const vec2 bofs = vec2(0.0f, 0.5f * bank); // vertical offset of the current bank relative to source texture size
const vec2 vscale = vec2(1.0f, 2.0f); // scaling factor from source to destination texture
const vec2 optr = v_tex - bofs; // used to check if the current destination line is within the current bank
const vec2 iptr = optr * vscale; // pointer to the current pixel in the source texture
// if the index of current destination line belongs to the current fiels we update it, otherwise
// we leave the old line in the destination buffer
if ((optr.y >= 0.0f) && (optr.y < 0.5f) && ((vpos & 1) == field))
o_col0 = texture(samp0, iptr);
if ((vpos & 1) == field)
o_col0 = textureLod(samp0, v_tex, 0);
else
discard;
}
@@ -150,13 +146,13 @@ void ps_main4()
// calculating motion, only relevant for missing lines where the "center line" is pointed by p_t1
vec4 hn = texture(samp0, p_t0 - lofs); // new high pixel
vec4 cn = texture(samp0, p_t1); // new center pixel
vec4 ln = texture(samp0, p_t0 + lofs); // new low pixel
vec4 hn = textureLod(samp0, p_t0 - lofs, 0); // new high pixel
vec4 cn = textureLod(samp0, p_t1, 0); // new center pixel
vec4 ln = textureLod(samp0, p_t0 + lofs, 0); // new low pixel
vec4 ho = texture(samp0, p_t2 - lofs); // old high pixel
vec4 co = texture(samp0, p_t3); // old center pixel
vec4 lo = texture(samp0, p_t2 + lofs); // old low pixel
vec4 ho = textureLod(samp0, p_t2 - lofs, 0); // old high pixel
vec4 co = textureLod(samp0, p_t3, 0); // old center pixel
vec4 lo = textureLod(samp0, p_t2 + lofs, 0); // old low pixel
vec3 mh = hn.rgb - ho.rgb; // high pixel motion
vec3 mc = cn.rgb - co.rgb; // center pixel motion
@@ -181,7 +177,7 @@ void ps_main4()
if ((vpos & 1) == field) // output coordinate present on current field
{
// output coordinate present on current field
o_col0 = texture(samp0, p_t0);
o_col0 = textureLod(samp0, p_t0, 0);
}
else if ((iptr.y > 0.5f - lofs.y) || (iptr.y < 0.0 + lofs.y))
{
+214 -218
View File
@@ -2,7 +2,7 @@
// Vertex Shader
//////////////////////////////////////////////////////////////////////
#if defined(VERTEX_SHADER) || defined(GEOMETRY_SHADER)
#if defined(VERTEX_SHADER)
layout(std140, set = 0, binding = 0) uniform cb0
{
@@ -15,18 +15,6 @@ layout(std140, set = 0, binding = 0) uniform cb0
uint pad_cb0;
};
#endif
#ifdef VERTEX_SHADER
layout(location = 0) in vec2 a_st;
layout(location = 1) in uvec4 a_c;
layout(location = 2) in float a_q;
layout(location = 3) in uvec2 a_p;
layout(location = 4) in uint a_z;
layout(location = 5) in uvec2 a_uv;
layout(location = 6) in vec4 a_f;
layout(location = 0) out VSOutput
{
vec4 t;
@@ -39,17 +27,27 @@ layout(location = 0) out VSOutput
#endif
} vsOut;
#if VS_EXPAND == 0
layout(location = 0) in vec2 a_st;
layout(location = 1) in uvec4 a_c;
layout(location = 2) in float a_q;
layout(location = 3) in uvec2 a_p;
layout(location = 4) in uint a_z;
layout(location = 5) in uvec2 a_uv;
layout(location = 6) in vec4 a_f;
void main()
{
// Clamp to max depth, gs doesn't wrap
float z = min(a_z, MaxDepth);
uint z = min(a_z, MaxDepth);
// pos -= 0.05 (1/320 pixel) helps avoiding rounding problems (integral part of pos is usually 5 digits, 0.05 is about as low as we can go)
// example: ceil(afterseveralvertextransformations(y = 133)) => 134 => line 133 stays empty
// input granularity is 1/16 pixel, anything smaller than that won't step drawing up/left by one pixel
// example: 133.0625 (133 + 1/16) should start from line 134, ceil(133.0625 - 0.05) still above 133
gl_Position = vec4(a_p, z, 1.0f) - vec4(0.05f, 0.05f, 0, 0);
gl_Position = vec4(a_p, float(z), 1.0f) - vec4(0.05f, 0.05f, 0, 0);
gl_Position.xy = gl_Position.xy * vec2(VertexScale.x, -VertexScale.y) - vec2(VertexOffset.x, -VertexOffset.y);
gl_Position.z *= exp2(-32.0f); // integer->float depth
gl_Position.y = -gl_Position.y;
@@ -78,217 +76,153 @@ void main()
#endif
#if VS_POINT_SIZE
gl_PointSize = float(VS_POINT_SIZE_VALUE);
gl_PointSize = PointSize.x;
#endif
vsOut.c = a_c;
vsOut.c = vec4(a_c);
vsOut.t.z = a_f.r;
}
#endif
#else // VS_EXPAND
#ifdef GEOMETRY_SHADER
layout(location = 0) in VSOutput
struct RawVertex
{
vec2 ST;
uint RGBA;
float Q;
uint XY;
uint Z;
uint UV;
uint FOG;
};
layout(std140, set = 0, binding = 2) readonly buffer VertexBuffer {
RawVertex vertex_buffer[];
};
struct ProcessedVertex
{
vec4 p;
vec4 t;
vec4 ti;
#if GS_IIP != 0
vec4 c;
vec4 c;
};
ProcessedVertex load_vertex(uint index)
{
RawVertex rvtx = vertex_buffer[gl_BaseVertexARB + index];
vec2 a_st = rvtx.ST;
uvec4 a_c = uvec4(bitfieldExtract(rvtx.RGBA, 0, 8), bitfieldExtract(rvtx.RGBA, 8, 8),
bitfieldExtract(rvtx.RGBA, 16, 8), bitfieldExtract(rvtx.RGBA, 24, 8));
float a_q = rvtx.Q;
uvec2 a_p = uvec2(bitfieldExtract(rvtx.XY, 0, 16), bitfieldExtract(rvtx.XY, 16, 16));
uint a_z = rvtx.Z;
uvec2 a_uv = uvec2(bitfieldExtract(rvtx.UV, 0, 16), bitfieldExtract(rvtx.UV, 16, 16));
vec4 a_f = unpackUnorm4x8(rvtx.FOG);
ProcessedVertex vtx;
uint z = min(a_z, MaxDepth);
vtx.p = vec4(a_p, float(z), 1.0f) - vec4(0.05f, 0.05f, 0, 0);
vtx.p.xy = vtx.p.xy * vec2(VertexScale.x, -VertexScale.y) - vec2(VertexOffset.x, -VertexOffset.y);
vtx.p.z *= exp2(-32.0f); // integer->float depth
vtx.p.y = -vtx.p.y;
#if VS_TME
vec2 uv = a_uv - TextureOffset;
vec2 st = a_st - TextureOffset;
vtx.ti.xy = uv * TextureScale;
#if VS_FST
vtx.ti.zw = uv;
#else
vtx.ti.zw = st / TextureScale;
#endif
vtx.t.xy = st;
vtx.t.w = a_q;
#else
flat vec4 c;
vtx.t = vec4(0.0f, 0.0f, 0.0f, 1.0f);
vtx.ti = vec4(0.0f);
#endif
} gsIn[];
layout(location = 0) out GSOutput
{
vec4 t;
vec4 ti;
#if GS_IIP != 0
vec4 c;
#else
flat vec4 c;
#endif
} gsOut;
vtx.c = a_c;
vtx.t.z = a_f.r;
void WriteVertex(vec4 pos, vec4 t, vec4 ti, vec4 c)
{
#if GS_FORWARD_PRIMID
gl_PrimitiveID = gl_PrimitiveIDIn;
#endif
gl_Position = pos;
gsOut.t = t;
gsOut.ti = ti;
gsOut.c = c;
EmitVertex();
return vtx;
}
//////////////////////////////////////////////////////////////////////
// Geometry Shader
//////////////////////////////////////////////////////////////////////
#if GS_PRIM == 0 && GS_POINT == 0
layout(points) in;
layout(points, max_vertices = 1) out;
void main()
{
WriteVertex(gl_in[0].gl_Position, gsIn[0].t, gsIn[0].ti, gsIn[0].c);
EndPrimitive();
}
#elif GS_PRIM == 0 && GS_POINT == 1
layout(points) in;
layout(triangle_strip, max_vertices = 4) out;
void main()
{
// Transform a point to a NxN sprite
ProcessedVertex vtx;
uint vid = uint(gl_VertexIndex - gl_BaseVertexARB);
// Get new position
vec4 lt_p = gl_in[0].gl_Position;
vec4 rb_p = gl_in[0].gl_Position + vec4(PointSize.x, PointSize.y, 0.0f, 0.0f);
vec4 lb_p = rb_p;
vec4 rt_p = rb_p;
lb_p.x = lt_p.x;
rt_p.y = lt_p.y;
#if VS_EXPAND == 1 // Point
WriteVertex(lt_p, gsIn[0].t, gsIn[0].ti, gsIn[0].c);
WriteVertex(lb_p, gsIn[0].t, gsIn[0].ti, gsIn[0].c);
WriteVertex(rt_p, gsIn[0].t, gsIn[0].ti, gsIn[0].c);
WriteVertex(rb_p, gsIn[0].t, gsIn[0].ti, gsIn[0].c);
vtx = load_vertex(vid >> 2);
EndPrimitive();
}
vtx.p.x += ((vid & 1u) != 0u) ? PointSize.x : 0.0f;
vtx.p.y += ((vid & 2u) != 0u) ? PointSize.y : 0.0f;
#elif GS_PRIM == 1 && GS_LINE == 0
#elif VS_EXPAND == 2 // Line
layout(lines) in;
layout(line_strip, max_vertices = 2) out;
uint vid_base = vid >> 2;
void main()
{
#if GS_IIP == 0
WriteVertex(gl_in[0].gl_Position, gsIn[0].t, gsIn[0].ti, gsIn[1].c);
WriteVertex(gl_in[1].gl_Position, gsIn[1].t, gsIn[1].ti, gsIn[1].c);
bool is_bottom = (vid & 2u) != 0u;
bool is_right = (vid & 1u) != 0u;
#ifdef VS_PROVOKING_VERTEX_LAST
uint vid_other = is_bottom ? vid_base - 1 : vid_base + 1;
#else
WriteVertex(gl_in[0].gl_Position, gsIn[0].t, gsIn[0].ti, gsIn[0].c);
WriteVertex(gl_in[1].gl_Position, gsIn[1].t, gsIn[1].ti, gsIn[1].c);
uint vid_other = is_bottom ? vid_base + 1 : vid_base - 1;
#endif
EndPrimitive();
}
vtx = load_vertex(vid_base);
ProcessedVertex other = load_vertex(vid_other);
#elif GS_PRIM == 1 && GS_LINE == 1
layout(lines) in;
layout(triangle_strip, max_vertices = 4) out;
void main()
{
// Transform a line to a thick line-sprite
vec4 left_t = gsIn[0].t;
vec4 left_ti = gsIn[0].ti;
vec4 left_c = gsIn[0].c;
vec4 right_t = gsIn[1].t;
vec4 right_ti = gsIn[1].ti;
vec4 right_c = gsIn[1].c;
vec4 lt_p = gl_in[0].gl_Position;
vec4 rt_p = gl_in[1].gl_Position;
// Potentially there is faster math
vec2 line_vector = normalize(rt_p.xy - lt_p.xy);
vec2 line_vector = normalize(vtx.p.xy - other.p.xy);
vec2 line_normal = vec2(line_vector.y, -line_vector.x);
vec2 line_width = (line_normal * PointSize) / 2.0;
vec2 line_width = (line_normal * PointSize) / 2;
// line_normal is inverted for bottom point
vec2 offset = ((uint(is_bottom) ^ uint(is_right)) != 0u) ? line_width : -line_width;
vtx.p.xy += offset;
lt_p.xy -= line_width;
rt_p.xy -= line_width;
vec4 lb_p = gl_in[0].gl_Position + vec4(line_width, 0.0, 0.0);
vec4 rb_p = gl_in[1].gl_Position + vec4(line_width, 0.0, 0.0);
// Lines will be run as (0 1 2) (1 2 3)
// This means that both triangles will have a point based off the top line point as their first point
// So we don't have to do anything for !IIP
#if GS_IIP == 0
left_c = right_c;
#endif
#elif VS_EXPAND == 3 // Sprite
WriteVertex(lt_p, left_t, left_ti, left_c);
WriteVertex(lb_p, left_t, left_ti, left_c);
WriteVertex(rt_p, right_t, right_ti, right_c);
WriteVertex(rb_p, right_t, right_ti, right_c);
EndPrimitive();
}
// Sprite points are always in pairs
uint vid_base = vid >> 1;
uint vid_lt = vid_base & ~1u;
uint vid_rb = vid_base | 1u;
#elif GS_PRIM == 2
ProcessedVertex lt = load_vertex(vid_lt);
ProcessedVertex rb = load_vertex(vid_rb);
vtx = rb;
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
bool is_right = ((vid & 1u) != 0u);
vtx.p.x = is_right ? lt.p.x : vtx.p.x;
vtx.t.x = is_right ? lt.t.x : vtx.t.x;
vtx.ti.xz = is_right ? lt.ti.xz : vtx.ti.xz;
void main()
{
#if GS_IIP == 0
WriteVertex(gl_in[0].gl_Position, gsIn[0].t, gsIn[0].ti, gsIn[2].c);
WriteVertex(gl_in[1].gl_Position, gsIn[1].t, gsIn[1].ti, gsIn[2].c);
WriteVertex(gl_in[2].gl_Position, gsIn[2].t, gsIn[2].ti, gsIn[2].c);
#else
WriteVertex(gl_in[0].gl_Position, gsIn[0].t, gsIn[0].ti, gsIn[0].c);
WriteVertex(gl_in[1].gl_Position, gsIn[1].t, gsIn[1].ti, gsIn[0].c);
WriteVertex(gl_in[2].gl_Position, gsIn[2].t, gsIn[2].ti, gsIn[0].c);
#endif
EndPrimitive();
}
#elif GS_PRIM == 3
layout(lines) in;
layout(triangle_strip, max_vertices = 4) out;
void main()
{
vec4 lt_p = gl_in[0].gl_Position;
vec4 lt_t = gsIn[0].t;
vec4 lt_ti = gsIn[0].ti;
vec4 lt_c = gsIn[0].c;
vec4 rb_p = gl_in[1].gl_Position;
vec4 rb_t = gsIn[1].t;
vec4 rb_ti = gsIn[1].ti;
vec4 rb_c = gsIn[1].c;
// flat depth
lt_p.z = rb_p.z;
// flat fog and texture perspective
lt_t.zw = rb_t.zw;
// flat color
lt_c = rb_c;
// Swap texture and position coordinate
vec4 lb_p = rb_p;
vec4 lb_t = rb_t;
vec4 lb_ti = rb_ti;
vec4 lb_c = rb_c;
lb_p.x = lt_p.x;
lb_t.x = lt_t.x;
lb_ti.x = lt_ti.x;
lb_ti.z = lt_ti.z;
vec4 rt_p = rb_p;
vec4 rt_t = rb_t;
vec4 rt_ti = rb_ti;
vec4 rt_c = rb_c;
rt_p.y = lt_p.y;
rt_t.y = lt_t.y;
rt_ti.y = lt_ti.y;
rt_ti.w = lt_ti.w;
WriteVertex(lt_p, lt_t, lt_ti, lt_c);
WriteVertex(lb_p, lb_t, lb_ti, lb_c);
WriteVertex(rt_p, rt_t, rt_ti, rt_c);
WriteVertex(rb_p, rb_t, rb_ti, rb_c);
EndPrimitive();
}
bool is_bottom = ((vid & 2u) != 0u);
vtx.p.y = is_bottom ? lt.p.y : vtx.p.y;
vtx.t.y = is_bottom ? lt.t.y : vtx.t.y;
vtx.ti.yw = is_bottom ? lt.ti.yw : vtx.ti.yw;
#endif
#endif
gl_Position = vtx.p;
vsOut.t = vtx.t;
vsOut.ti = vtx.ti;
vsOut.c = vtx.c;
}
#endif // VS_EXPAND
#endif // VERTEX_SHADER
#ifdef FRAGMENT_SHADER
@@ -320,7 +254,8 @@ void main()
#define PS_TCC 1
#define PS_ATST 1
#define PS_FOG 0
#define PS_CLR_HW 0
#define PS_BLEND_HW 0
#define PS_A_MASKED 0
#define PS_FBA 0
#define PS_FBMASK 0
#define PS_LTF 1
@@ -335,7 +270,6 @@ void main()
#define PS_CHANNEL_FETCH 0
#define PS_TALES_OF_ABYSS_HLE 0
#define PS_URBAN_CHAOS_HLE 0
#define PS_SCALE_FACTOR 1.0
#define PS_HDR 0
#define PS_COLCLIP 0
#define PS_BLEND_A 0
@@ -352,9 +286,12 @@ void main()
#define SW_BLEND (PS_BLEND_A || PS_BLEND_B || PS_BLEND_D)
#define SW_BLEND_NEEDS_RT (PS_BLEND_A == 1 || PS_BLEND_B == 1 || PS_BLEND_C == 1 || PS_BLEND_D == 1)
#define SW_AD_TO_HW (PS_BLEND_C == 1 && PS_A_MASKED)
#define PS_FEEDBACK_LOOP_IS_NEEDED (PS_TEX_IS_FB == 1 || PS_FBMASK || SW_BLEND_NEEDS_RT || (PS_DATE >= 5))
#define NEEDS_TEX (PS_TFX != 4)
layout(std140, set = 0, binding = 1) uniform cb1
{
vec3 FogColor;
@@ -371,6 +308,8 @@ layout(std140, set = 0, binding = 1) uniform cb1
vec2 TC_OffsetHack;
vec2 STScale;
mat4 DitherMatrix;
float ScaledScaleFactor;
float RcpScaleFactor;
};
layout(location = 0) in VSOutput
@@ -387,12 +326,14 @@ layout(location = 0) in VSOutput
#if !defined(DISABLE_DUAL_SOURCE) && !PS_NO_COLOR1
layout(location = 0, index = 0) out vec4 o_col0;
layout(location = 0, index = 1) out vec4 o_col1;
#else
#elif !PS_NO_COLOR
layout(location = 0) out vec4 o_col0;
#endif
#if NEEDS_TEX
layout(set = 1, binding = 0) uniform sampler2D Texture;
layout(set = 1, binding = 1) uniform texture2D Palette;
#endif
#if PS_FEEDBACK_LOOP_IS_NEEDED
#ifndef DISABLE_TEXTURE_BARRIER
@@ -408,10 +349,14 @@ layout(set = 1, binding = 1) uniform texture2D Palette;
layout(set = 2, binding = 1) uniform texture2D PrimMinTexture;
#endif
#if NEEDS_TEX
vec4 sample_c(vec2 uv)
{
#if PS_TEX_IS_FB
return sample_from_rt();
#elif PS_REGION_RECT
return texelFetch(Texture, ivec2(uv), 0);
#else
#if PS_POINT_SAMPLER
// Weird issue with ATI/AMD cards,
@@ -474,7 +419,15 @@ vec4 clamp_wrap_uv(vec4 uv)
#if PS_WMS == PS_WMT
{
#if PS_WMS == 2
#if PS_REGION_RECT == 1 && PS_WMS == 0
{
uv = fract(uv);
}
#elif PS_REGION_RECT == 1 && PS_WMS == 1
{
uv = clamp(uv, vec4(0.0f), vec4(1.0f));
}
#elif PS_WMS == 2
{
uv = clamp(uv, MinMax.xyxy, MinMax.zwzw);
}
@@ -491,7 +444,15 @@ vec4 clamp_wrap_uv(vec4 uv)
}
#else
{
#if PS_WMS == 2
#if PS_REGION_RECT == 1 && PS_WMS == 0
{
uv.xz = fract(uv.xz);
}
#elif PS_REGION_RECT == 1 && PS_WMS == 1
{
uv.xz = clamp(uv.xz, vec2(0.0f), vec2(1.0f));
}
#elif PS_WMS == 2
{
uv.xz = clamp(uv.xz, MinMax.xx, MinMax.zz);
}
@@ -503,7 +464,15 @@ vec4 clamp_wrap_uv(vec4 uv)
uv.xz = vec2((uvec2(uv.xz * tex_size.xx) & floatBitsToUint(MinMax.xx)) | floatBitsToUint(MinMax.zz)) / tex_size.xx;
}
#endif
#if PS_WMT == 2
#if PS_REGION_RECT == 1 && PS_WMT == 0
{
uv.yw = fract(uv.yw);
}
#elif PS_REGION_RECT == 1 && PS_WMT == 1
{
uv.yw = clamp(uv.yw, vec2(0.0f), vec2(1.0f));
}
#elif PS_WMT == 2
{
uv.yw = clamp(uv.yw, MinMax.yy, MinMax.ww);
}
@@ -518,6 +487,11 @@ vec4 clamp_wrap_uv(vec4 uv)
}
#endif
#if PS_REGION_RECT == 1
// Normalized -> Integer Coordinates.
uv = clamp(uv * WH.zwzw + STRange.xyxy, STRange.xyxy, STRange.zwzw);
#endif
return uv;
}
@@ -590,7 +564,11 @@ vec4 fetch_raw_color(ivec2 xy)
vec4 fetch_c(ivec2 uv)
{
#if PS_TEX_IS_FB
return sample_from_rt();
#else
return texelFetch(Texture, uv, 0);
#endif
}
//////////////////////////////////////////////////////////////////////
@@ -639,9 +617,13 @@ ivec2 clamp_wrap_uv_depth(ivec2 uv)
vec4 sample_depth(vec2 st, ivec2 pos)
{
vec2 uv_f = vec2(clamp_wrap_uv_depth(ivec2(st))) * vec2(PS_SCALE_FACTOR) * vec2(1.0f / 16.0f);
ivec2 uv = ivec2(uv_f);
vec2 uv_f = vec2(clamp_wrap_uv_depth(ivec2(st))) * vec2(ScaledScaleFactor);
#if PS_REGION_RECT == 1
uv_f = clamp(uv_f + STRange.xy, STRange.xy, STRange.zw);
#endif
ivec2 uv = ivec2(uv_f);
vec4 t = vec4(0.0f);
#if (PS_TALES_OF_ABYSS_HLE == 1)
@@ -790,7 +772,7 @@ vec4 sample_color(vec2 st)
mat4 c;
vec2 dd;
#if PS_LTF == 0 && PS_AEM_FMT == FMT_32 && PS_PAL_FMT == 0 && PS_WMS < 2 && PS_WMT < 2
#if PS_LTF == 0 && PS_AEM_FMT == FMT_32 && PS_PAL_FMT == 0 && PS_REGION_RECT == 0 && PS_WMS < 2 && PS_WMT < 2
{
c[0] = sample_c(st);
}
@@ -847,6 +829,8 @@ vec4 sample_color(vec2 st)
return trunc(t * 255.0f + 0.05f);
}
#endif // NEEDS_TEX
vec4 tfx(vec4 T, vec4 C)
{
vec4 C_out;
@@ -924,7 +908,9 @@ vec4 ps_color()
vec2 st_int = vsIn.ti.zw;
#endif
#if PS_CHANNEL_FETCH == 1
#if !NEEDS_TEX
vec4 T = vec4(0.0f);
#elif PS_CHANNEL_FETCH == 1
vec4 T = fetch_red(ivec2(gl_FragCoord.xy));
#elif PS_CHANNEL_FETCH == 2
vec4 T = fetch_green(ivec2(gl_FragCoord.xy));
@@ -967,7 +953,7 @@ void ps_dither(inout vec3 C)
#if PS_DITHER == 2
fpos = ivec2(gl_FragCoord.xy);
#else
fpos = ivec2(gl_FragCoord.xy / float(PS_SCALE_FACTOR));
fpos = ivec2(gl_FragCoord.xy * RcpScaleFactor);
#endif
float value = DitherMatrix[fpos.y & 3][fpos.x & 3];
@@ -985,7 +971,7 @@ void ps_color_clamp_wrap(inout vec3 C)
// so we need to limit the color depth on dithered items
#if SW_BLEND || PS_DITHER || PS_FBMASK
#if PS_DFMT == FMT_16 && PS_BLEND_MIX == 0 && PS_ROUND_INV != 0
#if PS_DFMT == FMT_16 && PS_BLEND_MIX == 0 && PS_ROUND_INV
C += 7.0f; // Need to round up, not down since the shader will invert
#endif
@@ -1072,9 +1058,9 @@ void ps_blend(inout vec4 Color, inout vec4 As_rgba)
#endif
// As/Af clamp alpha for Blend mix
// We shouldn't clamp blend mix with clr1 as we want alpha higher
// We shouldn't clamp blend mix with blend hw 1 as we want alpha higher
float C_clamped = C;
#if PS_BLEND_MIX > 0 && PS_CLR_HW != 1
#if PS_BLEND_MIX > 0 && PS_BLEND_HW != 1
C_clamped = min(C_clamped, 1.0f);
#endif
@@ -1095,11 +1081,9 @@ void ps_blend(inout vec4 Color, inout vec4 As_rgba)
Color.rgb = trunc((A - B) * C + D);
#endif
#if PS_CLR_HW == 1
// Replace Af with As so we can do proper compensation for Alpha.
#if PS_BLEND_C == 2
As_rgba = vec4(Af);
#endif
#if PS_BLEND_HW == 1
// As or Af
As_rgba.rgb = vec3(C);
// Subtract 1 for alpha to compensate for the changed equation,
// if c.rgb > 255.0f then we further need to adjust alpha accordingly,
// we pick the lowest overflow from all colors because it's the safest,
@@ -1107,7 +1091,7 @@ void ps_blend(inout vec4 Color, inout vec4 As_rgba)
// changed alpha should only be done for hw blend.
vec3 alpha_compensate = max(vec3(1.0f), Color.rgb / vec3(255.0f));
As_rgba.rgb -= alpha_compensate;
#elif PS_CLR_HW == 2
#elif PS_BLEND_HW == 2
// Compensate slightly for Cd*(As + 1) - Cs*As.
// The initial factor we chose is 1 (0.00392)
// as that is the minimum color Cd can be,
@@ -1115,13 +1099,21 @@ void ps_blend(inout vec4 Color, inout vec4 As_rgba)
// blended value it can be.
float color_compensate = 1.0f * (C + 1.0f);
Color.rgb -= vec3(color_compensate);
#elif PS_BLEND_HW == 3
// As, Ad or Af clamped.
As_rgba.rgb = vec3(C_clamped);
// Cs*(Alpha + 1) might overflow, if it does then adjust alpha value
// that is sent on second output to compensate.
vec3 overflow_check = (Color.rgb - vec3(255.0f)) / 255.0f;
vec3 alpha_compensate = max(vec3(0.0f), overflow_check);
As_rgba.rgb -= alpha_compensate;
#endif
#else
#if PS_CLR_HW == 1 || PS_CLR_HW == 5
#if PS_BLEND_HW == 1
// Needed for Cd * (As/Ad/F + 1) blending modes
Color.rgb = vec3(255.0f);
#elif PS_CLR_HW == 2 || PS_CLR_HW == 4
#elif PS_BLEND_HW == 2
// Cd*As,Cd*Ad or Cd*F
#if PS_BLEND_C == 2
@@ -1132,11 +1124,15 @@ void ps_blend(inout vec4 Color, inout vec4 As_rgba)
Color.rgb = max(vec3(0.0f), (Alpha - vec3(1.0f)));
Color.rgb *= vec3(255.0f);
#elif PS_CLR_HW == 3
#elif PS_BLEND_HW == 3
// Needed for Cs*Ad, Cs*Ad + Cd, Cd - Cs*Ad
// Multiply Color.rgb by (255/128) to compensate for wrong Ad/255 value
Color.rgb *= (255.0f / 128.0f);
// Multiply Color.rgb by (255/128) to compensate for wrong Ad/255 value when rgb are below 128.
// When any color channel is higher than 128 then adjust the compensation automatically
// to give us more accurate colors, otherwise they will be wrong.
// The higher the value (>128) the lower the compensation will be.
float max_color = max(max(Color.r, Color.g), Color.b);
float color_compensate = 255.0f / max(128.0f, max_color);
Color.rgb *= vec3(color_compensate);
#endif
#endif
}
@@ -1221,7 +1217,7 @@ void main()
C.a = 128.0f;
#endif
#if (PS_BLEND_C == 1 && PS_CLR_HW > 3)
#if (SW_AD_TO_HW)
vec4 RT = trunc(subpassLoad(RtSampler) * 255.0f + 0.1f);
vec4 alpha_blend = vec4(RT.a / 128.0f);
#else
-113
View File
@@ -1,113 +0,0 @@
set(wx_sdl_c_code "
#include <wx/setup.h>
#if (wxUSE_LIBSDL == 0)
#error cmake_WX_SDL
#endif
int main()
{
return 0;
}
")
set(gcc7_mmx_code "
#include <stdio.h>
#include <stdint.h>
#include <xmmintrin.h>
#include <emmintrin.h>
class alignas(16) GSVector4i
{
public:
__m128i m;
explicit GSVector4i(__m128i m)
{
this->m = m;
}
static void storel(void* p, const GSVector4i& v)
{
_mm_storel_epi64((__m128i*)p, v.m);
}
static GSVector4i loadl(const void* p)
{
return GSVector4i(_mm_loadl_epi64((__m128i*)p));
}
bool eq(const GSVector4i& v) const
{
return _mm_movemask_epi8(_mm_cmpeq_epi32(m, v.m)) == 0xffff;
}
};
union GIFRegTRXPOS
{
unsigned long long u64;
void operator = (const GSVector4i& v) {GSVector4i::storel(this, v);}
bool operator != (const union GIFRegTRXPOS& r) const {return !((GSVector4i)r).eq(*this);}
operator GSVector4i() const {return GSVector4i::loadl(this);}
};
extern GIFRegTRXPOS TRXPOS;
GIFRegTRXPOS TRXPOS = {};
void GIFRegHandlerTRXPOS(const GIFRegTRXPOS& p)
{
if(p != TRXPOS)
{
printf(\"foo\");
}
TRXPOS = (GSVector4i)p;
}
int main()
{
GIFRegTRXPOS r = {};
GIFRegHandlerTRXPOS(r);
uint16_t fpu[16] = {0};
__asm__ __volatile__(\"fstenv %0\" : \"=m\"(fpu));
bool ok = fpu[4] == 0xFFFF;
if (!ok) {
printf(\"Wrong MMX state !\");
exit(1);
}
return 0;
}
")
function(GCC7_BUG)
# try_run doesn't work when cross-compiling is enabled. It is completely silly in our case
# as i386 binaries are 100% fine on x64.
set(OLD_CMAKE_CROSSCOMPILING ${CMAKE_CROSSCOMPILING})
set(CMAKE_CROSSCOMPILING 0)
set(IN "${CMAKE_BINARY_DIR}/gcc7_mmx.cpp")
file(WRITE "${IN}" "${gcc7_mmx_code}")
enable_language(CXX)
try_run(
run_result
compile_result_unused
"${CMAKE_BINARY_DIR}"
"${IN}"
CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=-msse -msse2 -O2 -m32 -march=i686"
)
if (${run_result})
message(FATAL_ERROR "GCC 7.0/7.1 generates invalid code => https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80799\n"
"You can either backport the fix or swith to another version of GCC.")
endif()
set(CMAKE_CROSSCOMPILING ${OLD_CMAKE_CROSSCOMPILING})
endfunction()
+17 -31
View File
@@ -46,12 +46,12 @@ endif()
#-------------------------------------------------------------------------------
option(USE_ASAN "Enable address sanitizer")
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
if(MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(USE_CLANG_CL TRUE)
message(STATUS "Building with Clang-CL.")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
set(USE_CLANG TRUE)
message(STATUS "Building with Clang/LLVM.")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
set(USE_ICC TRUE)
message(STATUS "Building with Intel's ICC.")
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(USE_GCC TRUE)
message(STATUS "Building with GNU GCC")
@@ -103,33 +103,24 @@ include(TargetArch)
target_architecture(PCSX2_TARGET_ARCHITECTURES)
if(${PCSX2_TARGET_ARCHITECTURES} MATCHES "x86_64")
message(STATUS "Compiling a ${PCSX2_TARGET_ARCHITECTURES} build on a ${CMAKE_HOST_SYSTEM_PROCESSOR} host.")
else()
message(FATAL_ERROR "Unsupported architecture: ${PCSX2_TARGET_ARCHITECTURES}")
endif()
if(${PCSX2_TARGET_ARCHITECTURES} MATCHES "x86_64")
# x86_64 requires -fPIC
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
if(NOT DEFINED ARCH_FLAG AND NOT MSVC)
if (DISABLE_ADVANCE_SIMD)
if (USE_ICC)
set(ARCH_FLAG "-msse2 -msse4.1")
else()
set(ARCH_FLAG "-msse -msse2 -msse4.1 -mfxsr")
endif()
set(ARCH_FLAG "-msse -msse2 -msse4.1 -mfxsr")
else()
#set(ARCH_FLAG "-march=native -fabi-version=6")
set(ARCH_FLAG "-march=native")
endif()
elseif(NOT DEFINED ARCH_FLAG AND USE_CLANG_CL)
set(ARCH_FLAG "-msse4.1")
endif()
list(APPEND PCSX2_DEFS _ARCH_64=1 _M_X86=1)
set(_ARCH_64 1)
set(_M_X86 1)
else()
# All but i386 requires -fPIC
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
message(FATAL_ERROR "Unsupported architecture: ${PCSX2_TARGET_ARCHITECTURES}")
endif()
string(REPLACE " " ";" ARCH_FLAG_LIST "${ARCH_FLAG}")
@@ -143,9 +134,9 @@ option(USE_PGO_OPTIMIZE "Enable PGO optimization (use profile)")
# Note1: Builtin strcmp/memcmp was proved to be slower on Mesa than stdlib version.
# Note2: float operation SSE is impacted by the PCSX2 SSE configuration. In particular, flush to zero denormal.
if(MSVC)
if(MSVC AND NOT USE_CLANG_CL)
add_compile_options("$<$<COMPILE_LANGUAGE:CXX>:/Zc:externConstexpr>")
else()
elseif(NOT MSVC)
add_compile_options(-pipe -fvisibility=hidden -pthread -fno-builtin-strcmp -fno-builtin-memcmp -mfpmath=sse)
# -fno-operator-names should only be for C++ files, not C files.
@@ -164,6 +155,12 @@ if(WIN32)
list(APPEND PCSX2_DEFS TIXML_USE_STL _SCL_SECURE_NO_WARNINGS _UNICODE UNICODE)
endif()
# Enable debug information in release builds for Linux.
# Makes the backtrace actually meaningful.
if(UNIX AND NOT APPLE)
add_compile_options($<$<CONFIG:Release>:-g1>)
endif()
if(MSVC)
# Enable PDB generation in release builds
add_compile_options(
@@ -209,24 +206,13 @@ endif()
if (MSVC)
set(DEFAULT_WARNINGS)
else()
set(DEFAULT_WARNINGS -Wall -Wextra -Wno-attributes -Wno-unused-function -Wno-unused-parameter -Wno-missing-field-initializers -Wno-format -Wno-format-security)
if (NOT USE_ICC)
list(APPEND DEFAULT_WARNINGS -Wno-unused-value)
endif()
set(DEFAULT_WARNINGS -Wall -Wextra -Wno-attributes -Wno-unused-function -Wno-unused-parameter -Wno-missing-field-initializers -Wno-format -Wno-format-security -Wno-unused-value)
endif()
if (USE_GCC)
list(APPEND DEFAULT_WARNINGS -Wno-stringop-truncation -Wno-stringop-overflow -Wno-maybe-uninitialized )
endif()
# -Wstrict-aliasing=n: to fix one day aliasing issue. n=1/2/3
if (USE_ICC)
set(AGGRESSIVE_WARNING -Wstrict-aliasing)
elseif(NOT MSVC)
set(AGGRESSIVE_WARNING -Wstrict-aliasing -Wstrict-overflow=1)
endif()
if (USE_PGO_GENERATE OR USE_PGO_OPTIMIZE)
add_compile_options("-fprofile-dir=${CMAKE_SOURCE_DIR}/profile")
endif()
@@ -253,7 +239,7 @@ if(USE_CLANG AND TIMETRACE)
add_compile_options(-ftime-trace)
endif()
set(PCSX2_WARNINGS ${DEFAULT_WARNINGS} ${AGGRESSIVE_WARNING})
set(PCSX2_WARNINGS ${DEFAULT_WARNINGS})
if(DISABLE_BUILD_DATE)
message(STATUS "Disabling the inclusion of the binary compile date.")
+31
View File
@@ -0,0 +1,31 @@
# - Try to find libbacktrace
# Once done this will define
# LIBBACKTRACE_FOUND - System has libbacktrace
# LIBBACKTRACE_INCLUDE_DIRS - The libbacktrace include directories
# LIBBACKTRACE_LIBRARIES - The libraries needed to use libbacktrace
FIND_PATH(
LIBBACKTRACE_INCLUDE_DIR backtrace.h
HINTS /usr/include /usr/local/include
${LIBBACKTRACE_PATH_INCLUDES}
)
FIND_LIBRARY(
LIBBACKTRACE_LIBRARY
NAMES backtrace
PATHS ${ADDITIONAL_LIBRARY_PATHS} ${LIBBACKTRACE_PATH_LIB}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Libbacktrace DEFAULT_MSG
LIBBACKTRACE_LIBRARY LIBBACKTRACE_INCLUDE_DIR)
if(LIBBACKTRACE_FOUND)
add_library(libbacktrace::libbacktrace UNKNOWN IMPORTED)
set_target_properties(libbacktrace::libbacktrace PROPERTIES
IMPORTED_LOCATION ${LIBBACKTRACE_LIBRARY}
INTERFACE_INCLUDE_DIRECTORIES ${LIBBACKTRACE_INCLUDE_DIR}
)
endif()
mark_as_advanced(LIBBACKTRACE_INCLUDE_DIR LIBBACKTRACE_LIBRARY)
+6 -16
View File
@@ -12,21 +12,12 @@ find_path(VTUNE_INCLUDE_DIRS NAMES jitprofiling.h PATHS
/opt/intel/vtune_amplifier_xe_2016/include
)
if(${PCSX2_TARGET_ARCHITECTURES} MATCHES "i386")
find_library(VTUNE_LIBRARIES NAMES libjitprofiling.a PATHS
/opt/intel/oneapi/vtune/latest/lib32
/opt/intel/vtune_amplifier_xe_2018/lib32
/opt/intel/vtune_amplifier_xe_2017/lib32
/opt/intel/vtune_amplifier_xe_2016/lib32
)
else()
find_library(VTUNE_LIBRARIES NAMES libjitprofiling.a PATHS
/opt/intel/oneapi/vtune/latest/lib64
/opt/intel/vtune_amplifier_xe_2018/lib64
/opt/intel/vtune_amplifier_xe_2017/lib64
/opt/intel/vtune_amplifier_xe_2016/lib64
)
endif()
find_library(VTUNE_LIBRARIES NAMES libjitprofiling.a PATHS
/opt/intel/oneapi/vtune/latest/lib64
/opt/intel/vtune_amplifier_xe_2018/lib64
/opt/intel/vtune_amplifier_xe_2017/lib64
/opt/intel/vtune_amplifier_xe_2016/lib64
)
# handle the QUIETLY and REQUIRED arguments and set VTUNE_FOUND to TRUE if
# all listed variables are TRUE
@@ -41,4 +32,3 @@ if(VTUNE_LIBRARIES AND NOT TARGET Vtune::Vtune)
endif()
mark_as_advanced(VTUNE_FOUND VTUNE_INCLUDE_DIRS VTUNE_LIBRARIES)
+7 -13
View File
@@ -86,6 +86,8 @@ else()
if(WAYLAND_API)
find_package(Wayland REQUIRED)
endif()
find_package(Libbacktrace)
endif()
endif(WIN32)
@@ -100,18 +102,7 @@ if(ENABLE_TESTS)
endif()
endif()
#----------------------------------------
# Check correctness of the parameter
# Note: wxWidgets_INCLUDE_DIRS must be defined
#----------------------------------------
include(ApiValidation)
# Blacklist bad GCC
if(GCC_VERSION VERSION_EQUAL "7.0" OR GCC_VERSION VERSION_EQUAL "7.1")
GCC7_BUG()
endif()
if((GCC_VERSION VERSION_EQUAL "9.0" OR GCC_VERSION VERSION_GREATER "9.0") AND GCC_VERSION LESS "9.2")
if(GCC_VERSION VERSION_GREATER_EQUAL "9.0" AND GCC_VERSION VERSION_LESS "9.2")
message(WARNING "
It looks like you are compiling with 9.0.x or 9.1.x. Using these versions is not recommended,
as there is a bug known to cause the compiler to segfault while compiling. See patch
@@ -132,7 +123,7 @@ find_optional_system_library(libzip 3rdparty/libzip 1.8.0)
if(QT_BUILD)
# Default to bundled Qt6 for Windows.
if(WIN32 AND NOT DEFINED Qt6_DIR)
set(Qt6_DIR ${CMAKE_SOURCE_DIR}/3rdparty/qt/6.4.0/msvc2022_64/lib/cmake/Qt6)
set(Qt6_DIR ${CMAKE_SOURCE_DIR}/3rdparty/qt/6.5.0/msvc2022_64/lib/cmake/Qt6)
endif()
# Find the Qt components that we need.
@@ -152,6 +143,9 @@ if(QT_BUILD)
# rcheevos backend for RetroAchievements.
if(USE_ACHIEVEMENTS)
add_subdirectory(3rdparty/rcheevos EXCLUDE_FROM_ALL)
if(WIN32)
add_subdirectory(3rdparty/rainterface EXCLUDE_FROM_ALL)
endif()
endif()
# Discord-RPC library for rich presence.
+5
View File
@@ -288,6 +288,11 @@ if(NOT WIN32 AND (QT_BUILD OR NOGUI_BUILD))
target_link_libraries(common PRIVATE CURL::libcurl)
endif()
if(UNIX AND NOT APPLE AND TARGET libbacktrace::libbacktrace)
target_compile_definitions(common PRIVATE "HAS_LIBBACKTRACE=1")
target_link_libraries(common PRIVATE libbacktrace::libbacktrace)
endif()
target_link_libraries(common PRIVATE
${LIBC_LIBRARIES}
PNG::PNG
+194 -1
View File
@@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2022 PCSX2 Dev Team
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
@@ -215,6 +215,199 @@ void CrashHandler::Uninstall()
}
}
#elif defined(HAS_LIBBACKTRACE)
#include "FileSystem.h"
#include <backtrace.h>
#include <signal.h>
#include <sys/mman.h>
#include <unistd.h>
#include <cstdarg>
#include <cstdio>
#include <mutex>
namespace CrashHandler
{
struct BacktraceBuffer
{
char* buffer;
size_t used;
size_t size;
};
static const char* GetSignalName(int signal_no);
static void AllocateBuffer(BacktraceBuffer* buf);
static void FreeBuffer(BacktraceBuffer* buf);
static void AppendToBuffer(BacktraceBuffer* buf, const char* format, ...);
static int BacktraceFullCallback(void* data, uintptr_t pc, const char* filename, int lineno, const char* function);
static void CallExistingSignalHandler(int signal, siginfo_t* siginfo, void* ctx);
static void CrashSignalHandler(int signal, siginfo_t* siginfo, void* ctx);
static std::recursive_mutex s_crash_mutex;
static bool s_in_signal_handler = false;
static backtrace_state* s_backtrace_state = nullptr;
static struct sigaction s_old_sigbus_action;
static struct sigaction s_old_sigsegv_action;
}
const char* CrashHandler::GetSignalName(int signal_no)
{
switch (signal_no)
{
// Don't need to list all of them, there's only a couple we register.
// clang-format off
case SIGSEGV: return "SIGSEGV";
case SIGBUS: return "SIGBUS";
default: return "UNKNOWN";
// clang-format on
}
}
void CrashHandler::AllocateBuffer(BacktraceBuffer* buf)
{
buf->used = 0;
buf->size = __pagesize;
buf->buffer = static_cast<char*>(mmap(nullptr, buf->size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
if (buf->buffer == static_cast<char*>(MAP_FAILED))
{
buf->buffer = nullptr;
buf->size = 0;
}
}
void CrashHandler::FreeBuffer(BacktraceBuffer* buf)
{
if (buf->buffer)
munmap(buf->buffer, buf->size);
}
void CrashHandler::AppendToBuffer(BacktraceBuffer* buf, const char* format, ...)
{
std::va_list ap;
va_start(ap, format);
// Hope this doesn't allocate memory... it *can*, but hopefully unlikely since
// it won't be the first call, and we're providing the buffer.
if (buf->size > 0 && buf->used < (buf->size - 1))
{
const int written = std::vsnprintf(buf->buffer + buf->used, buf->size - buf->used, format, ap);
if (written > 0)
buf->used += static_cast<size_t>(written);
}
va_end(ap);
}
int CrashHandler::BacktraceFullCallback(void* data, uintptr_t pc, const char* filename, int lineno, const char* function)
{
BacktraceBuffer* buf = static_cast<BacktraceBuffer*>(data);
AppendToBuffer(buf, " %016p", pc);
if (function)
AppendToBuffer(buf, " %s", function);
if (filename)
AppendToBuffer(buf, " [%s:%d]", filename, lineno);
AppendToBuffer(buf, "\n");
return 0;
}
void CrashHandler::CallExistingSignalHandler(int signal, siginfo_t* siginfo, void* ctx)
{
const struct sigaction& sa = (signal == SIGBUS) ? s_old_sigbus_action : s_old_sigsegv_action;
if (sa.sa_flags & SA_SIGINFO)
{
sa.sa_sigaction(signal, siginfo, ctx);
}
else if (sa.sa_handler == SIG_DFL)
{
// Re-raising the signal would just queue it, and since we'd restore the handler back to us,
// we'd end up right back here again. So just abort, because that's probably what it'd do anyway.
abort();
}
else if (sa.sa_handler != SIG_IGN)
{
sa.sa_handler(signal);
}
}
void CrashHandler::CrashSignalHandler(int signal, siginfo_t* siginfo, void* ctx)
{
std::unique_lock lock(s_crash_mutex);
// If we crash somewhere in libbacktrace, don't bother trying again.
if (!s_in_signal_handler)
{
s_in_signal_handler = true;
#if defined(__APPLE__) && defined(__x86_64__)
void* const exception_pc = reinterpret_cast<void*>(static_cast<ucontext_t*>(ctx)->uc_mcontext->__ss.__rip);
#elif defined(__FreeBSD__) && defined(__x86_64__)
void* const exception_pc = reinterpret_cast<void*>(static_cast<ucontext_t*>(ctx)->uc_mcontext.mc_rip);
#elif defined(__x86_64__)
void* const exception_pc = reinterpret_cast<void*>(static_cast<ucontext_t*>(ctx)->uc_mcontext.gregs[REG_RIP]);
#else
void* const exception_pc = nullptr;
#endif
BacktraceBuffer buf;
AllocateBuffer(&buf);
AppendToBuffer(&buf, "*************** Unhandled %s at %p ***************\n", GetSignalName(signal), exception_pc);
const int rc = backtrace_full(s_backtrace_state, 0, BacktraceFullCallback, nullptr, &buf);
if (rc != 0)
AppendToBuffer(&buf, " backtrace_full() failed: %d\n");
AppendToBuffer(&buf, "*******************************************************************\n");
if (buf.used > 0)
write(STDERR_FILENO, buf.buffer, buf.used);
FreeBuffer(&buf);
s_in_signal_handler = false;
}
// Chances are we're not going to have anything else to call, but just in case.
lock.unlock();
CallExistingSignalHandler(signal, siginfo, ctx);
}
bool CrashHandler::Install()
{
const std::string progpath = FileSystem::GetProgramPath();
s_backtrace_state = backtrace_create_state(progpath.empty() ? nullptr : progpath.c_str(), 0, nullptr, nullptr);
if (!s_backtrace_state)
return false;
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO | SA_NODEFER;
sa.sa_sigaction = CrashSignalHandler;
if (sigaction(SIGBUS, &sa, &s_old_sigbus_action) != 0)
return false;
if (sigaction(SIGSEGV, &sa, &s_old_sigsegv_action) != 0)
return false;
return true;
}
void CrashHandler::SetWriteDirectory(const std::string_view& dump_directory)
{
}
void CrashHandler::WriteDumpForCaller()
{
}
void CrashHandler::Uninstall()
{
// We can't really unchain the signal handlers... so, YOLO.
}
#else
bool CrashHandler::Install()
+15 -14
View File
@@ -41,10 +41,7 @@ D3D11::ShaderCache::ShaderCache() = default;
D3D11::ShaderCache::~ShaderCache()
{
if (m_index_file)
std::fclose(m_index_file);
if (m_blob_file)
std::fclose(m_blob_file);
Close();
}
bool D3D11::ShaderCache::CacheIndexKey::operator==(const CacheIndexKey& key) const
@@ -82,6 +79,20 @@ bool D3D11::ShaderCache::Open(std::string_view base_path, D3D_FEATURE_LEVEL feat
return true;
}
void D3D11::ShaderCache::Close()
{
if (m_index_file)
{
std::fclose(m_index_file);
m_index_file = nullptr;
}
if (m_blob_file)
{
std::fclose(m_blob_file);
m_blob_file = nullptr;
}
}
bool D3D11::ShaderCache::CreateNew(const std::string& index_filename, const std::string& blob_filename)
{
if (FileSystem::FileExists(index_filename.c_str()))
@@ -326,16 +337,6 @@ bool D3D11::ShaderCache::GetVertexShaderAndInputLayout(ID3D11Device* device,
return true;
}
wil::com_ptr_nothrow<ID3D11GeometryShader> D3D11::ShaderCache::GetGeometryShader(ID3D11Device* device,
const std::string_view& shader_code, const D3D_SHADER_MACRO* macros /* = nullptr */, const char* entry_point /* = "main" */)
{
wil::com_ptr_nothrow<ID3DBlob> blob = GetShaderBlob(ShaderCompiler::Type::Geometry, shader_code, macros, entry_point);
if (!blob)
return {};
return D3D11::ShaderCompiler::CreateGeometryShader(device, blob.get());
}
wil::com_ptr_nothrow<ID3D11PixelShader> D3D11::ShaderCache::GetPixelShader(ID3D11Device* device,
const std::string_view& shader_code, const D3D_SHADER_MACRO* macros /* = nullptr */, const char* entry_point /* = "main" */)
{
+1 -4
View File
@@ -38,6 +38,7 @@ namespace D3D11
bool UsingDebugShaders() const { return m_debug; }
bool Open(std::string_view base_path, D3D_FEATURE_LEVEL feature_level, u32 version, bool debug);
void Close();
wil::com_ptr_nothrow<ID3DBlob> GetShaderBlob(ShaderCompiler::Type type, const std::string_view& shader_code,
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
@@ -50,9 +51,6 @@ namespace D3D11
const D3D11_INPUT_ELEMENT_DESC* layout, size_t layout_size,
const std::string_view& shader_code, const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
wil::com_ptr_nothrow<ID3D11GeometryShader> GetGeometryShader(ID3D11Device* device, const std::string_view& shader_code,
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
wil::com_ptr_nothrow<ID3D11PixelShader> GetPixelShader(ID3D11Device* device, const std::string_view& shader_code,
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
@@ -103,7 +101,6 @@ namespace D3D11
bool CreateNew(const std::string& index_filename, const std::string& blob_filename);
bool ReadExisting(const std::string& index_filename, const std::string& blob_filename);
void Close();
wil::com_ptr_nothrow<ID3DBlob> CompileAndAddShaderBlob(const CacheIndexKey& key, const std::string_view& shader_code,
const D3D_SHADER_MACRO* macros, const char* entry_point);
+5 -34
View File
@@ -31,21 +31,21 @@ wil::com_ptr_nothrow<ID3DBlob> D3D11::ShaderCompiler::CompileShader(Type type, D
{
case D3D_FEATURE_LEVEL_10_0:
{
static constexpr std::array<const char*, 4> targets = {{"vs_4_0", "gs_4_0", "ps_4_0", "cs_4_0"}};
static constexpr std::array<const char*, 4> targets = {{"vs_4_0", "ps_4_0", "cs_4_0"}};
target = targets[static_cast<int>(type)];
}
break;
case D3D_FEATURE_LEVEL_10_1:
{
static constexpr std::array<const char*, 4> targets = {{"vs_4_1", "gs_4_1", "ps_4_1", "cs_4_1"}};
static constexpr std::array<const char*, 4> targets = {{"vs_4_1", "ps_4_1", "cs_4_1"}};
target = targets[static_cast<int>(type)];
}
break;
case D3D_FEATURE_LEVEL_11_0:
{
static constexpr std::array<const char*, 4> targets = {{"vs_5_0", "gs_5_0", "ps_5_0", "cs_5_0"}};
static constexpr std::array<const char*, 4> targets = {{"vs_5_0", "ps_5_0", "cs_5_0"}};
target = targets[static_cast<int>(type)];
}
break;
@@ -53,7 +53,7 @@ wil::com_ptr_nothrow<ID3DBlob> D3D11::ShaderCompiler::CompileShader(Type type, D
case D3D_FEATURE_LEVEL_11_1:
default:
{
static constexpr std::array<const char*, 4> targets = {{"vs_5_1", "gs_5_1", "ps_5_1", "cs_5_1"}};
static constexpr std::array<const char*, 4> targets = {{"vs_5_1", "ps_5_1", "cs_5_1"}};
target = targets[static_cast<int>(type)];
}
break;
@@ -79,7 +79,7 @@ wil::com_ptr_nothrow<ID3DBlob> D3D11::ShaderCompiler::CompileShader(Type type, D
{
Console.WriteLn("Failed to compile '%s':\n%s", target, error_string.c_str());
std::ofstream ofs(StringUtil::StdStringFromFormat("bad_shader_%u.txt", s_next_bad_shader_id++).c_str(),
std::ofstream ofs(StringUtil::StdStringFromFormat("pcsx2_bad_shader_%u.txt", s_next_bad_shader_id++).c_str(),
std::ofstream::out | std::ofstream::binary);
if (ofs.is_open())
{
@@ -108,16 +108,6 @@ wil::com_ptr_nothrow<ID3D11VertexShader> D3D11::ShaderCompiler::CompileAndCreate
return CreateVertexShader(device, blob.get());
}
wil::com_ptr_nothrow<ID3D11GeometryShader> D3D11::ShaderCompiler::CompileAndCreateGeometryShader(ID3D11Device* device, bool debug,
const std::string_view& code, const D3D_SHADER_MACRO* macros /* = nullptr */, const char* entry_point /* = "main" */)
{
wil::com_ptr_nothrow<ID3DBlob> blob = CompileShader(Type::Geometry, device->GetFeatureLevel(), debug, code, macros, entry_point);
if (!blob)
return {};
return CreateGeometryShader(device, blob.get());
}
wil::com_ptr_nothrow<ID3D11PixelShader> D3D11::ShaderCompiler::CompileAndCreatePixelShader(ID3D11Device* device, bool debug,
const std::string_view& code, const D3D_SHADER_MACRO* macros /* = nullptr */, const char* entry_point /* = "main" */)
{
@@ -157,25 +147,6 @@ wil::com_ptr_nothrow<ID3D11VertexShader> D3D11::ShaderCompiler::CreateVertexShad
const_cast<ID3DBlob*>(blob)->GetBufferSize());
}
wil::com_ptr_nothrow<ID3D11GeometryShader> D3D11::ShaderCompiler::CreateGeometryShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length)
{
wil::com_ptr_nothrow<ID3D11GeometryShader> shader;
const HRESULT hr = device->CreateGeometryShader(bytecode, bytecode_length, nullptr, shader.put());
if (FAILED(hr))
{
Console.Error("Failed to create geometry shader: 0x%08X", hr);
return {};
}
return shader;
}
wil::com_ptr_nothrow<ID3D11GeometryShader> D3D11::ShaderCompiler::CreateGeometryShader(ID3D11Device* device, const ID3DBlob* blob)
{
return CreateGeometryShader(device, const_cast<ID3DBlob*>(blob)->GetBufferPointer(),
const_cast<ID3DBlob*>(blob)->GetBufferSize());
}
wil::com_ptr_nothrow<ID3D11PixelShader> D3D11::ShaderCompiler::CreatePixelShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length)
{
wil::com_ptr_nothrow<ID3D11PixelShader> shader;
-5
View File
@@ -27,7 +27,6 @@ namespace D3D11::ShaderCompiler
enum class Type
{
Vertex,
Geometry,
Pixel,
Compute
};
@@ -37,8 +36,6 @@ namespace D3D11::ShaderCompiler
wil::com_ptr_nothrow<ID3D11VertexShader> CompileAndCreateVertexShader(ID3D11Device* device, bool debug, const std::string_view& code,
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
wil::com_ptr_nothrow<ID3D11GeometryShader> CompileAndCreateGeometryShader(ID3D11Device* device, bool debug, const std::string_view& code,
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
wil::com_ptr_nothrow<ID3D11PixelShader> CompileAndCreatePixelShader(ID3D11Device* device, bool debug, const std::string_view& code,
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
wil::com_ptr_nothrow<ID3D11ComputeShader> CompileAndCreateComputeShader(ID3D11Device* device, bool debug, const std::string_view& code,
@@ -46,8 +43,6 @@ namespace D3D11::ShaderCompiler
wil::com_ptr_nothrow<ID3D11VertexShader> CreateVertexShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length);
wil::com_ptr_nothrow<ID3D11VertexShader> CreateVertexShader(ID3D11Device* device, const ID3DBlob* blob);
wil::com_ptr_nothrow<ID3D11GeometryShader> CreateGeometryShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length);
wil::com_ptr_nothrow<ID3D11GeometryShader> CreateGeometryShader(ID3D11Device* device, const ID3DBlob* blob);
wil::com_ptr_nothrow<ID3D11PixelShader> CreatePixelShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length);
wil::com_ptr_nothrow<ID3D11PixelShader> CreatePixelShader(ID3D11Device* device, const ID3DBlob* blob);
wil::com_ptr_nothrow<ID3D11ComputeShader> CreateComputeShader(ID3D11Device* device, const void* bytecode, size_t bytecode_length);
+68 -34
View File
@@ -125,15 +125,18 @@ bool Context::SupportsTextureFormat(DXGI_FORMAT format)
(support.Support1 & required) == required;
}
bool Context::Create(IDXGIFactory* dxgi_factory, u32 adapter_index, bool enable_debug_layer)
bool Context::Create(IDXGIFactory5* dxgi_factory, IDXGIAdapter1* adapter, bool enable_debug_layer)
{
pxAssertRel(!g_d3d12_context, "No context exists");
if (!LoadD3D12Library())
{
Console.Error("Failed to load D3D12 library");
return false;
}
g_d3d12_context.reset(new Context());
if (!g_d3d12_context->CreateDevice(dxgi_factory, adapter_index, enable_debug_layer) ||
if (!g_d3d12_context->CreateDevice(dxgi_factory, adapter, enable_debug_layer) ||
!g_d3d12_context->CreateCommandQueue() || !g_d3d12_context->CreateAllocator() ||
!g_d3d12_context->CreateFence() || !g_d3d12_context->CreateDescriptorHeaps() ||
!g_d3d12_context->CreateCommandLists() || !g_d3d12_context->CreateTimestampQuery() ||
@@ -166,31 +169,9 @@ u32 Context::GetAdapterVendorID() const
return desc.VendorId;
}
bool Context::CreateDevice(IDXGIFactory* dxgi_factory, u32 adapter_index, bool enable_debug_layer)
bool Context::CreateDevice(IDXGIFactory5* dxgi_factory, IDXGIAdapter1* adapter, bool enable_debug_layer)
{
ComPtr<IDXGIAdapter> adapter;
HRESULT hr = dxgi_factory->EnumAdapters(adapter_index, &adapter);
if (FAILED(hr))
{
Console.Error("Adapter %u not found, using default", adapter_index);
adapter = nullptr;
}
else
{
DXGI_ADAPTER_DESC adapter_desc;
if (SUCCEEDED(adapter->GetDesc(&adapter_desc)))
{
char adapter_name_buffer[128];
const int name_length = WideCharToMultiByte(CP_UTF8, 0, adapter_desc.Description,
static_cast<int>(std::wcslen(adapter_desc.Description)),
adapter_name_buffer, std::size(adapter_name_buffer), 0, nullptr);
if (name_length >= 0)
{
adapter_name_buffer[name_length] = 0;
Console.WriteLn("D3D Adapter: %s", adapter_name_buffer);
}
}
}
HRESULT hr;
// Enabling the debug layer will fail if the Graphics Tools feature is not installed.
if (enable_debug_layer)
@@ -208,18 +189,17 @@ bool Context::CreateDevice(IDXGIFactory* dxgi_factory, u32 adapter_index, bool e
}
// Create the actual device.
hr = s_d3d12_create_device(adapter.get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
hr = s_d3d12_create_device(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
if (FAILED(hr))
{
Console.Error("Failed to create D3D12 device: %08X", hr);
return false;
}
// get adapter
ComPtr<IDXGIFactory4> dxgi_factory4;
if (SUCCEEDED(dxgi_factory->QueryInterface<IDXGIFactory4>(dxgi_factory4.put())))
{
const LUID luid(m_device->GetAdapterLuid());
if (FAILED(dxgi_factory4->EnumAdapterByLuid(luid, IID_PPV_ARGS(m_adapter.put()))))
Console.Error("Failed to get lookup adapter by device LUID");
}
const LUID luid(m_device->GetAdapterLuid());
if (FAILED(dxgi_factory->EnumAdapterByLuid(luid, IID_PPV_ARGS(m_adapter.put()))))
Console.Error("Failed to get lookup adapter by device LUID");
if (enable_debug_layer)
{
@@ -685,3 +665,57 @@ void Context::SetEnableGPUTiming(bool enabled)
{
m_gpu_timing_enabled = enabled;
}
bool Context::AllocatePreinitializedGPUBuffer(u32 size, ID3D12Resource** gpu_buffer,
D3D12MA::Allocation** gpu_allocation, const std::function<void(void*)>& fill_callback)
{
// Try to place the fixed index buffer in GPU local memory.
// Use the staging buffer to copy into it.
const D3D12_RESOURCE_DESC rd = {D3D12_RESOURCE_DIMENSION_BUFFER, 0, size, 1, 1, 1,
DXGI_FORMAT_UNKNOWN, {1, 0}, D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
D3D12_RESOURCE_FLAG_NONE};
const D3D12MA::ALLOCATION_DESC cpu_ad = {
D3D12MA::ALLOCATION_FLAG_NONE,
D3D12_HEAP_TYPE_UPLOAD};
ComPtr<ID3D12Resource> cpu_buffer;
ComPtr<D3D12MA::Allocation> cpu_allocation;
HRESULT hr = m_allocator->CreateResource(&cpu_ad, &rd, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr,
cpu_allocation.put(), IID_PPV_ARGS(cpu_buffer.put()));
pxAssertMsg(SUCCEEDED(hr), "Allocate CPU buffer");
if (FAILED(hr))
return false;
static constexpr const D3D12_RANGE read_range = {};
const D3D12_RANGE write_range = {0, size};
void* mapped;
hr = cpu_buffer->Map(0, &read_range, &mapped);
pxAssertMsg(SUCCEEDED(hr), "Map CPU buffer");
if (FAILED(hr))
return false;
fill_callback(mapped);
cpu_buffer->Unmap(0, &write_range);
const D3D12MA::ALLOCATION_DESC gpu_ad = {
D3D12MA::ALLOCATION_FLAG_COMMITTED,
D3D12_HEAP_TYPE_DEFAULT};
hr = m_allocator->CreateResource(&gpu_ad, &rd, D3D12_RESOURCE_STATE_COPY_DEST, nullptr,
gpu_allocation, IID_PPV_ARGS(gpu_buffer));
pxAssertMsg(SUCCEEDED(hr), "Allocate GPU buffer");
if (FAILED(hr))
return false;
GetInitCommandList()->CopyBufferRegion(*gpu_buffer, 0, cpu_buffer.get(), 0, size);
D3D12_RESOURCE_BARRIER rb = {D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, D3D12_RESOURCE_BARRIER_FLAG_NONE};
rb.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
rb.Transition.pResource = *gpu_buffer;
rb.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST;
rb.Transition.StateAfter = D3D12_RESOURCE_STATE_INDEX_BUFFER;
GetInitCommandList()->ResourceBarrier(1, &rb);
DeferResourceDestruction(cpu_allocation.get(), cpu_buffer.get());
return true;
}
+7 -2
View File
@@ -22,6 +22,7 @@
#include <array>
#include <d3d12.h>
#include <dxgi1_5.h>
#include <memory>
#include <vector>
#include <wil/com.h>
@@ -60,7 +61,7 @@ namespace D3D12
~Context();
/// Creates new device and context.
static bool Create(IDXGIFactory* dxgi_factory, u32 adapter_index, bool enable_debug_layer);
static bool Create(IDXGIFactory5* dxgi_factory, IDXGIAdapter1* adapter, bool enable_debug_layer);
/// Destroys active context.
static void Destroy();
@@ -151,6 +152,10 @@ namespace D3D12
float GetAndResetAccumulatedGPUTime();
void SetEnableGPUTiming(bool enabled);
// Allocates a temporary CPU staging buffer, fires the callback with it to populate, then copies to a GPU buffer.
bool AllocatePreinitializedGPUBuffer(u32 size, ID3D12Resource** gpu_buffer, D3D12MA::Allocation** gpu_allocation,
const std::function<void(void*)>& fill_callback);
private:
struct CommandListResources
{
@@ -167,7 +172,7 @@ namespace D3D12
Context();
bool CreateDevice(IDXGIFactory* dxgi_factory, u32 adapter_index, bool enable_debug_layer);
bool CreateDevice(IDXGIFactory5* dxgi_factory, IDXGIAdapter1* adapter, bool enable_debug_layer);
bool CreateCommandQueue();
bool CreateAllocator();
bool CreateFence();
+27 -11
View File
@@ -45,14 +45,7 @@ ShaderCache::ShaderCache() = default;
ShaderCache::~ShaderCache()
{
if (m_pipeline_index_file)
std::fclose(m_pipeline_index_file);
if (m_pipeline_blob_file)
std::fclose(m_pipeline_blob_file);
if (m_shader_index_file)
std::fclose(m_shader_index_file);
if (m_shader_blob_file)
std::fclose(m_shader_blob_file);
Close();
}
bool ShaderCache::CacheIndexKey::operator==(const CacheIndexKey& key) const
@@ -109,6 +102,32 @@ bool ShaderCache::Open(std::string_view base_path, D3D_FEATURE_LEVEL feature_lev
return result;
}
void ShaderCache::Close()
{
if (m_pipeline_index_file)
{
std::fclose(m_pipeline_index_file);
m_pipeline_index_file = nullptr;
}
if (m_pipeline_blob_file)
{
std::fclose(m_pipeline_blob_file);
m_pipeline_blob_file = nullptr;
}
if (m_shader_index_file)
{
std::fclose(m_shader_index_file);
m_shader_index_file = nullptr;
}
if (m_shader_blob_file)
{
std::fclose(m_shader_blob_file);
m_shader_blob_file = nullptr;
}
m_base_path = {};
}
void ShaderCache::InvalidatePipelineCache()
{
m_pipeline_index.clear();
@@ -502,9 +521,6 @@ ShaderCache::ComPtr<ID3DBlob> ShaderCache::CompileAndAddShaderBlob(const CacheIn
case EntryType::VertexShader:
blob = D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Vertex, m_feature_level, m_debug, shader_code, macros, entry_point);
break;
case EntryType::GeometryShader:
blob = D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Geometry, m_feature_level, m_debug, shader_code, macros, entry_point);
break;
case EntryType::PixelShader:
blob = D3D11::ShaderCompiler::CompileShader(D3D11::ShaderCompiler::Type::Pixel, m_feature_level, m_debug, shader_code, macros, entry_point);
break;
+1 -7
View File
@@ -37,7 +37,6 @@ namespace D3D12
enum class EntryType
{
VertexShader,
GeometryShader,
PixelShader,
ComputeShader,
GraphicsPipeline,
@@ -52,17 +51,13 @@ namespace D3D12
__fi bool UsingDebugShaders() const { return m_debug; }
bool Open(std::string_view base_path, D3D_FEATURE_LEVEL feature_level, u32 version, bool debug);
void Close();
__fi ComPtr<ID3DBlob> GetVertexShader(std::string_view shader_code,
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main")
{
return GetShaderBlob(EntryType::VertexShader, shader_code, macros, entry_point);
}
__fi ComPtr<ID3DBlob> GetGeometryShader(std::string_view shader_code,
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main")
{
return GetShaderBlob(EntryType::GeometryShader, shader_code, macros, entry_point);
}
__fi ComPtr<ID3DBlob> GetPixelShader(std::string_view shader_code,
const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main")
{
@@ -129,7 +124,6 @@ namespace D3D12
bool ReadExisting(const std::string& index_filename, const std::string& blob_filename, std::FILE*& index_file,
std::FILE*& blob_file, CacheIndex& index);
void InvalidatePipelineCache();
void Close();
ComPtr<ID3DBlob> CompileAndAddShaderBlob(const CacheIndexKey& key, std::string_view shader_code,
const D3D_SHADER_MACRO* macros, const char* entry_point);
-13
View File
@@ -56,17 +56,6 @@ namespace GL
#endif
}
static void DisableBrokenExtensions(const char* gl_vendor, const char* gl_renderer)
{
if (std::strstr(gl_vendor, "ARM"))
{
// GL_{EXT,OES}_copy_image seem to be implemented on the CPU in the Mali drivers...
Console.Warning("Mali driver detected, disabling GL_{EXT,OES}_copy_image");
GLAD_GL_EXT_copy_image = 0;
GLAD_GL_OES_copy_image = 0;
}
}
Context::Context(const WindowInfo& wi)
: m_wi(wi)
{
@@ -154,8 +143,6 @@ namespace GL
DevCon.WriteLn(Color_Magenta, "GL_VERSION: %s", gl_version);
DevCon.WriteLn(Color_Magenta, "GL_SHADING_LANGUAGE_VERSION: %s", gl_shading_language_version);
DisableBrokenExtensions(gl_vendor, gl_renderer);
return context;
}
+22 -161
View File
@@ -77,7 +77,7 @@ namespace GL
{
Console.Error("Shader failed to compile:\n%s", info_log.c_str());
std::ofstream ofs(StringUtil::StdStringFromFormat("bad_shader_%u.txt", s_next_bad_shader_id++).c_str(),
std::ofstream ofs(StringUtil::StdStringFromFormat("pcsx2_bad_shader_%u.txt", s_next_bad_shader_id++).c_str(),
std::ofstream::out | std::ofstream::binary);
if (ofs.is_open())
{
@@ -100,43 +100,27 @@ namespace GL
s_last_program_id = 0;
}
bool Program::Compile(const std::string_view vertex_shader, const std::string_view geometry_shader,
const std::string_view fragment_shader)
bool Program::Compile(const std::string_view vertex_shader, const std::string_view fragment_shader)
{
GLuint vertex_shader_id = 0;
if (!vertex_shader.empty())
{
vertex_shader_id = CompileShader(GL_VERTEX_SHADER, vertex_shader);
if (vertex_shader_id == 0)
m_vertex_shader_id = CompileShader(GL_VERTEX_SHADER, vertex_shader);
if (m_vertex_shader_id == 0)
return false;
}
GLuint geometry_shader_id = 0;
if (!geometry_shader.empty())
{
geometry_shader_id = CompileShader(GL_GEOMETRY_SHADER, geometry_shader);
if (geometry_shader_id == 0)
return false;
}
GLuint fragment_shader_id = 0;
if (!fragment_shader.empty())
{
fragment_shader_id = CompileShader(GL_FRAGMENT_SHADER, fragment_shader);
if (fragment_shader_id == 0)
{
glDeleteShader(vertex_shader_id);
m_fragment_shader_id = CompileShader(GL_FRAGMENT_SHADER, fragment_shader);
if (m_fragment_shader_id == 0)
return false;
}
}
m_program_id = glCreateProgram();
if (vertex_shader_id != 0)
glAttachShader(m_program_id, vertex_shader_id);
if (geometry_shader_id != 0)
glAttachShader(m_program_id, geometry_shader_id);
if (fragment_shader_id != 0)
glAttachShader(m_program_id, fragment_shader_id);
if (m_vertex_shader_id != 0)
glAttachShader(m_program_id, m_vertex_shader_id);
if (m_fragment_shader_id != 0)
glAttachShader(m_program_id, m_fragment_shader_id);
return true;
}
@@ -485,151 +469,28 @@ namespace GL
glUniform4fv(location, 1, v);
}
void Program::Uniform1ui(const char* name, u32 x) const
void Program::UniformMatrix2fv(int index, const float* v)
{
const GLint location = glGetUniformLocation(m_program_id, name);
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
const GLint location = m_uniform_locations[index];
if (location >= 0)
glUniform1ui(location, x);
glUniformMatrix2fv(location, 1, GL_FALSE, v);
}
void Program::Uniform2ui(const char* name, u32 x, u32 y) const
void Program::UniformMatrix3fv(int index, const float* v)
{
const GLint location = glGetUniformLocation(m_program_id, name);
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
const GLint location = m_uniform_locations[index];
if (location >= 0)
glUniform2ui(location, x, y);
glUniformMatrix3fv(location, 1, GL_FALSE, v);
}
void Program::Uniform3ui(const char* name, u32 x, u32 y, u32 z) const
void Program::UniformMatrix4fv(int index, const float* v)
{
const GLint location = glGetUniformLocation(m_program_id, name);
pxAssert(static_cast<size_t>(index) < m_uniform_locations.size());
const GLint location = m_uniform_locations[index];
if (location >= 0)
glUniform3ui(location, x, y, z);
}
void Program::Uniform4ui(const char* name, u32 x, u32 y, u32 z, u32 w) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform4ui(location, x, y, z, w);
}
void Program::Uniform1i(const char* name, s32 x) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform1i(location, x);
}
void Program::Uniform2i(const char* name, s32 x, s32 y) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform2i(location, x, y);
}
void Program::Uniform3i(const char* name, s32 x, s32 y, s32 z) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform3i(location, x, y, z);
}
void Program::Uniform4i(const char* name, s32 x, s32 y, s32 z, s32 w) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform4i(location, x, y, z, w);
}
void Program::Uniform1f(const char* name, float x) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform1f(location, x);
}
void Program::Uniform2f(const char* name, float x, float y) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform2f(location, x, y);
}
void Program::Uniform3f(const char* name, float x, float y, float z) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform3f(location, x, y, z);
}
void Program::Uniform4f(const char* name, float x, float y, float z, float w) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform4f(location, x, y, z, w);
}
void Program::Uniform2uiv(const char* name, const u32* v) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform2uiv(location, 1, v);
}
void Program::Uniform3uiv(const char* name, const u32* v) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform3uiv(location, 1, v);
}
void Program::Uniform4uiv(const char* name, const u32* v) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform4uiv(location, 1, v);
}
void Program::Uniform2iv(const char* name, const s32* v) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform2iv(location, 1, v);
}
void Program::Uniform3iv(const char* name, const s32* v) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform3iv(location, 1, v);
}
void Program::Uniform4iv(const char* name, const s32* v) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform4iv(location, 1, v);
}
void Program::Uniform2fv(const char* name, const float* v) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform2fv(location, 1, v);
}
void Program::Uniform3fv(const char* name, const float* v) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform3fv(location, 1, v);
}
void Program::Uniform4fv(const char* name, const float* v) const
{
const GLint location = glGetUniformLocation(m_program_id, name);
if (location >= 0)
glUniform4fv(location, 1, v);
glUniformMatrix4fv(location, 1, GL_FALSE, v);
}
void Program::BindUniformBlock(const char* name, u32 index)
+4 -23
View File
@@ -34,8 +34,7 @@ namespace GL
bool IsValid() const { return m_program_id != 0; }
bool Compile(const std::string_view vertex_shader, const std::string_view geometry_shader,
const std::string_view fragment_shader);
bool Compile(const std::string_view vertex_shader, const std::string_view fragment_shader);
bool CompileCompute(const std::string_view glsl);
@@ -79,27 +78,9 @@ namespace GL
void Uniform3fv(int index, const float* v) const;
void Uniform4fv(int index, const float* v) const;
void Uniform1ui(const char* name, u32 x) const;
void Uniform2ui(const char* name, u32 x, u32 y) const;
void Uniform3ui(const char* name, u32 x, u32 y, u32 z) const;
void Uniform4ui(const char* name, u32 x, u32 y, u32 z, u32 w) const;
void Uniform1i(const char* name, s32 x) const;
void Uniform2i(const char* name, s32 x, s32 y) const;
void Uniform3i(const char* name, s32 x, s32 y, s32 z) const;
void Uniform4i(const char* name, s32 x, s32 y, s32 z, s32 w) const;
void Uniform1f(const char* name, float x) const;
void Uniform2f(const char* name, float x, float y) const;
void Uniform3f(const char* name, float x, float y, float z) const;
void Uniform4f(const char* name, float x, float y, float z, float w) const;
void Uniform2uiv(const char* name, const u32* v) const;
void Uniform3uiv(const char* name, const u32* v) const;
void Uniform4uiv(const char* name, const u32* v) const;
void Uniform2iv(const char* name, const s32* v) const;
void Uniform3iv(const char* name, const s32* v) const;
void Uniform4iv(const char* name, const s32* v) const;
void Uniform2fv(const char* name, const float* v) const;
void Uniform3fv(const char* name, const float* v) const;
void Uniform4fv(const char* name, const float* v) const;
void UniformMatrix2fv(int index, const float* v);
void UniformMatrix3fv(int index, const float* v);
void UniformMatrix4fv(int index, const float* v);
void BindUniformBlock(const char* name, u32 index);
+22 -41
View File
@@ -28,9 +28,6 @@ namespace GL
u64 vertex_source_hash_low;
u64 vertex_source_hash_high;
u32 vertex_source_length;
u64 geometry_source_hash_low;
u64 geometry_source_hash_high;
u32 geometry_source_length;
u64 fragment_source_hash_low;
u64 fragment_source_hash_high;
u32 fragment_source_length;
@@ -51,9 +48,7 @@ namespace GL
{
return (
vertex_source_hash_low == key.vertex_source_hash_low && vertex_source_hash_high == key.vertex_source_hash_high &&
vertex_source_length == key.vertex_source_length && geometry_source_hash_low == key.geometry_source_hash_low &&
geometry_source_hash_high == key.geometry_source_hash_high &&
geometry_source_length == key.geometry_source_length && fragment_source_hash_low == key.fragment_source_hash_low &&
vertex_source_length == key.vertex_source_length && fragment_source_hash_low == key.fragment_source_hash_low &&
fragment_source_hash_high == key.fragment_source_hash_high && fragment_source_length == key.fragment_source_length);
}
@@ -61,9 +56,7 @@ namespace GL
{
return (
vertex_source_hash_low != key.vertex_source_hash_low || vertex_source_hash_high != key.vertex_source_hash_high ||
vertex_source_length != key.vertex_source_length || geometry_source_hash_low != key.geometry_source_hash_low ||
geometry_source_hash_high != key.geometry_source_hash_high ||
geometry_source_length != key.geometry_source_length || fragment_source_hash_low != key.fragment_source_hash_low ||
vertex_source_length != key.vertex_source_length || fragment_source_hash_low != key.fragment_source_hash_low ||
fragment_source_hash_high != key.fragment_source_hash_high || fragment_source_length != key.fragment_source_length);
}
@@ -204,7 +197,6 @@ namespace GL
const CacheIndexKey key{
entry.vertex_source_hash_low, entry.vertex_source_hash_high, entry.vertex_source_length,
entry.geometry_source_hash_low, entry.geometry_source_hash_high, entry.geometry_source_length,
entry.fragment_source_hash_low, entry.fragment_source_hash_high, entry.fragment_source_length};
const CacheIndexData data{entry.file_offset, entry.blob_size, entry.blob_format};
m_index.emplace(key, data);
@@ -218,9 +210,17 @@ namespace GL
{
m_index.clear();
if (m_index_file)
{
std::fclose(m_index_file);
m_index_file = nullptr;
}
if (m_blob_file)
{
std::fclose(m_blob_file);
m_blob_file = nullptr;
}
m_base_path = {};
}
bool ShaderCache::Recreate()
@@ -234,7 +234,6 @@ namespace GL
}
ShaderCache::CacheIndexKey ShaderCache::GetCacheKey(const std::string_view& vertex_shader,
const std::string_view& geometry_shader,
const std::string_view& fragment_shader)
{
union ShaderHash
@@ -248,7 +247,6 @@ namespace GL
};
ShaderHash vertex_hash = {};
ShaderHash geometry_hash = {};
ShaderHash fragment_hash = {};
MD5Digest digest;
@@ -258,13 +256,6 @@ namespace GL
digest.Final(vertex_hash.bytes);
}
if (!geometry_shader.empty())
{
digest.Reset();
digest.Update(geometry_shader.data(), static_cast<u32>(geometry_shader.length()));
digest.Final(geometry_hash.bytes);
}
if (!fragment_shader.empty())
{
digest.Reset();
@@ -273,7 +264,6 @@ namespace GL
}
return CacheIndexKey{vertex_hash.low, vertex_hash.high, static_cast<u32>(vertex_shader.length()),
geometry_hash.low, geometry_hash.high, static_cast<u32>(geometry_shader.length()),
fragment_hash.low, fragment_hash.high, static_cast<u32>(fragment_shader.length())};
}
@@ -288,7 +278,6 @@ namespace GL
}
std::optional<Program> ShaderCache::GetProgram(const std::string_view vertex_shader,
const std::string_view geometry_shader,
const std::string_view fragment_shader, const PreLinkCallback& callback)
{
if (!m_program_binary_supported || !m_blob_file)
@@ -297,7 +286,7 @@ namespace GL
Common::Timer timer;
#endif
std::optional<Program> res = CompileProgram(vertex_shader, geometry_shader, fragment_shader, callback, false);
std::optional<Program> res = CompileProgram(vertex_shader, fragment_shader, callback, false);
#ifdef PCSX2_DEVBUILD
Console.WriteLn("Time to compile shader without caching: %.2fms", timer.GetTimeMilliseconds());
@@ -305,10 +294,10 @@ namespace GL
return res;
}
const auto key = GetCacheKey(vertex_shader, geometry_shader, fragment_shader);
const auto key = GetCacheKey(vertex_shader, fragment_shader);
auto iter = m_index.find(key);
if (iter == m_index.end())
return CompileAndAddProgram(key, vertex_shader, geometry_shader, fragment_shader, callback);
return CompileAndAddProgram(key, vertex_shader, fragment_shader, callback);
std::vector<u8> data(iter->second.blob_size);
if (std::fseek(m_blob_file, iter->second.file_offset, SEEK_SET) != 0 ||
@@ -335,16 +324,15 @@ namespace GL
Console.Warning(
"Failed to create program from binary, this may be due to a driver or GPU Change. Recreating cache.");
if (!Recreate())
return CompileProgram(vertex_shader, geometry_shader, fragment_shader, callback, false);
return CompileProgram(vertex_shader, fragment_shader, callback, false);
else
return CompileAndAddProgram(key, vertex_shader, geometry_shader, fragment_shader, callback);
return CompileAndAddProgram(key, vertex_shader, fragment_shader, callback);
}
bool ShaderCache::GetProgram(Program* out_program, const std::string_view vertex_shader,
const std::string_view geometry_shader, const std::string_view fragment_shader,
const PreLinkCallback& callback /* = */)
const std::string_view fragment_shader, const PreLinkCallback& callback /* = */)
{
auto prog = GetProgram(vertex_shader, geometry_shader, fragment_shader, callback);
auto prog = GetProgram(vertex_shader, fragment_shader, callback);
if (!prog)
return false;
@@ -366,9 +354,6 @@ namespace GL
entry.vertex_source_hash_low = key.vertex_source_hash_low;
entry.vertex_source_hash_high = key.vertex_source_hash_high;
entry.vertex_source_length = key.vertex_source_length;
entry.geometry_source_hash_low = key.geometry_source_hash_low;
entry.geometry_source_hash_high = key.geometry_source_hash_high;
entry.geometry_source_length = key.geometry_source_length;
entry.fragment_source_hash_low = key.fragment_source_hash_low;
entry.fragment_source_hash_high = key.fragment_source_hash_high;
entry.fragment_source_length = key.fragment_source_length;
@@ -389,12 +374,10 @@ namespace GL
}
std::optional<Program> ShaderCache::CompileProgram(const std::string_view& vertex_shader,
const std::string_view& geometry_shader,
const std::string_view& fragment_shader,
const PreLinkCallback& callback, bool set_retrievable)
const std::string_view& fragment_shader, const PreLinkCallback& callback, bool set_retrievable)
{
Program prog;
if (!prog.Compile(vertex_shader, geometry_shader, fragment_shader))
if (!prog.Compile(vertex_shader, fragment_shader))
return std::nullopt;
if (callback)
@@ -429,16 +412,14 @@ namespace GL
}
std::optional<Program> ShaderCache::CompileAndAddProgram(const CacheIndexKey& key,
const std::string_view& vertex_shader,
const std::string_view& geometry_shader,
const std::string_view& fragment_shader,
const std::string_view& vertex_shader, const std::string_view& fragment_shader,
const PreLinkCallback& callback)
{
#ifdef PCSX2_DEVBUILD
Common::Timer timer;
#endif
std::optional<Program> prog = CompileProgram(vertex_shader, geometry_shader, fragment_shader, callback, true);
std::optional<Program> prog = CompileProgram(vertex_shader, fragment_shader, callback, true);
if (!prog)
return std::nullopt;
@@ -483,7 +464,7 @@ namespace GL
return res;
}
const auto key = GetCacheKey(glsl, std::string_view(), std::string_view());
const auto key = GetCacheKey(glsl, std::string_view());
auto iter = m_index.find(key);
if (iter == m_index.end())
return CompileAndAddComputeProgram(key, glsl, callback);
+5 -13
View File
@@ -36,11 +36,10 @@ namespace GL
~ShaderCache();
bool Open(bool is_gles, std::string_view base_path, u32 version);
void Close();
std::optional<Program> GetProgram(const std::string_view vertex_shader, const std::string_view geometry_shader,
const std::string_view fragment_shader, const PreLinkCallback& callback = {});
bool GetProgram(Program* out_program, const std::string_view vertex_shader, const std::string_view geometry_shader,
const std::string_view fragment_shader, const PreLinkCallback& callback = {});
std::optional<Program> GetProgram(const std::string_view vertex_shader, const std::string_view fragment_shader, const PreLinkCallback& callback = {});
bool GetProgram(Program* out_program, const std::string_view vertex_shader, const std::string_view fragment_shader, const PreLinkCallback& callback = {});
std::optional<Program> GetComputeProgram(const std::string_view glsl, const PreLinkCallback& callback = {});
bool GetComputeProgram(Program* out_program, const std::string_view glsl, const PreLinkCallback& callback = {});
@@ -53,9 +52,6 @@ namespace GL
u64 vertex_source_hash_low;
u64 vertex_source_hash_high;
u32 vertex_source_length;
u64 geometry_source_hash_low;
u64 geometry_source_hash_high;
u32 geometry_source_length;
u64 fragment_source_hash_low;
u64 fragment_source_hash_high;
u32 fragment_source_length;
@@ -71,7 +67,6 @@ namespace GL
std::size_t h = 0;
HashCombine(h,
e.vertex_source_hash_low, e.vertex_source_hash_high, e.vertex_source_length,
e.geometry_source_hash_low, e.geometry_source_hash_high, e.geometry_source_length,
e.fragment_source_hash_low, e.fragment_source_hash_high, e.fragment_source_length);
return h;
}
@@ -86,24 +81,21 @@ namespace GL
using CacheIndex = std::unordered_map<CacheIndexKey, CacheIndexData, CacheIndexEntryHasher>;
static CacheIndexKey GetCacheKey(const std::string_view& vertex_shader, const std::string_view& geometry_shader,
const std::string_view& fragment_shader);
static CacheIndexKey GetCacheKey(const std::string_view& vertex_shader, const std::string_view& fragment_shader);
std::string GetIndexFileName() const;
std::string GetBlobFileName() const;
bool CreateNew(const std::string& index_filename, const std::string& blob_filename);
bool ReadExisting(const std::string& index_filename, const std::string& blob_filename);
void Close();
bool Recreate();
bool WriteToBlobFile(const CacheIndexKey& key, const std::vector<u8>& prog_data, u32 prog_format);
std::optional<Program> CompileProgram(const std::string_view& vertex_shader, const std::string_view& geometry_shader,
std::optional<Program> CompileProgram(const std::string_view& vertex_shader,
const std::string_view& fragment_shader, const PreLinkCallback& callback,
bool set_retrievable);
std::optional<Program> CompileAndAddProgram(const CacheIndexKey& key, const std::string_view& vertex_shader,
const std::string_view& geometry_shader,
const std::string_view& fragment_shader, const PreLinkCallback& callback);
std::optional<Program> CompileComputeProgram(const std::string_view& glsl, const PreLinkCallback& callback, bool set_retrievable);
+21 -10
View File
@@ -15,6 +15,7 @@
#include "StreamBuffer.h"
#include "common/Align.h"
#include "common/AlignedMalloc.h"
#include "common/Assertions.h"
#include <array>
#include <cstring>
@@ -49,11 +50,14 @@ namespace GL
class BufferSubDataStreamBuffer final : public StreamBuffer
{
public:
~BufferSubDataStreamBuffer() override = default;
~BufferSubDataStreamBuffer() override
{
_aligned_free(m_cpu_buffer);
}
MappingResult Map(u32 alignment, u32 min_size) override
{
return MappingResult{static_cast<void*>(m_cpu_buffer.data()), 0, 0, m_size / alignment};
return MappingResult{static_cast<void*>(m_cpu_buffer), 0, 0, m_size / alignment};
}
void Unmap(u32 used_size) override
@@ -62,7 +66,7 @@ namespace GL
return;
glBindBuffer(m_target, m_buffer_id);
glBufferSubData(m_target, 0, used_size, m_cpu_buffer.data());
glBufferSubData(m_target, 0, used_size, m_cpu_buffer);
}
u32 GetChunkSize() const override
@@ -93,22 +97,27 @@ namespace GL
private:
BufferSubDataStreamBuffer(GLenum target, GLuint buffer_id, u32 size)
: StreamBuffer(target, buffer_id, size)
, m_cpu_buffer(size)
{
m_cpu_buffer = static_cast<u8*>(_aligned_malloc(size, 32));
if (!m_cpu_buffer)
pxFailRel("Failed to allocate CPU storage for GL buffer");
}
std::vector<u8> m_cpu_buffer;
u8* m_cpu_buffer;
};
// Uses BufferData() to orphan the buffer after every update. Used on Mali where BufferSubData forces a sync.
class BufferDataStreamBuffer final : public StreamBuffer
{
public:
~BufferDataStreamBuffer() override = default;
~BufferDataStreamBuffer() override
{
_aligned_free(m_cpu_buffer);
}
MappingResult Map(u32 alignment, u32 min_size) override
{
return MappingResult{static_cast<void*>(m_cpu_buffer.data()), 0, 0, m_size / alignment};
return MappingResult{static_cast<void*>(m_cpu_buffer), 0, 0, m_size / alignment};
}
void Unmap(u32 used_size) override
@@ -117,7 +126,7 @@ namespace GL
return;
glBindBuffer(m_target, m_buffer_id);
glBufferData(m_target, used_size, m_cpu_buffer.data(), GL_STREAM_DRAW);
glBufferData(m_target, used_size, m_cpu_buffer, GL_STREAM_DRAW);
}
u32 GetChunkSize() const override
@@ -148,11 +157,13 @@ namespace GL
private:
BufferDataStreamBuffer(GLenum target, GLuint buffer_id, u32 size)
: StreamBuffer(target, buffer_id, size)
, m_cpu_buffer(size)
{
m_cpu_buffer = static_cast<u8*>(_aligned_malloc(size, 32));
if (!m_cpu_buffer)
pxFailRel("Failed to allocate CPU storage for GL buffer");
}
std::vector<u8> m_cpu_buffer;
u8* m_cpu_buffer;
};
// Base class for implementations which require syncing.
+6
View File
@@ -89,6 +89,7 @@ static void SysPageFaultSignalFilter(int signal, siginfo_t* siginfo, void* ctx)
// Prevent recursive exception filtering.
if (s_in_exception_handler)
{
lock.unlock();
CallExistingSignalHandler(signal, siginfo, ctx);
return;
}
@@ -121,6 +122,7 @@ static void SysPageFaultSignalFilter(int signal, siginfo_t* siginfo, void* ctx)
return;
// Call old signal handler, which will likely dump core.
lock.unlock();
CallExistingSignalHandler(signal, siginfo, ctx);
}
@@ -135,6 +137,10 @@ bool HostSys::InstallPageFaultHandler(PageFaultHandler handler)
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = SysPageFaultSignalFilter;
#ifdef __linux__
// Don't block the signal from executing recursively, we want to fire the original handler.
sa.sa_flags |= SA_NODEFER;
#endif
#ifdef __APPLE__
// MacOS uses SIGBUS for memory permission violations
if (sigaction(SIGBUS, &sa, &s_old_sigbus_action) != 0)
+173 -159
View File
@@ -15,197 +15,211 @@
#include "common/Perf.h"
#include "common/Pcsx2Defs.h"
#ifdef __unix__
#include <unistd.h>
#endif
#include "common/Assertions.h"
#include "common/StringUtil.h"
#ifdef ENABLE_VTUNE
#include "jitprofiling.h"
#endif
#include <string> // std::string
#include <cstring> // strncpy
#include <algorithm> // std::remove_if
#include <array>
#include <cstring>
#ifdef __linux__
#include <atomic>
#include <ctime>
#include <mutex>
#include <elf.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#endif
//#define ProfileWithPerf
#define MERGE_BLOCK_RESULT
//#define ProfileWithPerfJitDump
#ifdef ENABLE_VTUNE
#ifdef _WIN32
#if defined(ENABLE_VTUNE) && defined(_WIN32)
#pragma comment(lib, "jitprofiling.lib")
#endif
#endif
namespace Perf
{
// Warning object aren't thread safe
InfoVector any("");
InfoVector ee("EE");
InfoVector iop("IOP");
InfoVector vu("VU");
InfoVector vif("VIF");
Group any("");
Group ee("EE");
Group iop("IOP");
Group vu0("VU0");
Group vu1("VU1");
Group vif("VIF");
// Perf is only supported on linux
#if defined(__linux__) && (defined(ProfileWithPerf) || defined(ENABLE_VTUNE))
////////////////////////////////////////////////////////////////////////////////
// Implementation of the Info object
////////////////////////////////////////////////////////////////////////////////
Info::Info(uptr x86, u32 size, const char* symbol)
: m_x86(x86)
, m_size(size)
, m_dynamic(false)
#if defined(__linux__) && defined(ProfileWithPerf)
static std::FILE* s_map_file = nullptr;
static bool s_map_file_opened = false;
static std::mutex s_mutex;
static void RegisterMethod(const void* ptr, size_t size, const char* symbol)
{
strncpy(m_symbol, symbol, sizeof(m_symbol));
}
std::unique_lock lock(s_mutex);
Info::Info(uptr x86, u32 size, const char* symbol, u32 pc)
: m_x86(x86)
, m_size(size)
, m_dynamic(true)
{
snprintf(m_symbol, sizeof(m_symbol), "%s_0x%08x", symbol, pc);
}
void Info::Print(FILE* fp)
{
fprintf(fp, "%x %x %s\n", m_x86, m_size, m_symbol);
}
////////////////////////////////////////////////////////////////////////////////
// Implementation of the InfoVector object
////////////////////////////////////////////////////////////////////////////////
InfoVector::InfoVector(const char* prefix)
{
strncpy(m_prefix, prefix, sizeof(m_prefix));
#ifdef ENABLE_VTUNE
m_vtune_id = iJIT_GetNewMethodID();
#else
m_vtune_id = 0;
#endif
}
void InfoVector::print(FILE* fp)
{
for (auto&& it : m_v)
it.Print(fp);
}
void InfoVector::map(uptr x86, u32 size, const char* symbol)
{
// This function is typically used for dispatcher and recompiler.
// Dispatchers are on a page and must always be kept.
// Recompilers are much bigger (TODO check VIF) and are only
// useful when MERGE_BLOCK_RESULT is defined
#if defined(ENABLE_VTUNE) || !defined(MERGE_BLOCK_RESULT)
u32 max_code_size = 16 * _1kb;
#else
u32 max_code_size = _1gb;
#endif
if (size < max_code_size)
if (!s_map_file)
{
m_v.emplace_back(x86, size, symbol);
if (s_map_file_opened)
return;
#ifdef ENABLE_VTUNE
std::string name = std::string(symbol);
iJIT_Method_Load ml;
memset(&ml, 0, sizeof(ml));
ml.method_id = iJIT_GetNewMethodID();
ml.method_name = (char*)name.c_str();
ml.method_load_address = (void*)x86;
ml.method_size = size;
iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &ml);
//fprintf(stderr, "mapF %s: %p size %dKB\n", ml.method_name, ml.method_load_address, ml.method_size / 1024u);
#endif
char file[256];
snprintf(file, std::size(file), "/tmp/perf-%d.map", getpid());
s_map_file = std::fopen(file, "wb");
s_map_file_opened = true;
if (!s_map_file)
return;
}
std::fprintf(s_map_file, "%" PRIx64 " %zx %s\n", static_cast<u64>(reinterpret_cast<uintptr_t>(ptr)), size, symbol);
std::fflush(s_map_file);
}
#elif defined(__linux__) && defined(ProfileWithPerfJitDump)
enum : u32
{
JIT_CODE_LOAD = 0,
JIT_CODE_MOVE = 1,
JIT_CODE_DEBUG_INFO = 2,
JIT_CODE_CLOSE = 3,
JIT_CODE_UNWINDING_INFO = 4
};
#pragma pack(push, 1)
struct JITDUMP_HEADER
{
u32 magic = 0x4A695444; // JiTD
u32 version = 1;
u32 header_size = sizeof(JITDUMP_HEADER);
u32 elf_mach;
u32 pad1 = 0;
u32 pid;
u64 timestamp;
u64 flags = 0;
};
struct JITDUMP_RECORD_HEADER
{
u32 id;
u32 total_size;
u64 timestamp;
};
struct JITDUMP_CODE_LOAD
{
JITDUMP_RECORD_HEADER header;
u32 pid;
u32 tid;
u64 vma;
u64 code_addr;
u64 code_size;
u64 code_index;
// name
};
#pragma pack(pop)
static u64 JitDumpTimestamp()
{
struct timespec ts = {};
clock_gettime(CLOCK_MONOTONIC, &ts);
return (static_cast<u64>(ts.tv_sec) * 1000000000ULL) + static_cast<u64>(ts.tv_nsec);
}
void InfoVector::map(uptr x86, u32 size, u32 pc)
static FILE* s_jitdump_file = nullptr;
static bool s_jitdump_file_opened = false;
static std::mutex s_jitdump_mutex;
static u32 s_jitdump_record_id;
static void RegisterMethod(const void* ptr, size_t size, const char* symbol)
{
#ifndef MERGE_BLOCK_RESULT
m_v.emplace_back(x86, size, m_prefix, pc);
#endif
const u32 namelen = std::strlen(symbol) + 1;
#ifdef ENABLE_VTUNE
iJIT_Method_Load_V2 ml;
std::unique_lock lock(s_jitdump_mutex);
if (!s_jitdump_file)
{
if (!s_jitdump_file_opened)
{
char file[256];
snprintf(file, std::size(file), "jit-%d.dump", getpid());
s_jitdump_file = fopen(file, "w+b");
s_jitdump_file_opened = true;
if (!s_jitdump_file)
return;
}
memset(&ml, 0, sizeof(ml));
void* perf_marker = mmap(nullptr, 4096, PROT_READ | PROT_EXEC, MAP_PRIVATE, fileno(s_jitdump_file), 0);
pxAssertRel(perf_marker != MAP_FAILED, "Map perf marker");
#ifdef MERGE_BLOCK_RESULT
ml.method_id = m_vtune_id;
ml.method_name = m_prefix;
#else
std::string name = std::string(m_prefix) + "_" + std::to_string(pc);
JITDUMP_HEADER jh = {};
jh.elf_mach = EM_X86_64;
jh.pid = getpid();
jh.timestamp = JitDumpTimestamp();
std::fwrite(&jh, sizeof(jh), 1, s_jitdump_file);
}
JITDUMP_CODE_LOAD cl = {};
cl.header.id = JIT_CODE_LOAD;
cl.header.total_size = sizeof(cl) + namelen + static_cast<u32>(size);
cl.header.timestamp = JitDumpTimestamp();
cl.pid = getpid();
cl.tid = syscall(SYS_gettid);
cl.vma = 0;
cl.code_addr = static_cast<u64>(reinterpret_cast<uintptr_t>(ptr));
cl.code_size = static_cast<u64>(size);
cl.code_index = s_jitdump_record_id++;
std::fwrite(&cl, sizeof(cl), 1, s_jitdump_file);
std::fwrite(symbol, namelen, 1, s_jitdump_file);
std::fwrite(ptr, size, 1, s_jitdump_file);
std::fflush(s_jitdump_file);
}
#elif defined(ENABLE_VTUNE)
static void RegisterMethod(const void* ptr, size_t size, const char* symbol)
{
iJIT_Method_Load_V2 ml = {};
ml.method_id = iJIT_GetNewMethodID();
ml.method_name = (char*)name.c_str();
#endif
ml.method_load_address = (void*)x86;
ml.method_size = size;
ml.method_name = const_cast<char*>(symbol);
ml.method_load_address = ptr;
ml.method_size = static_cast<unsigned int>(size);
iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED_V2, &ml);
//fprintf(stderr, "mapB %s: %p size %d\n", ml.method_name, ml.method_load_address, ml.method_size);
#endif
}
void InfoVector::reset()
{
auto dynamic = std::remove_if(m_v.begin(), m_v.end(), [](Info i) { return i.m_dynamic; });
m_v.erase(dynamic, m_v.end());
}
////////////////////////////////////////////////////////////////////////////////
// Global function
////////////////////////////////////////////////////////////////////////////////
void dump()
{
char file[256];
snprintf(file, 250, "/tmp/perf-%d.map", getpid());
FILE* fp = fopen(file, "w");
any.print(fp);
ee.print(fp);
iop.print(fp);
vu.print(fp);
if (fp)
fclose(fp);
}
void dump_and_reset()
{
dump();
any.reset();
ee.reset();
iop.reset();
vu.reset();
}
#else
////////////////////////////////////////////////////////////////////////////////
// Dummy implementation
////////////////////////////////////////////////////////////////////////////////
InfoVector::InfoVector(const char* prefix)
: m_vtune_id(0)
static void RegisterMethod(const void* ptr, size_t size, const char* method)
{
}
void InfoVector::map(uptr x86, u32 size, const char* symbol) {}
void InfoVector::map(uptr x86, u32 size, u32 pc) {}
void InfoVector::reset() {}
#endif
void dump() {}
void dump_and_reset() {}
#if (defined(__linux__) && (defined(ProfileWithPerf) || defined(ProfileWithPerfJitDump))) || defined(ENABLE_VTUNE)
void Group::Register(const void* ptr, size_t size, const char* symbol)
{
char full_symbol[128];
if (HasPrefix())
std::snprintf(full_symbol, std::size(full_symbol), "%s_%s", m_prefix, symbol);
else
StringUtil::Strlcpy(full_symbol, symbol, std::size(full_symbol));
RegisterMethod(ptr, size, full_symbol);
}
void Group::RegisterPC(const void* ptr, size_t size, u32 pc)
{
char full_symbol[128];
if (HasPrefix())
std::snprintf(full_symbol, std::size(full_symbol), "%s_%08X", m_prefix, pc);
else
std::snprintf(full_symbol, std::size(full_symbol), "%08X", pc);
RegisterMethod(ptr, size, full_symbol);
}
void Group::RegisterKey(const void* ptr, size_t size, const char* prefix, u64 key)
{
char full_symbol[128];
if (HasPrefix())
std::snprintf(full_symbol, std::size(full_symbol), "%s_%s%016" PRIX64, m_prefix, prefix, key);
else
std::snprintf(full_symbol, std::size(full_symbol), "%s%016" PRIX64, prefix, key);
RegisterMethod(ptr, size, full_symbol);
}
#else
void Group::Register(const void* ptr, size_t size, const char* symbol) {}
void Group::RegisterPC(const void* ptr, size_t size, u32 pc) {}
void Group::RegisterKey(const void* ptr, size_t size, const char* prefix, u64 key) {}
#endif
} // namespace Perf
+13 -32
View File
@@ -21,42 +21,23 @@
namespace Perf
{
struct Info
class Group
{
uptr m_x86;
u32 m_size;
char m_symbol[20];
// The idea is to keep static zones that are set only
// once.
bool m_dynamic;
Info(uptr x86, u32 size, const char* symbol);
Info(uptr x86, u32 size, const char* symbol, u32 pc);
void Print(FILE* fp);
};
class InfoVector
{
std::vector<Info> m_v;
char m_prefix[20];
unsigned int m_vtune_id;
const char* m_prefix;
public:
InfoVector(const char* prefix);
constexpr Group(const char* prefix) : m_prefix(prefix) {}
bool HasPrefix() const { return (m_prefix && m_prefix[0]); }
void print(FILE* fp);
void map(uptr x86, u32 size, const char* symbol);
void map(uptr x86, u32 size, u32 pc);
void reset();
void Register(const void* ptr, size_t size, const char* symbol);
void RegisterPC(const void* ptr, size_t size, u32 pc);
void RegisterKey(const void* ptr, size_t size, const char* prefix, u64 key);
};
void dump();
void dump_and_reset();
extern InfoVector any;
extern InfoVector ee;
extern InfoVector iop;
extern InfoVector vu;
extern InfoVector vif;
extern Group any;
extern Group ee;
extern Group iop;
extern Group vu0;
extern Group vu1;
extern Group vif;
} // namespace Perf
-111
View File
@@ -97,114 +97,3 @@ public:
virtual SafeArray<T>* Clone() const;
};
//////////////////////////////////////////////////////////////////////////////////////////
// SafeList - Simple growable container without all the mess or hassle of std containers.
//
// This container is intended for reasonably simple class types only. Things which this
// container does not handle with desired robustness:
//
// * Classes with non-trivial constructors (such that construction creates much overhead)
// * Classes with copy constructors (copying is done using performance memcpy)
// * Classes with destructors (they're not called, sorry!)
//
template <typename T>
class SafeList
{
DeclareNoncopyableObject(SafeList);
public:
static const int DefaultChunkSize = 0x80 * sizeof(T);
public:
std::string Name; // user-assigned block name
int ChunkSize; // assigned DefaultChunkSize on init, reconfigurable at any time.
protected:
T* m_ptr;
int m_allocsize; // size of the allocation of memory
uint m_length; // length of the array (active items, not buffer allocation)
protected:
virtual T* _virtual_realloc(int newsize);
void _MakeRoomFor_threshold(int newsize);
T* _getPtr(uint i) const;
public:
virtual ~SafeList();
explicit SafeList(const char* name = "Unnamed");
explicit SafeList(int initialSize, const char* name = "Unnamed");
virtual SafeList<T>* Clone() const;
void Remove(int index);
void MakeRoomFor(int blockSize);
T& New();
int Add(const T& src);
T& AddNew(const T& src);
// Returns the size of the list, as according to the array type. This includes
// mapped items only. The actual size of the allocation may differ.
int GetLength() const { return m_length; }
// Returns the size of the list, in bytes. This includes mapped items only.
// The actual size of the allocation may differ.
int GetSizeInBytes() const { return m_length * sizeof(T); }
void MatchLengthToAllocatedSize()
{
m_length = m_allocsize;
}
void GrowBy(int items)
{
MakeRoomFor(m_length + ChunkSize + items + 1);
}
// Sets the item length to zero. Does not free memory allocations.
void Clear()
{
m_length = 0;
}
// Gets an element of this memory allocation much as if it were an array.
// DevBuilds : Generates assertion if the index is invalid.
T& operator[](int idx) { return *_getPtr((uint)idx); }
const T& operator[](int idx) const { return *_getPtr((uint)idx); }
T* GetPtr() { return m_ptr; }
const T* GetPtr() const { return m_ptr; }
T& GetLast() { return m_ptr[m_length - 1]; }
const T& GetLast() const { return m_ptr[m_length - 1]; }
};
// --------------------------------------------------------------------------------------
// SafeAlignedArray<T>
// --------------------------------------------------------------------------------------
// Handy little class for allocating a resizable memory block, complete with
// exception-based error handling and automatic cleanup.
// This one supports aligned data allocations too!
template <typename T, uint Alignment>
class SafeAlignedArray : public SafeArray<T>
{
typedef SafeArray<T> _parent;
protected:
T* _virtual_realloc(int newsize);
public:
using _parent::operator[];
virtual ~SafeAlignedArray();
explicit SafeAlignedArray(std::string name = "Unnamed")
: SafeArray<T>::SafeArray(name)
{
}
explicit SafeAlignedArray(int initialSize, std::string name = "Unnamed");
virtual SafeAlignedArray<T, Alignment>* Clone() const;
};
-166
View File
@@ -15,13 +15,9 @@
#pragma once
#include "common/AlignedMalloc.h"
#include "common/Assertions.h"
#include "common/Exceptions.h"
#include "common/SafeArray.h"
#include "fmt/core.h"
// Internal constructor for use by derived classes. This allows a derived class to
// use its own memory allocation (with an aligned memory, for example).
// Throws:
@@ -123,165 +119,3 @@ SafeArray<T>* SafeArray<T>::Clone() const
memcpy(retval->GetPtr(), m_ptr, sizeof(T) * m_size);
return retval;
}
// --------------------------------------------------------------------------------------
// SafeAlignedArray<T> (implementations)
// --------------------------------------------------------------------------------------
template <typename T, uint Alignment>
T* SafeAlignedArray<T, Alignment>::_virtual_realloc(int newsize)
{
return (T*)((this->m_ptr == NULL) ?
_aligned_malloc(newsize * sizeof(T), Alignment) :
pcsx2_aligned_realloc(this->m_ptr, newsize * sizeof(T), Alignment, this->m_size * sizeof(T)));
}
// Appends "(align: xx)" to the name of the allocation in devel builds.
// Maybe useful,maybe not... no harm in attaching it. :D
template <typename T, uint Alignment>
SafeAlignedArray<T, Alignment>::~SafeAlignedArray()
{
safe_aligned_free(this->m_ptr);
// mptr is set to null, so the parent class's destructor won't re-free it.
}
template <typename T, uint Alignment>
SafeAlignedArray<T, Alignment>::SafeAlignedArray(int initialSize, std::string name)
: SafeArray<T>::SafeArray(
std::move(name),
(T*)_aligned_malloc(initialSize * sizeof(T), Alignment),
initialSize)
{
}
template <typename T, uint Alignment>
SafeAlignedArray<T, Alignment>* SafeAlignedArray<T, Alignment>::Clone() const
{
SafeAlignedArray<T, Alignment>* retval = new SafeAlignedArray<T, Alignment>(this->m_size);
memcpy(retval->GetPtr(), this->m_ptr, sizeof(T) * this->m_size);
return retval;
}
// --------------------------------------------------------------------------------------
// SafeList<T> (implementations)
// --------------------------------------------------------------------------------------
template <typename T>
T* SafeList<T>::_virtual_realloc(int newsize)
{
return (T*)realloc(m_ptr, newsize * sizeof(T));
}
template <typename T>
SafeList<T>::~SafeList()
{
safe_free(m_ptr);
}
template <typename T>
SafeList<T>::SafeList(const char* name)
: Name(name)
{
ChunkSize = DefaultChunkSize;
m_ptr = NULL;
m_allocsize = 0;
m_length = 0;
}
template <typename T>
SafeList<T>::SafeList(int initialSize, const char* name)
: Name(name)
{
ChunkSize = DefaultChunkSize;
m_allocsize = initialSize;
m_length = 0;
m_ptr = (T*)malloc(initialSize * sizeof(T));
if (m_ptr == NULL)
pxFailRel("SafeList exact alloc failed");
for (int i = 0; i < m_allocsize; ++i)
{
new (&m_ptr[i]) T();
}
}
template <typename T>
T* SafeList<T>::_getPtr(uint i) const
{
pxAssumeDev(i < m_length, "Index in bounds");
return &m_ptr[i];
}
// Ensures that the allocation is large enough to fit data of the
// amount requested. The memory allocation is not resized smaller.
template <typename T>
void SafeList<T>::MakeRoomFor(int blockSize)
{
if (blockSize > m_allocsize)
{
const int newalloc = blockSize + ChunkSize;
m_ptr = _virtual_realloc(newalloc);
if (m_ptr == NULL)
pxFailRel("SafeList MakeRoomFor failed");
for (; m_allocsize < newalloc; ++m_allocsize)
{
new (&m_ptr[m_allocsize]) T();
}
}
}
// Appends an item to the end of the list and returns a handle to it.
template <typename T>
T& SafeList<T>::New()
{
_MakeRoomFor_threshold(m_length + 1);
return m_ptr[m_length++];
}
template <typename T>
int SafeList<T>::Add(const T& src)
{
_MakeRoomFor_threshold(m_length + 1);
m_ptr[m_length] = src;
return m_length++;
}
// Same as Add, but returns the handle of the new object instead of it's array index.
template <typename T>
T& SafeList<T>::AddNew(const T& src)
{
_MakeRoomFor_threshold(m_length + 1);
m_ptr[m_length] = src;
return m_ptr[m_length];
}
// Performs a standard array-copy removal of the given item. All items past the
// given item are copied over.
// DevBuilds : Generates assertion if the index is invalid.
template <typename T>
void SafeList<T>::Remove(int index)
{
pxAssert(index < m_length);
int copylen = m_length - index;
if (copylen > 0)
memcpy(&m_ptr[index], &m_ptr[index + 1], copylen);
}
template <typename T>
SafeList<T>* SafeList<T>::Clone() const
{
SafeList<T>* retval = new SafeList<T>(m_length);
memcpy(retval->m_ptr, m_ptr, sizeof(T) * m_length);
return retval;
}
template <typename T>
void SafeList<T>::_MakeRoomFor_threshold(int newsize)
{
MakeRoomFor(newsize + ChunkSize);
}
-6
View File
@@ -698,11 +698,6 @@ namespace Vulkan
{
pxAssert(m_num_writes < MAX_WRITES && (m_num_image_infos + num_views) < MAX_IMAGE_INFOS);
#if 1
// NOTE: This is deliberately split up - updating multiple descriptors in one write is broken on Adreno.
for (u32 i = 0; i < num_views; i++)
AddCombinedImageSamplerDescriptorWrite(set, binding + i, views[i], samplers[i], layout);
#else
VkWriteDescriptorSet& dw = m_writes[m_num_writes++];
dw.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
dw.dstSet = set;
@@ -718,7 +713,6 @@ namespace Vulkan
ii.sampler = samplers[i];
ii.imageLayout = layout;
}
#endif
}
void DescriptorSetUpdateBuilder::AddBufferDescriptorWrite(
+117 -163
View File
@@ -26,6 +26,8 @@
#include <array>
#include <cstring>
#include "fmt/format.h"
#ifdef _WIN32
#include "common/RedtapeWindows.h"
#else
@@ -70,8 +72,7 @@ namespace Vulkan
Context::~Context() = default;
VkInstance Context::CreateVulkanInstance(
const WindowInfo* wi, bool enable_debug_utils, bool enable_validation_layer)
VkInstance Context::CreateVulkanInstance(const WindowInfo& wi, bool enable_debug_utils, bool enable_validation_layer)
{
ExtensionList enabled_extensions;
if (!SelectInstanceExtensions(&enabled_extensions, wi, enable_debug_utils))
@@ -118,7 +119,7 @@ namespace Vulkan
return instance;
}
bool Context::SelectInstanceExtensions(ExtensionList* extension_list, const WindowInfo* wi, bool enable_debug_utils)
bool Context::SelectInstanceExtensions(ExtensionList* extension_list, const WindowInfo& wi, bool enable_debug_utils)
{
u32 extension_count = 0;
VkResult res = vkEnumerateInstanceExtensionProperties(nullptr, &extension_count, nullptr);
@@ -155,34 +156,32 @@ namespace Vulkan
};
// Common extensions
if (wi && wi->type != WindowInfo::Type::Surfaceless && !SupportsExtension(VK_KHR_SURFACE_EXTENSION_NAME, true))
if (wi.type != WindowInfo::Type::Surfaceless && !SupportsExtension(VK_KHR_SURFACE_EXTENSION_NAME, true))
return false;
#if defined(VK_USE_PLATFORM_WIN32_KHR)
if (wi && wi->type == WindowInfo::Type::Win32 && !SupportsExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, true))
if (wi.type == WindowInfo::Type::Win32 && !SupportsExtension(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, true))
return false;
#endif
#if defined(VK_USE_PLATFORM_XLIB_KHR)
if (wi && wi->type == WindowInfo::Type::X11 && !SupportsExtension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME, true))
if (wi.type == WindowInfo::Type::X11 && !SupportsExtension(VK_KHR_XLIB_SURFACE_EXTENSION_NAME, true))
return false;
#endif
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
if (wi && wi->type == WindowInfo::Type::Wayland &&
!SupportsExtension(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, true))
if (wi.type == WindowInfo::Type::Wayland && !SupportsExtension(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, true))
return false;
#endif
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
if (wi && wi->type == WindowInfo::Type::Android &&
!SupportsExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, true))
if (wi.type == WindowInfo::Type::Android && !SupportsExtension(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, true))
return false;
#endif
#if defined(VK_USE_PLATFORM_METAL_EXT)
if (wi && wi->type == WindowInfo::Type::MacOS && !SupportsExtension(VK_EXT_METAL_SURFACE_EXTENSION_NAME, true))
if (wi.type == WindowInfo::Type::MacOS && !SupportsExtension(VK_EXT_METAL_SURFACE_EXTENSION_NAME, true))
return false;
#endif
#if 0
if (wi && wi->type == WindowInfo::Type::Display && !SupportsExtension(VK_KHR_DISPLAY_EXTENSION_NAME, true))
if (wi.type == WindowInfo::Type::Display && !SupportsExtension(VK_KHR_DISPLAY_EXTENSION_NAME, true))
return false;
#endif
@@ -195,162 +194,67 @@ namespace Vulkan
Context::GPUList Context::EnumerateGPUs(VkInstance instance)
{
GPUList gpus;
u32 gpu_count = 0;
VkResult res = vkEnumeratePhysicalDevices(instance, &gpu_count, nullptr);
if (res != VK_SUCCESS || gpu_count == 0)
if ((res != VK_SUCCESS && res != VK_INCOMPLETE) || gpu_count == 0)
{
LOG_VULKAN_ERROR(res, "vkEnumeratePhysicalDevices failed: ");
return {};
LOG_VULKAN_ERROR(res, "vkEnumeratePhysicalDevices (1) failed: ");
return gpus;
}
GPUList gpus;
gpus.resize(gpu_count);
res = vkEnumeratePhysicalDevices(instance, &gpu_count, gpus.data());
if (res != VK_SUCCESS)
std::vector<VkPhysicalDevice> physical_devices(gpu_count);
res = vkEnumeratePhysicalDevices(instance, &gpu_count, physical_devices.data());
if (res == VK_INCOMPLETE)
{
LOG_VULKAN_ERROR(res, "vkEnumeratePhysicalDevices failed: ");
return {};
Console.Warning("First vkEnumeratePhysicalDevices() call returned %zu devices, but second returned %u",
physical_devices.size(), gpu_count);
}
else if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkEnumeratePhysicalDevices (2) failed: ");
return gpus;
}
return gpus;
}
// Maybe we lost a GPU?
if (gpu_count < physical_devices.size())
physical_devices.resize(gpu_count);
Context::GPUNameList Context::EnumerateGPUNames(VkInstance instance)
{
u32 gpu_count = 0;
VkResult res = vkEnumeratePhysicalDevices(instance, &gpu_count, nullptr);
if (res != VK_SUCCESS || gpu_count == 0)
{
LOG_VULKAN_ERROR(res, "vkEnumeratePhysicalDevices failed: ");
return {};
}
GPUList gpus;
gpus.resize(gpu_count);
res = vkEnumeratePhysicalDevices(instance, &gpu_count, gpus.data());
if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkEnumeratePhysicalDevices failed: ");
return {};
}
GPUNameList gpu_names;
gpu_names.reserve(gpu_count);
for (u32 i = 0; i < gpu_count; i++)
gpus.reserve(physical_devices.size());
for (VkPhysicalDevice device : physical_devices)
{
VkPhysicalDeviceProperties props = {};
vkGetPhysicalDeviceProperties(gpus[i], &props);
vkGetPhysicalDeviceProperties(device, &props);
std::string gpu_name(props.deviceName);
std::string gpu_name = props.deviceName;
// handle duplicate adapter names
if (std::any_of(gpu_names.begin(), gpu_names.end(),
[&gpu_name](const std::string& other) { return (gpu_name == other); }))
if (std::any_of(gpus.begin(), gpus.end(),
[&gpu_name](const auto& other) { return (gpu_name == other.second); }))
{
std::string original_adapter_name = std::move(gpu_name);
u32 current_extra = 2;
do
{
gpu_name = StringUtil::StdStringFromFormat("%s (%u)", original_adapter_name.c_str(), current_extra);
gpu_name = fmt::format("{} ({})", original_adapter_name, current_extra);
current_extra++;
} while (std::any_of(gpu_names.begin(), gpu_names.end(),
[&gpu_name](const std::string& other) { return (gpu_name == other); }));
} while (std::any_of(gpus.begin(), gpus.end(),
[&gpu_name](const auto& other) { return (gpu_name == other.second); }));
}
gpu_names.push_back(std::move(gpu_name));
gpus.emplace_back(device, std::move(gpu_name));
}
return gpu_names;
return gpus;
}
bool Context::Create(std::string_view gpu_name, const WindowInfo* wi, std::unique_ptr<SwapChain>* out_swap_chain,
VkPresentModeKHR preferred_present_mode, bool threaded_presentation, bool enable_debug_utils,
bool enable_validation_layer)
bool Context::Create(VkInstance instance, VkSurfaceKHR surface, VkPhysicalDevice physical_device,
bool threaded_presentation, bool enable_debug_utils, bool enable_validation_layer)
{
pxAssertMsg(!g_vulkan_context, "Has no current context");
if (!Vulkan::LoadVulkanLibrary())
{
Console.Error("Failed to load Vulkan library");
return false;
}
const bool enable_surface = (wi && wi->type != WindowInfo::Type::Surfaceless);
VkInstance instance = CreateVulkanInstance(wi, enable_debug_utils, enable_validation_layer);
if (instance == VK_NULL_HANDLE)
{
if (enable_debug_utils || enable_validation_layer)
{
// Try again without the validation layer.
enable_debug_utils = false;
enable_validation_layer = false;
instance = CreateVulkanInstance(wi, enable_debug_utils, enable_validation_layer);
if (instance == VK_NULL_HANDLE)
{
Vulkan::UnloadVulkanLibrary();
return false;
}
Console.Error("Vulkan validation/debug layers requested but are unavailable. Creating non-debug device.");
}
}
if (!Vulkan::LoadVulkanInstanceFunctions(instance))
{
Console.Error("Failed to load Vulkan instance functions");
vkDestroyInstance(instance, nullptr);
Vulkan::UnloadVulkanLibrary();
return false;
}
GPUList gpus = EnumerateGPUs(instance);
if (gpus.empty())
{
vkDestroyInstance(instance, nullptr);
Vulkan::UnloadVulkanLibrary();
return false;
}
u32 gpu_index = 0;
GPUNameList gpu_names = EnumerateGPUNames(instance);
if (!gpu_name.empty())
{
for (; gpu_index < static_cast<u32>(gpu_names.size()); gpu_index++)
{
Console.WriteLn("GPU %u: %s", static_cast<u32>(gpu_index), gpu_names[gpu_index].c_str());
if (gpu_names[gpu_index] == gpu_name)
break;
}
if (gpu_index == static_cast<u32>(gpu_names.size()))
{
Console.Warning("Requested GPU '%s' not found, using first (%s)", std::string(gpu_name).c_str(),
gpu_names[0].c_str());
gpu_index = 0;
}
}
else
{
Console.WriteLn("No GPU requested, using first (%s)", gpu_names[0].c_str());
}
VkSurfaceKHR surface = VK_NULL_HANDLE;
WindowInfo wi_copy;
if (wi)
wi_copy = *wi;
if (enable_surface &&
(surface = SwapChain::CreateVulkanSurface(instance, gpus[gpu_index], &wi_copy)) == VK_NULL_HANDLE)
{
vkDestroyInstance(instance, nullptr);
Vulkan::UnloadVulkanLibrary();
return false;
}
g_vulkan_context.reset(new Context(instance, gpus[gpu_index]));
g_vulkan_context.reset(new Context(instance, physical_device));
if (enable_debug_utils)
g_vulkan_context->EnableDebugUtils();
@@ -359,8 +263,7 @@ namespace Vulkan
if (!g_vulkan_context->CreateDevice(surface, enable_validation_layer, nullptr, 0, nullptr, 0, nullptr) ||
!g_vulkan_context->CreateAllocator() || !g_vulkan_context->CreateGlobalDescriptorPool() ||
!g_vulkan_context->CreateCommandBuffers() || !g_vulkan_context->CreateTextureStreamBuffer() ||
!g_vulkan_context->InitSpinResources() ||
(enable_surface && (*out_swap_chain = SwapChain::Create(wi_copy, surface, preferred_present_mode)) == nullptr))
!g_vulkan_context->InitSpinResources())
{
// Since we are destroying the instance, we're also responsible for destroying the surface.
if (surface != VK_NULL_HANDLE)
@@ -460,12 +363,15 @@ namespace Vulkan
SupportsExtension(VK_EXT_CALIBRATED_TIMESTAMPS_EXTENSION_NAME, false);
m_optional_extensions.vk_ext_line_rasterization =
SupportsExtension(VK_EXT_LINE_RASTERIZATION_EXTENSION_NAME, false);
m_optional_extensions.vk_ext_rasterization_order_attachment_access =
SupportsExtension(VK_EXT_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME, false) ||
SupportsExtension(VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME, false);
m_optional_extensions.vk_khr_driver_properties =
SupportsExtension(VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME, false);
m_optional_extensions.vk_arm_rasterization_order_attachment_access =
SupportsExtension(VK_ARM_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_EXTENSION_NAME, false);
m_optional_extensions.vk_khr_fragment_shader_barycentric =
SupportsExtension(VK_KHR_FRAGMENT_SHADER_BARYCENTRIC_EXTENSION_NAME, false);
m_optional_extensions.vk_khr_shader_draw_parameters =
SupportsExtension(VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, false);
return true;
}
@@ -480,7 +386,6 @@ namespace Vulkan
// Enable the features we use.
m_device_features.dualSrcBlend = available_features.dualSrcBlend;
m_device_features.geometryShader = available_features.geometryShader;
m_device_features.largePoints = available_features.largePoints;
m_device_features.wideLines = available_features.wideLines;
m_device_features.fragmentStoresAndAtomics = available_features.fragmentStoresAndAtomics;
@@ -654,8 +559,8 @@ namespace Vulkan
// provoking vertex
VkPhysicalDeviceProvokingVertexFeaturesEXT provoking_vertex_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT};
VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM rasterization_order_access_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM};
VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT rasterization_order_access_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT};
VkPhysicalDeviceLineRasterizationFeaturesEXT line_rasterization_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT};
@@ -669,7 +574,7 @@ namespace Vulkan
line_rasterization_feature.bresenhamLines = VK_TRUE;
Util::AddPointerToChain(&device_info, &line_rasterization_feature);
}
if (m_optional_extensions.vk_arm_rasterization_order_attachment_access)
if (m_optional_extensions.vk_ext_rasterization_order_attachment_access)
{
rasterization_order_access_feature.rasterizationOrderColorAttachmentAccess = VK_TRUE;
Util::AddPointerToChain(&device_info, &rasterization_order_access_feature);
@@ -735,15 +640,15 @@ namespace Vulkan
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT};
VkPhysicalDeviceLineRasterizationFeaturesEXT line_rasterization_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT};
VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesARM rasterization_order_access_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_ARM};
VkPhysicalDeviceRasterizationOrderAttachmentAccessFeaturesEXT rasterization_order_access_feature = {
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RASTERIZATION_ORDER_ATTACHMENT_ACCESS_FEATURES_EXT};
// add in optional feature structs
if (m_optional_extensions.vk_ext_provoking_vertex)
Util::AddPointerToChain(&features2, &provoking_vertex_features);
if (m_optional_extensions.vk_ext_line_rasterization)
Util::AddPointerToChain(&features2, &line_rasterization_feature);
if (m_optional_extensions.vk_arm_rasterization_order_attachment_access)
if (m_optional_extensions.vk_ext_rasterization_order_attachment_access)
Util::AddPointerToChain(&features2, &rasterization_order_access_feature);
// query
@@ -751,7 +656,7 @@ namespace Vulkan
// confirm we actually support it
m_optional_extensions.vk_ext_provoking_vertex &= (provoking_vertex_features.provokingVertexLast == VK_TRUE);
m_optional_extensions.vk_arm_rasterization_order_attachment_access &= (rasterization_order_access_feature.rasterizationOrderColorAttachmentAccess == VK_TRUE);
m_optional_extensions.vk_ext_rasterization_order_attachment_access &= (rasterization_order_access_feature.rasterizationOrderColorAttachmentAccess == VK_TRUE);
m_optional_extensions.vk_ext_line_rasterization &= (line_rasterization_feature.bresenhamLines == VK_TRUE);
VkPhysicalDeviceProperties2 properties2 = {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
@@ -807,8 +712,8 @@ namespace Vulkan
m_optional_extensions.vk_ext_line_rasterization ? "supported" : "NOT supported");
Console.WriteLn("VK_EXT_calibrated_timestamps is %s",
m_optional_extensions.vk_ext_calibrated_timestamps ? "supported" : "NOT supported");
Console.WriteLn("VK_ARM_rasterization_order_attachment_access is %s",
m_optional_extensions.vk_arm_rasterization_order_attachment_access ? "supported" : "NOT supported");
Console.WriteLn("VK_EXT_rasterization_order_attachment_access is %s",
m_optional_extensions.vk_ext_rasterization_order_attachment_access ? "supported" : "NOT supported");
}
bool Context::CreateAllocator()
@@ -948,11 +853,9 @@ namespace Vulkan
bool Context::CreateGlobalDescriptorPool()
{
// TODO: A better way to choose the number of descriptors.
VkDescriptorPoolSize pool_sizes[] = {
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1024},
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1024},
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1},
static constexpr const VkDescriptorPoolSize pool_sizes[] = {
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 2},
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2},
};
VkDescriptorPoolCreateInfo pool_create_info = {VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, nullptr,
@@ -1658,7 +1561,7 @@ namespace Vulkan
input_reference.layout = VK_IMAGE_LAYOUT_GENERAL;
input_reference_ptr = &input_reference;
if (!g_vulkan_context->GetOptionalExtensions().vk_arm_rasterization_order_attachment_access)
if (!g_vulkan_context->GetOptionalExtensions().vk_ext_rasterization_order_attachment_access)
{
// don't need the framebuffer-local dependency when we have rasterization order attachment access
subpass_dependency.srcSubpass = 0;
@@ -1677,20 +1580,23 @@ namespace Vulkan
}
if (key.depth_format != VK_FORMAT_UNDEFINED)
{
const VkImageLayout layout = key.depth_sampling ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
attachments[num_attachments] = {0, static_cast<VkFormat>(key.depth_format), VK_SAMPLE_COUNT_1_BIT,
static_cast<VkAttachmentLoadOp>(key.depth_load_op),
static_cast<VkAttachmentStoreOp>(key.depth_store_op),
static_cast<VkAttachmentLoadOp>(key.stencil_load_op),
static_cast<VkAttachmentStoreOp>(key.stencil_store_op),
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL};
layout, layout};
depth_reference.attachment = num_attachments;
depth_reference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
depth_reference.layout = layout;
depth_reference_ptr = &depth_reference;
num_attachments++;
}
const VkSubpassDescriptionFlags subpass_flags =
(key.color_feedback_loop && g_vulkan_context->GetOptionalExtensions().vk_arm_rasterization_order_attachment_access) ? VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_ARM : 0;
(key.color_feedback_loop && g_vulkan_context->GetOptionalExtensions().vk_ext_rasterization_order_attachment_access) ?
VK_SUBPASS_DESCRIPTION_RASTERIZATION_ORDER_ATTACHMENT_COLOR_ACCESS_BIT_EXT :
0;
const VkSubpassDescription subpass = {subpass_flags, VK_PIPELINE_BIND_POINT_GRAPHICS, input_reference_ptr ? 1u : 0u,
input_reference_ptr ? input_reference_ptr : nullptr, color_reference_ptr ? 1u : 0u,
color_reference_ptr ? color_reference_ptr : nullptr, nullptr, depth_reference_ptr, 0, nullptr};
@@ -1740,7 +1646,7 @@ void main()
{
if (!m_spinning_supported)
return true;
auto spirv = ShaderCompiler::CompileComputeShader(SPIN_SHADER);
auto spirv = ShaderCompiler::CompileComputeShader(SPIN_SHADER, false);
if (!spirv.has_value())
return false;
@@ -2068,4 +1974,52 @@ void main()
return static_cast<u64>(ts.tv_sec) * 1000000000 + ts.tv_nsec;
#endif
}
bool Context::AllocatePreinitializedGPUBuffer(u32 size, VkBuffer* gpu_buffer, VmaAllocation* gpu_allocation,
VkBufferUsageFlags gpu_usage, const std::function<void(void*)>& fill_callback)
{
// Try to place the fixed index buffer in GPU local memory.
// Use the staging buffer to copy into it.
const VkBufferCreateInfo cpu_bci = {
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
nullptr,
0, size,
VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_SHARING_MODE_EXCLUSIVE};
const VmaAllocationCreateInfo cpu_aci = {
VMA_ALLOCATION_CREATE_MAPPED_BIT, VMA_MEMORY_USAGE_CPU_ONLY, 0, 0};
VkBuffer cpu_buffer;
VmaAllocation cpu_allocation;
VmaAllocationInfo cpu_ai;
VkResult res = vmaCreateBuffer(m_allocator, &cpu_bci, &cpu_aci, &cpu_buffer,
&cpu_allocation, &cpu_ai);
if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vmaCreateBuffer() for CPU expand buffer failed: ");
return false;
}
const VkBufferCreateInfo gpu_bci = {
VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
nullptr,
0, size,
VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_SHARING_MODE_EXCLUSIVE};
const VmaAllocationCreateInfo gpu_aci = {
0, VMA_MEMORY_USAGE_GPU_ONLY, 0, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT};
VmaAllocationInfo ai;
res = vmaCreateBuffer(m_allocator, &gpu_bci, &gpu_aci, gpu_buffer, gpu_allocation, &ai);
if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vmaCreateBuffer() for expand buffer failed: ");
vmaDestroyBuffer(m_allocator, cpu_buffer, cpu_allocation);
return false;
}
const VkBufferCopy buf_copy = {0u, 0u, size};
fill_callback(cpu_ai.pMappedData);
vmaFlushAllocation(m_allocator, cpu_allocation, 0, size);
vkCmdCopyBuffer(GetCurrentInitCommandBuffer(), cpu_buffer, *gpu_buffer, 1, &buf_copy);
DeferBufferDestruction(cpu_buffer, cpu_allocation);
return true;
}
} // namespace Vulkan
+15 -10
View File
@@ -53,27 +53,25 @@ namespace Vulkan
bool vk_ext_memory_budget : 1;
bool vk_ext_calibrated_timestamps : 1;
bool vk_ext_line_rasterization : 1;
bool vk_ext_rasterization_order_attachment_access : 1;
bool vk_khr_driver_properties : 1;
bool vk_arm_rasterization_order_attachment_access : 1;
bool vk_khr_fragment_shader_barycentric : 1;
bool vk_khr_shader_draw_parameters : 1;
};
~Context();
// Helper method to create a Vulkan instance.
static VkInstance CreateVulkanInstance(
const WindowInfo* wi, bool enable_debug_utils, bool enable_validation_layer);
const WindowInfo& wi, bool enable_debug_utils, bool enable_validation_layer);
// Returns a list of Vulkan-compatible GPUs.
using GPUList = std::vector<VkPhysicalDevice>;
using GPUNameList = std::vector<std::string>;
using GPUList = std::vector<std::pair<VkPhysicalDevice, std::string>>;
static GPUList EnumerateGPUs(VkInstance instance);
static GPUNameList EnumerateGPUNames(VkInstance instance);
// Creates a new context and sets it up as global.
static bool Create(std::string_view gpu_name, const WindowInfo* wi, std::unique_ptr<SwapChain>* out_swap_chain,
VkPresentModeKHR preferred_present_mode, bool threaded_presentation, bool enable_debug_utils,
bool enable_validation_layer);
static bool Create(VkInstance instance, VkSurfaceKHR surface, VkPhysicalDevice physical_device,
bool threaded_presentation, bool enable_debug_utils, bool enable_validation_layer);
// Destroys context.
static void Destroy();
@@ -139,7 +137,8 @@ namespace Vulkan
VkAttachmentLoadOp depth_load_op = VK_ATTACHMENT_LOAD_OP_LOAD,
VkAttachmentStoreOp depth_store_op = VK_ATTACHMENT_STORE_OP_STORE,
VkAttachmentLoadOp stencil_load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
VkAttachmentStoreOp stencil_store_op = VK_ATTACHMENT_STORE_OP_DONT_CARE, bool color_feedback_loop = false)
VkAttachmentStoreOp stencil_store_op = VK_ATTACHMENT_STORE_OP_DONT_CARE,
bool color_feedback_loop = false, bool depth_sampling = false)
{
RenderPassCacheKey key = {};
key.color_format = color_format;
@@ -151,6 +150,7 @@ namespace Vulkan
key.stencil_load_op = stencil_load_op;
key.stencil_store_op = stencil_store_op;
key.color_feedback_loop = color_feedback_loop;
key.depth_sampling = depth_sampling;
auto it = m_render_pass_cache.find(key.key);
if (it != m_render_pass_cache.end())
@@ -236,6 +236,10 @@ namespace Vulkan
void CountRenderPass() { m_command_buffer_render_passes++; }
void NotifyOfReadback();
// Allocates a temporary CPU staging buffer, fires the callback with it to populate, then copies to a GPU buffer.
bool AllocatePreinitializedGPUBuffer(u32 size, VkBuffer* gpu_buffer, VmaAllocation* gpu_allocation,
VkBufferUsageFlags gpu_usage, const std::function<void(void*)>& fill_callback);
private:
Context(VkInstance instance, VkPhysicalDevice physical_device);
@@ -252,6 +256,7 @@ namespace Vulkan
u32 stencil_load_op : 2;
u32 stencil_store_op : 1;
u32 color_feedback_loop : 1;
u32 depth_sampling : 1;
};
u32 key;
@@ -259,7 +264,7 @@ namespace Vulkan
using ExtensionList = std::vector<const char*>;
static bool SelectInstanceExtensions(
ExtensionList* extension_list, const WindowInfo* wi, bool enable_debug_utils);
ExtensionList* extension_list, const WindowInfo& wi, bool enable_debug_utils);
bool SelectDeviceExtensions(ExtensionList* extension_list, bool enable_surface);
bool SelectDeviceFeatures(const VkPhysicalDeviceFeatures* required_features);
bool CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer, const char** required_device_extensions,
-5
View File
@@ -493,11 +493,6 @@ namespace Vulkan
return GetShaderModule(ShaderCompiler::Type::Vertex, std::move(shader_code));
}
VkShaderModule ShaderCache::GetGeometryShader(std::string_view shader_code)
{
return GetShaderModule(ShaderCompiler::Type::Geometry, std::move(shader_code));
}
VkShaderModule ShaderCache::GetFragmentShader(std::string_view shader_code)
{
return GetShaderModule(ShaderCompiler::Type::Fragment, std::move(shader_code));
-1
View File
@@ -47,7 +47,6 @@ namespace Vulkan
VkShaderModule GetShaderModule(ShaderCompiler::Type type, std::string_view shader_code);
VkShaderModule GetVertexShader(std::string_view shader_code);
VkShaderModule GetGeometryShader(std::string_view shader_code);
VkShaderModule GetFragmentShader(std::string_view shader_code);
VkShaderModule GetComputeShader(std::string_view shader_code);
+17 -23
View File
@@ -37,7 +37,7 @@ namespace Vulkan::ShaderCompiler
static bool glslang_initialized = false;
static std::optional<SPIRVCodeVector> CompileShaderToSPV(
EShLanguage stage, const char* stage_filename, std::string_view source)
EShLanguage stage, const char* stage_filename, std::string_view source, bool debug)
{
if (!InitializeGlslang())
return std::nullopt;
@@ -45,9 +45,9 @@ namespace Vulkan::ShaderCompiler
std::unique_ptr<glslang::TShader> shader = std::make_unique<glslang::TShader>(stage);
std::unique_ptr<glslang::TProgram> program;
glslang::TShader::ForbidIncluder includer;
EProfile profile = ECoreProfile;
EShMessages messages = static_cast<EShMessages>(EShMsgDefault | EShMsgSpvRules | EShMsgVulkanRules);
int default_version = 450;
const EProfile profile = ECoreProfile;
const EShMessages messages = static_cast<EShMessages>(EShMsgDefault | EShMsgSpvRules | EShMsgVulkanRules | (debug ? EShMsgDebugInfo : 0));
const int default_version = 450;
std::string full_source_code;
const char* pass_source_code = source.data();
@@ -55,7 +55,7 @@ namespace Vulkan::ShaderCompiler
shader->setStringsWithLengths(&pass_source_code, &pass_source_code_length, 1);
auto DumpBadShader = [&](const char* msg) {
std::string filename = StringUtil::StdStringFromFormat("bad_shader_%u.txt", s_next_bad_shader_id++);
std::string filename = StringUtil::StdStringFromFormat("pcsx2_bad_shader_%u.txt", s_next_bad_shader_id++);
Console.Error("CompileShaderToSPV: %s, writing to %s", msg, filename.c_str());
std::ofstream ofs(filename.c_str(), std::ofstream::out | std::ofstream::binary);
@@ -104,7 +104,9 @@ namespace Vulkan::ShaderCompiler
SPIRVCodeVector out_code;
spv::SpvBuildLogger logger;
glslang::GlslangToSpv(*intermediate, out_code, &logger);
glslang::SpvOptions options;
options.generateDebugInfo = debug;
glslang::GlslangToSpv(*intermediate, out_code, &logger, &options);
// Write out messages
if (std::strlen(shader->getInfoLog()) > 0)
@@ -147,24 +149,19 @@ namespace Vulkan::ShaderCompiler
glslang_initialized = false;
}
std::optional<SPIRVCodeVector> CompileVertexShader(std::string_view source_code)
std::optional<SPIRVCodeVector> CompileVertexShader(std::string_view source_code, bool debug)
{
return CompileShaderToSPV(EShLangVertex, "vs", source_code);
return CompileShaderToSPV(EShLangVertex, "vs", source_code, debug);
}
std::optional<SPIRVCodeVector> CompileGeometryShader(std::string_view source_code)
std::optional<SPIRVCodeVector> CompileFragmentShader(std::string_view source_code, bool debug)
{
return CompileShaderToSPV(EShLangGeometry, "gs", source_code);
return CompileShaderToSPV(EShLangFragment, "ps", source_code, debug);
}
std::optional<SPIRVCodeVector> CompileFragmentShader(std::string_view source_code)
std::optional<SPIRVCodeVector> CompileComputeShader(std::string_view source_code, bool debug)
{
return CompileShaderToSPV(EShLangFragment, "ps", source_code);
}
std::optional<SPIRVCodeVector> CompileComputeShader(std::string_view source_code)
{
return CompileShaderToSPV(EShLangCompute, "cs", source_code);
return CompileShaderToSPV(EShLangCompute, "cs", source_code, debug);
}
std::optional<ShaderCompiler::SPIRVCodeVector> CompileShader(Type type, std::string_view source_code, bool debug)
@@ -172,16 +169,13 @@ namespace Vulkan::ShaderCompiler
switch (type)
{
case Type::Vertex:
return CompileShaderToSPV(EShLangVertex, "vs", source_code);
case Type::Geometry:
return CompileShaderToSPV(EShLangGeometry, "gs", source_code);
return CompileShaderToSPV(EShLangVertex, "vs", source_code, debug);
case Type::Fragment:
return CompileShaderToSPV(EShLangFragment, "ps", source_code);
return CompileShaderToSPV(EShLangFragment, "ps", source_code, debug);
case Type::Compute:
return CompileShaderToSPV(EShLangCompute, "cs", source_code);
return CompileShaderToSPV(EShLangCompute, "cs", source_code, debug);
default:
return std::nullopt;
+3 -7
View File
@@ -26,7 +26,6 @@ namespace Vulkan::ShaderCompiler
enum class Type
{
Vertex,
Geometry,
Fragment,
Compute
};
@@ -38,16 +37,13 @@ namespace Vulkan::ShaderCompiler
using SPIRVCodeVector = std::vector<SPIRVCodeType>;
// Compile a vertex shader to SPIR-V.
std::optional<SPIRVCodeVector> CompileVertexShader(std::string_view source_code);
// Compile a geometry shader to SPIR-V.
std::optional<SPIRVCodeVector> CompileGeometryShader(std::string_view source_code);
std::optional<SPIRVCodeVector> CompileVertexShader(std::string_view source_code, bool debug);
// Compile a fragment shader to SPIR-V.
std::optional<SPIRVCodeVector> CompileFragmentShader(std::string_view source_code);
std::optional<SPIRVCodeVector> CompileFragmentShader(std::string_view source_code, bool debug);
// Compile a compute shader to SPIR-V.
std::optional<SPIRVCodeVector> CompileComputeShader(std::string_view source_code);
std::optional<SPIRVCodeVector> CompileComputeShader(std::string_view source_code, bool debug);
std::optional<SPIRVCodeVector> CompileShader(Type type, std::string_view source_code, bool debug);
} // namespace Vulkan::ShaderCompiler
+11 -5
View File
@@ -545,9 +545,7 @@ namespace Vulkan
// Determine the dimensions of the swap chain. Values of -1 indicate the size we specify here
// determines window size?
VkExtent2D size = surface_capabilities.currentExtent;
#ifndef ANDROID
if (size.width == UINT32_MAX)
#endif
{
size.width = m_window_info.surface_width;
size.height = m_window_info.surface_height;
@@ -562,9 +560,17 @@ namespace Vulkan
if (!(surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR))
transform = surface_capabilities.currentTransform;
VkCompositeAlphaFlagBitsKHR alpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
if (!(surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR))
{
// If we only support pre-multiplied/post-multiplied... :/
if (surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
alpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
}
// Select swap chain flags, we only need a colour attachment
VkImageUsageFlags image_usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
if (!(surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT))
VkImageUsageFlags image_usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
if ((surface_capabilities.supportedUsageFlags & image_usage) != image_usage)
{
Console.Error("Vulkan: Swap chain does not support usage as color attachment");
return false;
@@ -577,7 +583,7 @@ namespace Vulkan
// Now we can actually create the swap chain
VkSwapchainCreateInfoKHR swap_chain_info = {VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, nullptr, 0, m_surface,
image_count, m_surface_format.format, m_surface_format.colorSpace, size, 1u, image_usage,
VK_SHARING_MODE_EXCLUSIVE, 0, nullptr, transform, VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, m_present_mode,
VK_SHARING_MODE_EXCLUSIVE, 0, nullptr, transform, alpha, m_present_mode,
VK_TRUE, old_swap_chain};
std::array<uint32_t, 2> indices = {{
g_vulkan_context->GetGraphicsQueueFamilyIndex(),
+12 -6
View File
@@ -291,9 +291,12 @@ namespace Vulkan
case VK_IMAGE_LAYOUT_GENERAL:
// General is used for feedback loops.
barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
barrier.srcAccessMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT) ?
(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT) :
(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT);
srcStageMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT) ?
(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) :
(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
break;
default:
@@ -341,9 +344,12 @@ namespace Vulkan
case VK_IMAGE_LAYOUT_GENERAL:
// General is used for feedback loops.
barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
barrier.dstAccessMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT) ?
(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT) :
(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT);
dstStageMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT) ?
(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) :
(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
break;
default:
+3 -3
View File
@@ -2,11 +2,11 @@
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="UserMacros">
<BinaryOutputDir>$(SolutionDir)bin\</BinaryOutputDir>
<PCSX2QTDIRDefault Condition="'$(Platform)'=='x64'">$(SolutionDir)3rdparty\qt\6.4.0\msvc2022_64\</PCSX2QTDIRDefault>
<PCSX2QTDIRDefault Condition="'$(Platform)'=='ARM64'">$(SolutionDir)3rdparty\qt\6.4.0\msvc2022_arm64\</PCSX2QTDIRDefault>
<PCSX2QTDIRDefault Condition="'$(Platform)'=='x64'">$(SolutionDir)3rdparty\qt\6.5.0\msvc2022_64\</PCSX2QTDIRDefault>
<PCSX2QTDIRDefault Condition="'$(Platform)'=='ARM64'">$(SolutionDir)3rdparty\qt\6.5.0\msvc2022_arm64\</PCSX2QTDIRDefault>
<PCSX2QTDIR Condition="Exists('$(PCSX2QTDIRDefault)') And ('$(PCSX2QTDIR)'=='' Or !Exists('$(PCSX2QTDIR)'))">$(PCSX2QTDIRDefault)</PCSX2QTDIR>
<PCSX2QTDIR Condition="Exists('$(PCSX2QTDIR)') And !HasTrailingSlash('$(PCSX2QTDIR)')">$(PCSX2QTDIR)\</PCSX2QTDIR>
<PCSX2QTDIRHost>$(SolutionDir)3rdparty\qt\6.4.0\msvc2022_64\</PCSX2QTDIRHost>
<PCSX2QTDIRHost>$(SolutionDir)3rdparty\qt\6.5.0\msvc2022_64\</PCSX2QTDIRHost>
<QtDirValid>false</QtDirValid>
<QtDirValid Condition="Exists('$(PCSX2QTDIR)')">true</QtDirValid>
<QtIncludeDir>$(PCSX2QTDIR)include\</QtIncludeDir>
+36 -59
View File
@@ -45,7 +45,7 @@
#include "pcsx2/GS.h"
#include "pcsx2/GS/GS.h"
#include "pcsx2/GSDumpReplayer.h"
#include "pcsx2/HostDisplay.h"
#include "pcsx2/Host.h"
#include "pcsx2/HostSettings.h"
#include "pcsx2/INISettingsInterface.h"
#include "pcsx2/PAD/Host/PAD.h"
@@ -60,7 +60,9 @@
namespace GSRunner
{
static void InitializeConsole();
static bool InitializeConfig();
static bool ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& params);
static bool CreatePlatformWindow();
static void DestroyPlatformWindow();
@@ -77,6 +79,7 @@ alignas(16) static SysMtgsThread s_mtgs_thread;
static std::string s_output_prefix;
static s32 s_loop_count = 1;
static std::optional<bool> s_use_window;
static bool s_no_console = false;
// Owned by the GS thread.
static u32 s_dump_frame_number = 0;
@@ -112,7 +115,7 @@ bool GSRunner::InitializeConfig()
si.SetBoolValue("EmuCore", "EnablePerGameSettings", false);
// force logging
si.SetBoolValue("Logging", "EnableSystemConsole", true);
si.SetBoolValue("Logging", "EnableSystemConsole", !s_no_console);
si.SetBoolValue("Logging", "EnableTimestamps", true);
si.SetBoolValue("Logging", "EnableVerbose", true);
@@ -251,38 +254,18 @@ void Host::SetRelativeMouseMode(bool enabled)
{
}
bool Host::AcquireHostDisplay(RenderAPI api, bool clear_state_on_fail)
std::optional<WindowInfo> Host::AcquireRenderWindow(bool recreate_window)
{
const std::optional<WindowInfo> wi(GSRunner::GetPlatformWindowInfo());
if (!wi.has_value())
return false;
g_host_display = HostDisplay::CreateForAPI(api);
if (!g_host_display)
return false;
if (!g_host_display->CreateDevice(wi.value(), Host::GetEffectiveVSyncMode()) ||
!g_host_display->MakeCurrent() || !g_host_display->SetupDevice() || !ImGuiManager::Initialize())
{
ReleaseHostDisplay(clear_state_on_fail);
return false;
}
Console.WriteLn(Color_StrongGreen, "%s Graphics Driver Info:", HostDisplay::RenderAPIToString(g_host_display->GetRenderAPI()));
Console.Indent().WriteLn(g_host_display->GetDriverInfo());
return g_host_display.get();
return GSRunner::GetPlatformWindowInfo();
}
void Host::ReleaseHostDisplay(bool clear_state)
void Host::ReleaseRenderWindow()
{
ImGuiManager::Shutdown(clear_state);
g_host_display.reset();
}
HostDisplay::PresentResult Host::BeginPresentFrame(bool frame_skip)
void Host::BeginPresentFrame()
{
if (s_loop_number == 0)
if (s_loop_number == 0 && !s_output_prefix.empty())
{
// when we wrap around, don't race other files
GSJoinSnapshotThreads();
@@ -291,33 +274,6 @@ HostDisplay::PresentResult Host::BeginPresentFrame(bool frame_skip)
std::string dump_path(fmt::format("{}_frame{}.png", s_output_prefix, s_dump_frame_number));
GSQueueSnapshot(dump_path);
}
const HostDisplay::PresentResult result = g_host_display->BeginPresent(frame_skip);
if (result != HostDisplay::PresentResult::OK)
{
// don't render imgui
ImGuiManager::SkipFrame();
}
return result;
}
void Host::EndPresentFrame()
{
if (GSDumpReplayer::IsReplayingDump())
GSDumpReplayer::RenderUI();
ImGuiManager::RenderOSD();
g_host_display->EndPresent();
ImGuiManager::NewFrame();
}
void Host::ResizeHostDisplay(u32 new_window_width, u32 new_window_height, float new_window_scale)
{
}
void Host::UpdateHostDisplay()
{
}
void Host::RequestResizeHostDisplay(s32 width, s32 height)
@@ -453,7 +409,15 @@ static void PrintCommandLineHelp(const char* progname)
std::fprintf(stderr, "\n");
}
static bool ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& params)
void GSRunner::InitializeConsole()
{
const char* var = std::getenv("PCSX2_NOCONSOLE");
s_no_console = (var && StringUtil::FromChars<bool>(var).value_or(false));
if (!s_no_console)
CommonHost::InitializeEarlyConsole();
}
bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& params)
{
bool no_more_args = false;
for (int i = 1; i < argc; i++)
@@ -556,6 +520,19 @@ static bool ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& param
continue;
}
else if (CHECK_ARG_PARAM("-upscale"))
{
const float upscale = StringUtil::FromChars<float>(argv[++i]).value_or(0.0f);
if (upscale < 0.5f)
{
Console.WriteLn("Invalid upscale multiplier");
return false;
}
Console.WriteLn(fmt::format("Setting upscale multiplier to {}", upscale));
s_settings_interface.SetFloatValue("EmuCore/GS", "upscale_multiplier", upscale);
continue;
}
else if (CHECK_ARG_PARAM("-logfile"))
{
const char* logfile = argv[++i];
@@ -573,7 +550,7 @@ static bool ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& param
else if (CHECK_ARG("-noshadercache"))
{
Console.WriteLn("Disabling shader cache");
s_settings_interface.SetBoolValue("EmuCore/GS", "disable_shader_cache", false);
s_settings_interface.SetBoolValue("EmuCore/GS", "disable_shader_cache", true);
continue;
}
else if (CHECK_ARG("-window"))
@@ -637,7 +614,7 @@ static bool ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& param
int main(int argc, char* argv[])
{
CommonHost::InitializeEarlyConsole();
GSRunner::InitializeConsole();
if (!GSRunner::InitializeConfig())
{
@@ -646,7 +623,7 @@ int main(int argc, char* argv[])
}
VMBootParameters params;
if (!ParseCommandLineArgs(argc, argv, params))
if (!GSRunner::ParseCommandLineArgs(argc, argv, params))
return EXIT_FAILURE;
PerformanceMetrics::SetCPUThread(Threading::ThreadHandle::GetForCallingThread());
@@ -656,7 +633,7 @@ int main(int argc, char* argv[])
return EXIT_FAILURE;
}
if (s_use_window.value_or(false) && !GSRunner::CreatePlatformWindow())
if (s_use_window.value_or(true) && !GSRunner::CreatePlatformWindow())
{
Console.Error("Failed to create window.");
return EXIT_FAILURE;
+32 -19
View File
@@ -7,20 +7,19 @@ import multiprocessing
from pathlib import Path
from functools import partial
def is_gs_path(path):
ppath = Path(path)
for extension in [[".gs"], [".gs", ".xz"], [".gs", ".zst"]]:
if ppath.suffixes == extension:
return True
def get_gs_name(path):
lpath = path.lower()
return False
for extension in [".gs", ".gs.xz", ".gs.zst"]:
if lpath.endswith(extension):
return os.path.basename(path)[:-len(extension)]
return None
def run_regression_test(runner, dumpdir, renderer, parallel, renderhacks, gspath):
def run_regression_test(runner, dumpdir, renderer, upscale, renderhacks, parallel, gspath):
args = [runner]
gsname = Path(gspath).name
while gsname.rfind('.') >= 0:
gsname = gsname[:gsname.rfind('.')]
gsname = get_gs_name(gspath)
real_dumpdir = os.path.join(dumpdir, gsname).strip()
if not os.path.exists(real_dumpdir):
@@ -28,6 +27,9 @@ def run_regression_test(runner, dumpdir, renderer, parallel, renderhacks, gspath
if renderer is not None:
args.extend(["-renderer", renderer])
if upscale != 1.0:
args.extend(["-upscale", str(upscale)])
if renderhacks is not None:
args.extend(["-renderhacks", renderhacks])
@@ -43,16 +45,23 @@ def run_regression_test(runner, dumpdir, renderer, parallel, renderhacks, gspath
if parallel > 1:
args.append("-noshadercache")
# run surfaceless, we don't want tons of windows popping up
args.append("-surfaceless");
# disable output console entirely
environ = os.environ.copy()
environ["PCSX2_NOCONSOLE"] = "1"
args.append("--")
args.append(gspath)
print("Running '%s'" % (" ".join(args)))
subprocess.run(args)
#print("Running '%s'" % (" ".join(args)))
subprocess.run(args, env=environ, stdin=subprocess.DEVNULL, stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
def run_regression_tests(runner, gsdir, dumpdir, renderer, renderhacks, parallel=1):
def run_regression_tests(runner, gsdir, dumpdir, renderer, upscale, renderhacks, parallel=1):
paths = glob.glob(gsdir + "/*.*", recursive=True)
gamepaths = list(filter(is_gs_path, paths))
gamepaths = list(filter(lambda x: get_gs_name(x) is not None, paths))
if not os.path.isdir(dumpdir):
os.mkdir(dumpdir)
@@ -61,12 +70,15 @@ def run_regression_tests(runner, gsdir, dumpdir, renderer, renderhacks, parallel
if parallel <= 1:
for game in gamepaths:
run_regression_test(runner, dumpdir, renderer, parallel, renderhacks, game)
run_regression_test(runner, dumpdir, renderer, upscale, renderhacks, parallel, game)
else:
print("Processing %u games on %u processors" % (len(gamepaths), parallel))
func = partial(run_regression_test, runner, dumpdir, renderer, parallel, renderhacks)
func = partial(run_regression_test, runner, dumpdir, renderer, upscale, renderhacks, parallel)
pool = multiprocessing.Pool(parallel)
pool.map(func, gamepaths)
completed = 0
for _ in pool.imap_unordered(func, gamepaths, chunksize=1):
completed += 1
print("Processed %u of %u GS dumps (%u%%)" % (completed, len(gamepaths), (completed * 100) // len(gamepaths)))
pool.close()
@@ -79,12 +91,13 @@ if __name__ == "__main__":
parser.add_argument("-gsdir", action="store", required=True, help="Directory containing GS dumps")
parser.add_argument("-dumpdir", action="store", required=True, help="Base directory to dump frames to")
parser.add_argument("-renderer", action="store", required=False, help="Renderer to use")
parser.add_argument("-upscale", action="store", type=float, default=1, help="Upscaling multiplier to use")
parser.add_argument("-renderhacks", action="store", required=False, help="Enable HW Rendering hacks")
parser.add_argument("-parallel", action="store", type=int, default=1, help="Number of proceeses to run")
parser.add_argument("-renderhacks", action="store", required=False, help="Enable HW Renering hacks")
args = parser.parse_args()
if not run_regression_tests(args.runner, os.path.realpath(args.gsdir), os.path.realpath(args.dumpdir), args.renderer, args.renderhacks, args.parallel):
if not run_regression_tests(args.runner, os.path.realpath(args.gsdir), os.path.realpath(args.dumpdir), args.renderer, args.upscale, args.renderhacks, args.parallel):
sys.exit(1)
else:
sys.exit(0)
+2 -2
View File
@@ -66,7 +66,7 @@
<item>
<widget class="QLabel" name="scmversion">
<property name="text">
<string>SCM Version</string>
<string extracomment="SCM= Source Code Management">SCM Version</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
@@ -128,7 +128,7 @@
<item>
<widget class="QLabel" name="links">
<property name="text">
<string>TextLabel</string>
<string notr="true">TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
+32 -1
View File
@@ -385,7 +385,7 @@ void AutoUpdaterDialog::getChangesComplete(QNetworkReply* reply)
if (update_will_break_save_states)
{
changes_html.prepend(tr("<h2>Save State Warning</h2><p>Installing this update will make your save states "
"<b>incompatible</b>. Please ensure you have saved your games to memory card "
"<b>incompatible</b>. Please ensure you have saved your games to a Memory Card "
"before installing this update or you will lose progress.</p>"));
}
@@ -595,6 +595,11 @@ bool AutoUpdaterDialog::doUpdate(const QString& zip_path, const QString& updater
return true;
}
void AutoUpdaterDialog::cleanupAfterUpdate()
{
// Nothing to do on Windows for now, the updater stub cleans everything up.
}
#elif defined(__linux__)
bool AutoUpdaterDialog::processUpdate(const QByteArray& update_data, QProgressDialog&)
@@ -663,6 +668,7 @@ bool AutoUpdaterDialog::processUpdate(const QByteArray& update_data, QProgressDi
// Execute new appimage.
QProcess* new_process = new QProcess();
new_process->setProgram(qappimage_path);
new_process->setArguments(QStringList{QStringLiteral("-updatecleanup")});
if (!new_process->startDetached())
{
reportError("Failed to execute new AppImage.");
@@ -673,6 +679,23 @@ bool AutoUpdaterDialog::processUpdate(const QByteArray& update_data, QProgressDi
return true;
}
void AutoUpdaterDialog::cleanupAfterUpdate()
{
// Remove old/backup AppImage.
const char* appimage_path = std::getenv("APPIMAGE");
if (!appimage_path)
return;
const QString qappimage_path(QString::fromUtf8(appimage_path));
const QString backup_appimage_path(qappimage_path + QStringLiteral(".backup"));
if (!QFile::exists(backup_appimage_path))
return;
Console.WriteLn(Color_StrongOrange, QStringLiteral("Removing backup AppImage %1").arg(backup_appimage_path).toStdString());
if (!QFile::remove(backup_appimage_path))
Console.Error(QStringLiteral("Failed to remove backup AppImage %1").arg(backup_appimage_path).toStdString());
}
#elif defined(__APPLE__)
static QString UpdateVersionNumberInName(QString name, QStringView new_version)
@@ -789,6 +812,10 @@ bool AutoUpdaterDialog::processUpdate(const QByteArray& update_data, QProgressDi
return true;
}
void AutoUpdaterDialog::cleanupAfterUpdate()
{
}
#else
bool AutoUpdaterDialog::processUpdate(const QByteArray& update_data, QProgressDialog& progress)
@@ -796,4 +823,8 @@ bool AutoUpdaterDialog::processUpdate(const QByteArray& update_data, QProgressDi
return false;
}
void AutoUpdaterDialog::cleanupAfterUpdate()
{
}
#endif
+1
View File
@@ -37,6 +37,7 @@ public:
static std::string getDefaultTag();
static QString getCurrentVersion();
static QString getCurrentVersionDate();
static void cleanupAfterUpdate();
Q_SIGNALS:
void updateCheckCompleted();
+2 -1
View File
@@ -24,6 +24,8 @@ target_sources(pcsx2-qt PRIVATE
MainWindow.ui
PrecompiledHeader.cpp
PrecompiledHeader.h
SettingWidgetBinder.h
Themes.cpp
QtHost.cpp
QtHost.h
QtKeyCodes.cpp
@@ -31,7 +33,6 @@ target_sources(pcsx2-qt PRIVATE
QtProgressCallback.h
QtUtils.cpp
QtUtils.h
SettingWidgetBinder.h
GameList/EmptyGameListWidget.ui
GameList/GameListModel.cpp
GameList/GameListModel.h
+27 -1
View File
@@ -418,6 +418,7 @@ void CpuWidget::onFuncListContextMenu(QPoint pos)
else
m_funclistContextMenu->clear();
//: "Demangling" is the opposite of "Name mangling", which is a process where a compiler takes function names and combines them with other characteristics of the function (e.g. what types of data it accepts) to ensure they stay unique even when multiple functions exist with the same name (but different inputs / const-ness). See here: https://en.wikipedia.org/wiki/Name_mangling#C++
QAction* demangleAction = new QAction(tr("Demangle Symbols"), m_ui.listFunctions);
demangleAction->setCheckable(true);
demangleAction->setChecked(m_demangleFunctions);
@@ -664,9 +665,11 @@ void CpuWidget::onSearchButtonClicked()
const QString searchValue = m_ui.txtSearchValue->text();
unsigned long long value;
if (searchType < 4)
{
searchValue.toLong(&ok, searchHex ? 16 : 10);
value = searchValue.toULongLong(&ok, searchHex ? 16 : 10);
}
else if (searchType != 6)
{
@@ -679,6 +682,29 @@ void CpuWidget::onSearchButtonClicked()
return;
}
switch (searchType)
{
case 6:
case 5:
case 4:
break;
case 3:
if (value <= std::numeric_limits<unsigned long long>::max())
break;
case 2:
if (value <= std::numeric_limits<unsigned long>::max())
break;
case 1:
if (value <= std::numeric_limits<unsigned short>::max())
break;
case 0:
if (value <= std::numeric_limits<unsigned char>::max())
break;
default:
QMessageBox::critical(this, tr("Debugger"), tr("Value is larger than type"));
return;
}
QFutureWatcher<std::vector<u32>>* workerWatcher = new QFutureWatcher<std::vector<u32>>;
connect(workerWatcher, &QFutureWatcher<std::vector<u32>>::finished, [this, workerWatcher] {
+2 -2
View File
@@ -159,7 +159,7 @@
<item row="4" column="1" colspan="3">
<widget class="QLineEdit" name="txtSearchStart">
<property name="text">
<string>0x00</string>
<string notr="true">0x00</string>
</property>
</widget>
</item>
@@ -183,7 +183,7 @@
<item row="5" column="1" colspan="3">
<widget class="QLineEdit" name="txtSearchEnd">
<property name="text">
<string>0x2000000</string>
<string notr="true">0x2000000</string>
</property>
</widget>
</item>
@@ -79,6 +79,7 @@ QVariant BreakpointModel::data(const QModelIndex& index, int role) const
QString type("");
type += (mc->cond & MEMCHECK_READ) ? tr("Read") : "";
type += ((mc->cond & MEMCHECK_BOTH) == MEMCHECK_BOTH) ? ", " : " ";
//: (C) = changes, as in "look for changes".
type += (mc->cond & MEMCHECK_WRITE) ? (mc->cond & MEMCHECK_WRITE_ONCHANGE) ? tr("Write(C)") : tr("Write") : "";
return type;
}
@@ -169,18 +170,25 @@ QVariant BreakpointModel::headerData(int section, Qt::Orientation orientation, i
switch (section)
{
case BreakpointColumns::TYPE:
//: Warning: limited space available. Abbreviate if needed.
return tr("TYPE");
case BreakpointColumns::OFFSET:
//: Warning: limited space available. Abbreviate if needed.
return tr("OFFSET");
case BreakpointColumns::SIZE_LABEL:
//: Warning: limited space available. Abbreviate if needed.
return tr("SIZE / LABEL");
case BreakpointColumns::OPCODE:
//: Warning: limited space available. Abbreviate if needed.
return tr("INSTRUCTION");
case BreakpointColumns::CONDITION:
//: Warning: limited space available. Abbreviate if needed.
return tr("CONDITION");
case BreakpointColumns::HITS:
//: Warning: limited space available. Abbreviate if needed.
return tr("HITS");
case BreakpointColumns::ENABLED:
//: Warning: limited space available. Abbreviate if needed.
return tr("ENABLED");
default:
return QVariant();
+6
View File
@@ -87,16 +87,22 @@ QVariant StackModel::headerData(int section, Qt::Orientation orientation, int ro
switch (section)
{
case StackColumns::ENTRY:
//: Warning: short space limit. Abbreviate if needed.
return tr("ENTRY");
case StackColumns::ENTRY_LABEL:
//: Warning: short space limit. Abbreviate if needed.
return tr("LABEL");
case StackColumns::PC:
//: Warning: short space limit. Abbreviate if needed. PC = Program Counter (location where the CPU is executing).
return tr("PC");
case StackColumns::PC_OPCODE:
//: Warning: short space limit. Abbreviate if needed.
return tr("INSTRUCTION");
case StackColumns::SP:
//: Warning: short space limit. Abbreviate if needed.
return tr("STACK POINTER");
case StackColumns::SIZE:
//: Warning: short space limit. Abbreviate if needed.
return tr("SIZE");
default:
return QVariant();
+6
View File
@@ -110,16 +110,22 @@ QVariant ThreadModel::headerData(int section, Qt::Orientation orientation, int r
switch (section)
{
case ThreadColumns::ID:
//: Warning: short space limit. Abbreviate if needed.
return tr("ID");
case ThreadColumns::PC:
//: Warning: short space limit. Abbreviate if needed. PC = Program Counter (location where the CPU is executing).
return tr("PC");
case ThreadColumns::ENTRY:
//: Warning: short space limit. Abbreviate if needed.
return tr("ENTRY");
case ThreadColumns::PRIORITY:
//: Warning: short space limit. Abbreviate if needed.
return tr("PRIORITY");
case ThreadColumns::STATE:
//: Warning: short space limit. Abbreviate if needed.
return tr("STATE");
case ThreadColumns::WAIT_TYPE:
//: Warning: short space limit. Abbreviate if needed.
return tr("WAIT TYPE");
default:
return QVariant();
+18
View File
@@ -49,24 +49,42 @@ public:
private:
const std::map<ThreadStatus, QString> ThreadStateStrings{
//ADDING I18N comments here because the context string added by QtLinguist does not mention that these are thread states.
//: Refers to a Thread State in the Debugger.
{ThreadStatus::THS_BAD, tr("BAD")},
//: Refers to a Thread State in the Debugger.
{ThreadStatus::THS_RUN, tr("RUN")},
//: Refers to a Thread State in the Debugger.
{ThreadStatus::THS_READY, tr("READY")},
//: Refers to a Thread State in the Debugger.
{ThreadStatus::THS_WAIT, tr("WAIT")},
//: Refers to a Thread State in the Debugger.
{ThreadStatus::THS_SUSPEND, tr("SUSPEND")},
//: Refers to a Thread State in the Debugger.
{ThreadStatus::THS_WAIT_SUSPEND, tr("WAIT SUSPEND")},
//: Refers to a Thread State in the Debugger.
{ThreadStatus::THS_DORMANT, tr("DORMANT")},
};
const std::map<WaitState, QString> ThreadWaitStrings{
//ADDING I18N comments here because the context string added by QtLinguist does not mention that these are thread wait states.
//: Refers to a Thread Wait State in the Debugger.
{WaitState::NONE, tr("NONE")},
//: Refers to a Thread Wait State in the Debugger.
{WaitState::WAKEUP_REQ, tr("WAKEUP REQUEST")},
//: Refers to a Thread Wait State in the Debugger.
{WaitState::SEMA, tr("SEMAPHORE")},
//: Refers to a Thread Wait State in the Debugger.
{WaitState::SLEEP, tr("SLEEP")},
//: Refers to a Thread Wait State in the Debugger.
{WaitState::DELAY, tr("DELAY")},
//: Refers to a Thread Wait State in the Debugger.
{WaitState::EVENTFLAG, tr("EVENTFLAG")},
//: Refers to a Thread Wait State in the Debugger.
{WaitState::MBOX, tr("MBOX")},
//: Refers to a Thread Wait State in the Debugger.
{WaitState::VPOOL, tr("VPOOL")},
//: Refers to a Thread Wait State in the Debugger.
{WaitState::FIXPOOL, tr("FIXPOOL")},
};
+1
View File
@@ -342,6 +342,7 @@ bool RegisterWidget::contextFetchNewValue(u64& out, u64 currentValue, bool segme
else
existingValue = existingValue.arg(bit_cast<float>((u32)currentValue));
//: Changing the value in a CPU register (e.g. "Change t0")
QString input = QInputDialog::getText(this, tr("Change %1").arg(m_cpu->getRegisterName(categoryIndex, m_selectedRow)), "",
QLineEdit::Normal, existingValue, &ok);
+2 -2
View File
@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
<string notr="true">Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
@@ -40,7 +40,7 @@
<item>
<widget class="QLabel" name="supportedFormats">
<property name="text">
<string>TextLabel</string>
<string notr="true">TextLabel</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
+1 -1
View File
@@ -181,7 +181,7 @@ void GameListWidget::initialize()
m_list_view = new GameListGridListView(m_ui.stack);
m_list_view->setModel(m_sort_model);
m_list_view->setModelColumn(GameListModel::Column_Cover);
m_list_view->setSelectionMode(QAbstractItemView::ExtendedSelection);
m_list_view->setSelectionMode(QAbstractItemView::SingleSelection);
m_list_view->setViewMode(QListView::IconMode);
m_list_view->setResizeMode(QListView::Adjust);
m_list_view->setUniformItemSizes(true);
+1 -1
View File
@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
<string notr="true">Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
+123 -548
View File
@@ -32,9 +32,9 @@
#include "pcsx2/CDVD/CDVDdiscReader.h"
#include "pcsx2/Frontend/GameList.h"
#include "pcsx2/Frontend/LogSink.h"
#include "pcsx2/GS.h"
#include "pcsx2/GS/GS.h"
#include "pcsx2/GSDumpReplayer.h"
#include "pcsx2/HostDisplay.h"
#include "pcsx2/HostSettings.h"
#include "pcsx2/PerformanceMetrics.h"
#include "pcsx2/Recording/InputRecording.h"
@@ -66,7 +66,6 @@
#include "pcsx2/Frontend/Achievements.h"
#endif
const char* MainWindow::OPEN_FILE_FILTER =
QT_TRANSLATE_NOOP("MainWindow", "All File Types (*.bin *.iso *.cue *.chd *.cso *.gz *.elf *.irx *.gs *.gs.xz *.gs.zst *.dump);;"
"Single-Track Raw Images (*.bin *.iso);;"
@@ -87,16 +86,7 @@ const char* MainWindow::DISC_IMAGE_FILTER = QT_TRANSLATE_NOOP("MainWindow", "All
"GZ Images (*.gz);;"
"Block Dumps (*.dump)");
#ifdef __APPLE__
const char* MainWindow::DEFAULT_THEME_NAME = "";
#else
const char* MainWindow::DEFAULT_THEME_NAME = "darkfusion";
#endif
MainWindow* g_main_window = nullptr;
static QString s_unthemed_style_name;
static QPalette s_unthemed_palette;
static bool s_unthemed_style_name_set;
#if defined(_WIN32) || defined(__APPLE__)
static const bool s_use_central_widget = false;
@@ -254,13 +244,17 @@ void MainWindow::setupAdditionalUi()
m_status_vps_widget->setFixedSize(125, 16);
m_status_vps_widget->hide();
m_settings_toolbar_menu = new QMenu(m_ui.toolBar);
m_settings_toolbar_menu->addAction(m_ui.actionSettings);
m_settings_toolbar_menu->addAction(m_ui.actionViewGameProperties);
for (u32 scale = 0; scale <= 10; scale++)
{
QAction* action = m_ui.menuWindowSize->addAction((scale == 0) ? tr("Internal Resolution") : tr("%1x Scale").arg(scale));
connect(action, &QAction::triggered, [scale]() { g_emu_thread->requestDisplaySize(static_cast<float>(scale)); });
}
updateEmulationActions(false, false);
updateEmulationActions(false, false, false);
updateDisplayRelatedActions(false, false, false);
#ifdef ENABLE_RAINTEGRATION
@@ -316,6 +310,7 @@ void MainWindow::connectSignals()
connect(m_ui.menuLoadState, &QMenu::aboutToShow, this, &MainWindow::onLoadStateMenuAboutToShow);
connect(m_ui.menuSaveState, &QMenu::aboutToShow, this, &MainWindow::onSaveStateMenuAboutToShow);
connect(m_ui.actionSettings, &QAction::triggered, [this]() { doSettings(); });
connect(m_ui.actionSettings2, &QAction::triggered, this, &MainWindow::onSettingsTriggeredFromToolbar);
connect(m_ui.actionInterfaceSettings, &QAction::triggered, [this]() { doSettings("Interface"); });
connect(m_ui.actionGameListSettings, &QAction::triggered, [this]() { doSettings("Game List"); });
connect(m_ui.actionEmulationSettings, &QAction::triggered, [this]() { doSettings("Emulation"); });
@@ -410,10 +405,9 @@ void MainWindow::connectVMThreadSignals(EmuThread* thread)
connect(m_ui.actionStartFullscreenUI, &QAction::triggered, thread, &EmuThread::startFullscreenUI);
connect(m_ui.actionStartFullscreenUI2, &QAction::triggered, thread, &EmuThread::startFullscreenUI);
connect(thread, &EmuThread::messageConfirmed, this, &MainWindow::confirmMessage, Qt::BlockingQueuedConnection);
connect(thread, &EmuThread::onCreateDisplayRequested, this, &MainWindow::createDisplay, Qt::BlockingQueuedConnection);
connect(thread, &EmuThread::onUpdateDisplayRequested, this, &MainWindow::updateDisplay, Qt::BlockingQueuedConnection);
connect(thread, &EmuThread::onDestroyDisplayRequested, this, &MainWindow::destroyDisplay, Qt::BlockingQueuedConnection);
connect(thread, &EmuThread::onResizeDisplayRequested, this, &MainWindow::displayResizeRequested);
connect(thread, &EmuThread::onAcquireRenderWindowRequested, this, &MainWindow::acquireRenderWindow, Qt::BlockingQueuedConnection);
connect(thread, &EmuThread::onReleaseRenderWindowRequested, this, &MainWindow::releaseRenderWindow, Qt::BlockingQueuedConnection);
connect(thread, &EmuThread::onResizeRenderWindowRequested, this, &MainWindow::displayResizeRequested);
connect(thread, &EmuThread::onRelativeMouseModeRequested, this, &MainWindow::relativeMouseModeRequested);
connect(thread, &EmuThread::onVMStarting, this, &MainWindow::onVMStarting);
connect(thread, &EmuThread::onVMStarted, this, &MainWindow::onVMStarted);
@@ -498,415 +492,7 @@ void MainWindow::resetSettings(bool ui)
g_main_window->recreateSettings();
}
void MainWindow::updateApplicationTheme()
{
if (!s_unthemed_style_name_set)
{
s_unthemed_style_name_set = true;
s_unthemed_style_name = QApplication::style()->objectName();
s_unthemed_palette = QApplication::style()->standardPalette();
}
setStyleFromSettings();
setIconThemeFromStyle();
}
void MainWindow::setStyleFromSettings()
{
const std::string theme(Host::GetBaseStringSettingValue("UI", "Theme", DEFAULT_THEME_NAME));
if (theme == "fusion")
{
qApp->setPalette(s_unthemed_palette);
qApp->setStyleSheet(QString());
qApp->setStyle(QStyleFactory::create("Fusion"));
}
else if (theme == "darkfusion")
{
// adapted from https://gist.github.com/QuantumCD/6245215
qApp->setStyle(QStyleFactory::create("Fusion"));
const QColor lighterGray(75, 75, 75);
const QColor darkGray(53, 53, 53);
const QColor gray(128, 128, 128);
const QColor black(25, 25, 25);
const QColor blue(198, 238, 255);
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, darkGray);
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, black);
darkPalette.setColor(QPalette::AlternateBase, darkGray);
darkPalette.setColor(QPalette::ToolTipBase, darkGray);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, darkGray);
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::Link, blue);
darkPalette.setColor(QPalette::Highlight, lighterGray);
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::PlaceholderText, QColor(Qt::white).darker());
darkPalette.setColor(QPalette::Active, QPalette::Button, darkGray);
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Light, darkGray);
qApp->setPalette(darkPalette);
qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
}
else if (theme == "darkfusionblue")
{
// adapted from https://gist.github.com/QuantumCD/6245215
qApp->setStyle(QStyleFactory::create("Fusion"));
const QColor darkGray(53, 53, 53);
const QColor gray(128, 128, 128);
const QColor black(25, 25, 25);
const QColor blue(198, 238, 255);
const QColor blue2(0, 88, 208);
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, darkGray);
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, black);
darkPalette.setColor(QPalette::AlternateBase, darkGray);
darkPalette.setColor(QPalette::ToolTipBase, blue2);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, darkGray);
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::Link, blue);
darkPalette.setColor(QPalette::Highlight, blue2);
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::PlaceholderText, QColor(Qt::white).darker());
darkPalette.setColor(QPalette::Active, QPalette::Button, darkGray);
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Light, darkGray);
qApp->setPalette(darkPalette);
qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
}
else if (theme == "UntouchedLagoon")
{
// Custom palette by RedDevilus, Tame (Light/Washed out) Green as main color and Grayish Blue as complimentary.
// Alternative white theme.
qApp->setStyle(QStyleFactory::create("Fusion"));
const QColor black(25, 25, 25);
const QColor darkteal(0, 77, 77);
const QColor teal(0, 128, 128);
const QColor tameTeal(160, 190, 185);
const QColor grayBlue(160, 180, 190);
QPalette standardPalette;
standardPalette.setColor(QPalette::Window, tameTeal);
standardPalette.setColor(QPalette::WindowText, black.lighter());
standardPalette.setColor(QPalette::Base, grayBlue);
standardPalette.setColor(QPalette::AlternateBase, tameTeal);
standardPalette.setColor(QPalette::ToolTipBase, tameTeal);
standardPalette.setColor(QPalette::ToolTipText, grayBlue);
standardPalette.setColor(QPalette::Text, black);
standardPalette.setColor(QPalette::Button, tameTeal);
standardPalette.setColor(QPalette::ButtonText, black);
standardPalette.setColor(QPalette::Link, black.lighter());
standardPalette.setColor(QPalette::Highlight, teal);
standardPalette.setColor(QPalette::HighlightedText, grayBlue.lighter());
standardPalette.setColor(QPalette::Active, QPalette::Button, tameTeal);
standardPalette.setColor(QPalette::Disabled, QPalette::ButtonText, darkteal);
standardPalette.setColor(QPalette::Disabled, QPalette::WindowText, darkteal.lighter());
standardPalette.setColor(QPalette::Disabled, QPalette::Text, darkteal.lighter());
standardPalette.setColor(QPalette::Disabled, QPalette::Light, tameTeal);
qApp->setPalette(standardPalette);
qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
}
else if (theme == "BabyPastel")
{
// Custom palette by RedDevilus, Blue as main color and blue as complimentary.
// Alternative light theme.
qApp->setStyle(QStyleFactory::create("Fusion"));
const QColor gray(150, 150, 150);
const QColor black(25, 25, 25);
const QColor redpinkish(200, 75, 132);
const QColor pink(255, 174, 201);
const QColor brightPink(255, 230, 255);
const QColor congoPink(255, 127, 121);
const QColor blue(221, 225, 239);
QPalette standardPalette;
standardPalette.setColor(QPalette::Window, pink);
standardPalette.setColor(QPalette::WindowText, black);
standardPalette.setColor(QPalette::Base, brightPink);
standardPalette.setColor(QPalette::AlternateBase, blue);
standardPalette.setColor(QPalette::ToolTipBase, pink);
standardPalette.setColor(QPalette::ToolTipText, brightPink);
standardPalette.setColor(QPalette::Text, black);
standardPalette.setColor(QPalette::Button, pink);
standardPalette.setColor(QPalette::ButtonText, black);
standardPalette.setColor(QPalette::Link, black);
standardPalette.setColor(QPalette::Highlight, congoPink);
standardPalette.setColor(QPalette::HighlightedText, black);
standardPalette.setColor(QPalette::Active, QPalette::Button, pink);
standardPalette.setColor(QPalette::Disabled, QPalette::ButtonText, redpinkish);
standardPalette.setColor(QPalette::Disabled, QPalette::WindowText, redpinkish);
standardPalette.setColor(QPalette::Disabled, QPalette::Text, redpinkish);
standardPalette.setColor(QPalette::Disabled, QPalette::Light, gray);
qApp->setPalette(standardPalette);
qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
}
else if (theme == "PCSX2Blue")
{
// Custom palette by RedDevilus, White as main color and Blue as complimentary.
// Alternative light theme.
qApp->setStyle(QStyleFactory::create("Fusion"));
const QColor blackish(35, 35, 35);
const QColor darkBlue(73, 97, 177);
const QColor blue2(80, 120, 200);
const QColor blue(106, 156, 255);
const QColor lightBlue(130, 155, 241);
QPalette standardPalette;
standardPalette.setColor(QPalette::Window, blue2.lighter());
standardPalette.setColor(QPalette::WindowText, blackish);
standardPalette.setColor(QPalette::Base, lightBlue);
standardPalette.setColor(QPalette::AlternateBase, blue2.lighter());
standardPalette.setColor(QPalette::ToolTipBase, blue2);
standardPalette.setColor(QPalette::ToolTipText, Qt::white);
standardPalette.setColor(QPalette::Text, blackish);
standardPalette.setColor(QPalette::Button, blue);
standardPalette.setColor(QPalette::ButtonText, blackish);
standardPalette.setColor(QPalette::Link, darkBlue);
standardPalette.setColor(QPalette::Highlight, Qt::white);
standardPalette.setColor(QPalette::HighlightedText, blackish);
standardPalette.setColor(QPalette::Active, QPalette::Button, blue);
standardPalette.setColor(QPalette::Disabled, QPalette::ButtonText, darkBlue);
standardPalette.setColor(QPalette::Disabled, QPalette::WindowText, darkBlue);
standardPalette.setColor(QPalette::Disabled, QPalette::Text, darkBlue);
standardPalette.setColor(QPalette::Disabled, QPalette::Light, darkBlue);
qApp->setPalette(standardPalette);
qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
}
else if (theme == "ScarletDevilRed")
{
// Custom palette by RedDevilus, Red as main color and Purple as complimentary.
// Alternative dark theme.
qApp->setStyle(QStyleFactory::create("Fusion"));
const QColor darkRed(80, 45, 69);
const QColor purplishRed(120, 45, 69);
const QColor brightRed(200, 45, 69);
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, darkRed);
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, purplishRed);
darkPalette.setColor(QPalette::AlternateBase, darkRed);
darkPalette.setColor(QPalette::ToolTipBase, darkRed);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, purplishRed.darker());
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::Link, brightRed);
darkPalette.setColor(QPalette::Highlight, brightRed);
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::Active, QPalette::Button, purplishRed.darker());
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, brightRed);
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, brightRed);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, brightRed);
darkPalette.setColor(QPalette::Disabled, QPalette::Light, darkRed);
qApp->setPalette(darkPalette);
qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
}
else if (theme == "CobaltSky")
{
// Custom palette by KamFretoZ, A soothing deep royal blue
// that are meant to be easy on the eyes as the main color.
// Alternative dark theme.
qApp->setStyle(QStyleFactory::create("Fusion"));
const QColor gray(192, 192, 192);
const QColor royalBlue(29, 41, 81);
const QColor darkishBlue(17, 30, 108);
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, royalBlue);
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, royalBlue.lighter());
darkPalette.setColor(QPalette::AlternateBase, royalBlue);
darkPalette.setColor(QPalette::ToolTipBase, darkishBlue);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, royalBlue.darker());
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::Link, Qt::white);
darkPalette.setColor(QPalette::Highlight, darkishBlue.lighter());
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::Active, QPalette::Button, darkishBlue);
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Light, gray.darker());
qApp->setPalette(darkPalette);
qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
}
else if (theme == "VioletAngelPurple")
{
// Custom palette by RedDevilus, Blue as main color and Purple as complimentary.
// Alternative dark theme.
qApp->setStyle(QStyleFactory::create("Fusion"));
const QColor blackishblue(50, 25, 70);
const QColor darkerPurple(90, 30, 105);
const QColor nauticalPurple(110, 30, 125);
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, blackishblue);
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, nauticalPurple);
darkPalette.setColor(QPalette::AlternateBase, blackishblue);
darkPalette.setColor(QPalette::ToolTipBase, nauticalPurple);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, nauticalPurple.darker());
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::Link, darkerPurple.lighter());
darkPalette.setColor(QPalette::Highlight, darkerPurple.lighter());
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::Active, QPalette::Button, nauticalPurple.darker());
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, darkerPurple.lighter());
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, darkerPurple.lighter());
darkPalette.setColor(QPalette::Disabled, QPalette::Text, darkerPurple.darker());
darkPalette.setColor(QPalette::Disabled, QPalette::Light, nauticalPurple);
qApp->setPalette(darkPalette);
qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
}
else if (theme == "Ruby")
{
// Custom palette by Daisouji, Black as main color and Red as complimentary.
// Alternative dark (black) theme.
qApp->setStyle(QStyleFactory::create("Fusion"));
const QColor gray(128, 128, 128);
const QColor slate(18, 18, 18);
const QColor rubyish(172, 21, 31);
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, slate);
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, slate.lighter());
darkPalette.setColor(QPalette::AlternateBase, slate.lighter());
darkPalette.setColor(QPalette::ToolTipBase, slate);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, slate);
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::Link, Qt::white);
darkPalette.setColor(QPalette::Highlight, rubyish);
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::Active, QPalette::Button, slate);
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Light, slate.lighter());
qApp->setPalette(darkPalette);
qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
}
else if (theme == "Sapphire")
{
// Custom palette by RedDevilus, Black as main color and Blue as complimentary.
// Alternative dark (black) theme.
qApp->setStyle(QStyleFactory::create("Fusion"));
const QColor gray(128, 128, 128);
const QColor slate(18, 18, 18);
const QColor persianBlue(32, 35, 204);
QPalette darkPalette;
darkPalette.setColor(QPalette::Window, slate);
darkPalette.setColor(QPalette::WindowText, Qt::white);
darkPalette.setColor(QPalette::Base, slate.lighter());
darkPalette.setColor(QPalette::AlternateBase, slate.lighter());
darkPalette.setColor(QPalette::ToolTipBase, slate);
darkPalette.setColor(QPalette::ToolTipText, Qt::white);
darkPalette.setColor(QPalette::Text, Qt::white);
darkPalette.setColor(QPalette::Button, slate);
darkPalette.setColor(QPalette::ButtonText, Qt::white);
darkPalette.setColor(QPalette::Link, Qt::white);
darkPalette.setColor(QPalette::Highlight, persianBlue);
darkPalette.setColor(QPalette::HighlightedText, Qt::white);
darkPalette.setColor(QPalette::Active, QPalette::Button, slate);
darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Text, gray);
darkPalette.setColor(QPalette::Disabled, QPalette::Light, slate.lighter());
qApp->setPalette(darkPalette);
qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
}
else if (theme == "Custom")
{
//Additional Theme option than loads .qss from main PCSX2 Directory
qApp->setStyle(QStyleFactory::create("Fusion"));
QString sheet_content;
QFile sheets(QString::fromStdString(Path::Combine(EmuFolders::DataRoot, "custom.qss")));
if (sheets.open(QFile::ReadOnly))
{
QString sheet_content = QString::fromUtf8(sheets.readAll().data());
qApp->setStyleSheet(sheet_content);
}
else
{
qApp->setStyle(QStyleFactory::create("Fusion"));
}
}
else
{
qApp->setPalette(s_unthemed_palette);
qApp->setStyleSheet(QString());
qApp->setStyle(s_unthemed_style_name);
}
}
void MainWindow::setIconThemeFromStyle()
{
QPalette palette = qApp->palette();
bool dark = palette.windowText().color().value() > palette.window().color().value();
QIcon::setThemeName(dark ? QStringLiteral("white") : QStringLiteral("black"));
}
void MainWindow::onScreenshotActionTriggered()
{
@@ -1013,6 +599,18 @@ void MainWindow::onToolsVideoCaptureToggled(bool checked)
g_emu_thread->beginCapture(path);
}
void MainWindow::onSettingsTriggeredFromToolbar()
{
if (s_vm_valid)
{
m_settings_toolbar_menu->exec(QCursor::pos());
}
else
{
doSettings();
}
}
void MainWindow::saveStateToConfig()
{
if (!isVisible())
@@ -1068,13 +666,13 @@ void MainWindow::restoreStateFromConfig()
}
}
void MainWindow::updateEmulationActions(bool starting, bool running)
void MainWindow::updateEmulationActions(bool starting, bool running, bool stopping)
{
const bool starting_or_running = starting || running;
m_ui.actionStartFile->setDisabled(starting_or_running);
m_ui.actionStartDisc->setDisabled(starting_or_running);
m_ui.actionStartBios->setDisabled(starting_or_running);
m_ui.actionStartFile->setDisabled(starting_or_running || stopping);
m_ui.actionStartDisc->setDisabled(starting_or_running || stopping);
m_ui.actionStartBios->setDisabled(starting_or_running || stopping);
m_ui.actionPowerOff->setEnabled(running);
m_ui.actionPowerOffWithoutSaving->setEnabled(running);
@@ -1091,22 +689,28 @@ void MainWindow::updateEmulationActions(bool starting, bool running)
m_ui.actionToolsVideoCapture->setEnabled(running);
if (!running && m_ui.actionToolsVideoCapture->isChecked())
{
QSignalBlocker sb(m_ui.actionToolsVideoCapture);
m_ui.actionToolsVideoCapture->setChecked(false);
}
m_game_list_widget->setDisabled(starting && !running);
if (!starting && !running)
{
QSignalBlocker sb(m_ui.actionPause);
m_ui.actionPause->setChecked(false);
}
// scanning needs to be disabled while running
m_ui.actionScanForNewGames->setDisabled(starting_or_running);
m_ui.actionRescanAllGames->setDisabled(starting_or_running);
m_ui.actionScanForNewGames->setDisabled(starting_or_running || stopping);
m_ui.actionRescanAllGames->setDisabled(starting_or_running || stopping);
}
void MainWindow::updateDisplayRelatedActions(bool has_surface, bool render_to_main, bool fullscreen)
{
// rendering to main, or switched to gamelist/grid
m_ui.actionViewSystemDisplay->setEnabled((has_surface && render_to_main) || (!has_surface && g_host_display));
m_ui.actionViewSystemDisplay->setEnabled((has_surface && render_to_main) || (!has_surface && GetMTGS().IsOpen()));
m_ui.menuWindowSize->setEnabled(has_surface && !fullscreen);
m_ui.actionFullscreen->setEnabled(has_surface);
@@ -1218,10 +822,10 @@ bool MainWindow::isShowingGameList() const
bool MainWindow::isRenderingFullscreen() const
{
if (!g_host_display || !m_display_widget)
if (!GetMTGS().IsOpen() || !m_display_widget)
return false;
return getDisplayContainer()->isFullScreen() || g_host_display->IsFullscreen();
return getDisplayContainer()->isFullScreen();
}
bool MainWindow::isRenderingToMain() const
@@ -1354,6 +958,14 @@ bool MainWindow::requestShutdown(bool allow_confirm, bool allow_save_to_state, b
if (!isRenderingToMain() && isHidden() && !QtHost::InBatchMode() && !g_emu_thread->isRunningFullscreenUI())
updateWindowState(true);
// Clear the VM valid state early. That way we can't do anything in the UI if we take a while to shut down.
if (s_vm_valid)
{
s_vm_valid = false;
updateEmulationActions(false, false, true);
updateDisplayRelatedActions(false, false, false);
}
// Now we can actually shut down the VM.
g_emu_thread->shutdownVM(save_state);
return true;
@@ -1361,13 +973,16 @@ bool MainWindow::requestShutdown(bool allow_confirm, bool allow_save_to_state, b
void MainWindow::requestExit(bool allow_confirm)
{
// requestShutdown() clears this flag.
const bool vm_was_valid = QtHost::IsVMValid();
// this is block, because otherwise closeEvent() will also prompt
if (!requestShutdown(allow_confirm, true, EmuConfig.SaveStateOnShutdown))
return;
// VM stopped signal won't have fired yet, so queue an exit if we still have one.
// Otherwise, immediately exit, because there's no VM to exit us later.
if (QtHost::IsVMValid())
if (vm_was_valid)
m_is_closing = true;
else
QGuiApplication::quit();
@@ -1467,6 +1082,7 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
});
}
//: Refers to the directory where a game is contained.
action = menu.addAction(tr("Open Containing Directory..."));
connect(action, &QAction::triggered, [this, entry]() {
const QFileInfo fi(QString::fromStdString(entry->path));
@@ -1501,7 +1117,11 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
if (m_ui.menuDebug->menuAction()->isVisible())
{
action = menu.addAction(tr("Boot and Debug"));
connect(action, &QAction::triggered, [this, entry]() { DebugInterface::setPauseOnEntry(true); startGameListEntry(entry); getDebuggerWindow()->show(); });
connect(action, &QAction::triggered, [this, entry]() {
DebugInterface::setPauseOnEntry(true);
startGameListEntry(entry);
getDebuggerWindow()->show();
});
}
menu.addSeparator();
@@ -1765,7 +1385,7 @@ void MainWindow::onToolsCoverDownloaderTriggered()
void MainWindow::updateTheme()
{
updateApplicationTheme();
QtHost::UpdateApplicationTheme();
m_game_list_widget->refreshImages();
}
@@ -1899,7 +1519,7 @@ void MainWindow::onInputRecOpenViewer()
void MainWindow::onVMStarting()
{
s_vm_valid = true;
updateEmulationActions(true, false);
updateEmulationActions(true, false, false);
updateWindowTitle();
// prevent loading state until we're fully initialized
@@ -1910,7 +1530,7 @@ void MainWindow::onVMStarted()
{
s_vm_valid = true;
m_was_disc_change_request = false;
updateEmulationActions(true, true);
updateEmulationActions(true, true, false);
updateWindowTitle();
updateStatusBarWidgetVisibility();
updateInputRecordingActions(true);
@@ -1959,7 +1579,7 @@ void MainWindow::onVMStopped()
s_vm_valid = false;
s_vm_paused = false;
m_last_fps_status = QString();
updateEmulationActions(false, false);
updateEmulationActions(false, false, false);
updateWindowTitle();
updateWindowState();
updateStatusBarWidgetVisibility();
@@ -2040,7 +1660,7 @@ static QString getFilenameFromMimeData(const QMimeData* md)
// only one url accepted
const QList<QUrl> urls(md->urls());
if (urls.size() == 1)
filename = urls.front().toLocalFile();
filename = QDir::toNativeSeparators(urls.front().toLocalFile());
}
return filename;
@@ -2127,80 +1747,29 @@ bool MainWindow::nativeEvent(const QByteArray& eventType, void* message, qintptr
#endif
DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
std::optional<WindowInfo> MainWindow::acquireRenderWindow(bool recreate_window, bool fullscreen, bool render_to_main, bool surfaceless)
{
DevCon.WriteLn("createDisplay(%u, %u)", static_cast<u32>(fullscreen), static_cast<u32>(render_to_main));
if (!g_host_display)
return nullptr;
const std::string fullscreen_mode(Host::GetBaseStringSettingValue("EmuCore/GS", "FullscreenMode", ""));
const bool is_exclusive_fullscreen = (fullscreen && !fullscreen_mode.empty() && g_host_display->SupportsFullscreen());
createDisplayWidget(fullscreen, render_to_main, is_exclusive_fullscreen);
// we need the surface visible.. this might be able to be replaced with something else
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
std::optional<WindowInfo> wi = m_display_widget->getWindowInfo();
if (!wi.has_value())
{
QMessageBox::critical(this, tr("Error"), tr("Failed to get window info from widget"));
destroyDisplayWidget(true);
return nullptr;
}
g_emu_thread->connectDisplaySignals(m_display_widget);
if (!g_host_display->CreateDevice(wi.value(), Host::GetEffectiveVSyncMode()))
{
QMessageBox::critical(this, tr("Error"), tr("Failed to create host display device context."));
destroyDisplayWidget(true);
return nullptr;
}
m_display_created = true;
if (is_exclusive_fullscreen)
setDisplayFullscreen(fullscreen_mode);
updateWindowTitle();
updateWindowState();
m_ui.actionStartFullscreenUI->setEnabled(false);
m_ui.actionStartFullscreenUI2->setEnabled(false);
updateDisplayWidgetCursor();
m_display_widget->setFocus();
g_host_display->DoneCurrent();
return m_display_widget;
}
DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main, bool surfaceless)
{
DevCon.WriteLn("updateDisplay() fullscreen=%s render_to_main=%s surfaceless=%s", fullscreen ? "true" : "false",
render_to_main ? "true" : "false", surfaceless ? "true" : "false");
DevCon.WriteLn("acquireRenderWindow() recreate=%s fullscreen=%s render_to_main=%s surfaceless=%s", recreate_window ? "true" : "false",
fullscreen ? "true" : "false", render_to_main ? "true" : "false", surfaceless ? "true" : "false");
QWidget* container = m_display_container ? static_cast<QWidget*>(m_display_container) : static_cast<QWidget*>(m_display_widget);
const bool is_fullscreen = isRenderingFullscreen();
const bool is_rendering_to_main = isRenderingToMain();
const std::string fullscreen_mode(Host::GetBaseStringSettingValue("EmuCore/GS", "FullscreenMode", ""));
const bool is_exclusive_fullscreen = (fullscreen && !fullscreen_mode.empty() && g_host_display->SupportsFullscreen());
const bool changing_surfaceless = (!m_display_widget != surfaceless);
if (fullscreen == is_fullscreen && is_rendering_to_main == render_to_main && !changing_surfaceless)
return m_display_widget;
if (m_display_created && !recreate_window && fullscreen == is_fullscreen && is_rendering_to_main == render_to_main &&
!changing_surfaceless)
{
return m_display_widget ? m_display_widget->getWindowInfo() : WindowInfo();
}
// Skip recreating the surface if we're just transitioning between fullscreen and windowed with render-to-main off.
// .. except on Wayland, where everything tends to break if you don't recreate.
const bool has_container = (m_display_container != nullptr);
const bool needs_container = DisplayContainer::isNeeded(fullscreen, render_to_main);
if (!is_rendering_to_main && !render_to_main && !is_exclusive_fullscreen && has_container == needs_container && !needs_container &&
!changing_surfaceless)
if (m_display_created && !recreate_window && !is_rendering_to_main && !render_to_main && has_container == needs_container &&
!needs_container && !changing_surfaceless)
{
DevCon.WriteLn("Toggling to %s without recreating surface", (fullscreen ? "fullscreen" : "windowed"));
if (g_host_display->IsFullscreen())
g_host_display->SetFullscreen(false, 0, 0, 0.0f);
// since we don't destroy the display widget, we need to save it here
if (!is_fullscreen && !is_rendering_to_main)
@@ -2221,45 +1790,44 @@ DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main, b
updateWindowState();
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
return m_display_widget;
return m_display_widget->getWindowInfo();
}
g_host_display->DestroySurface();
destroyDisplayWidget(surfaceless);
m_display_created = true;
// if we're going to surfaceless, we're done here
if (surfaceless)
return nullptr;
return WindowInfo();
createDisplayWidget(fullscreen, render_to_main, is_exclusive_fullscreen);
createDisplayWidget(fullscreen, render_to_main);
// we need the surface visible.. this might be able to be replaced with something else
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
std::optional<WindowInfo> wi = m_display_widget->getWindowInfo();
if (!wi.has_value())
{
QMessageBox::critical(this, tr("Error"), tr("Failed to get new window info from widget"));
QMessageBox::critical(this, tr("Error"), tr("Failed to get window info from widget"));
destroyDisplayWidget(true);
return nullptr;
return std::nullopt;
}
g_emu_thread->connectDisplaySignals(m_display_widget);
if (!g_host_display->ChangeWindow(wi.value()))
pxFailRel("Failed to recreate surface on new widget.");
if (is_exclusive_fullscreen)
setDisplayFullscreen(fullscreen_mode);
updateWindowTitle();
updateWindowState();
m_ui.actionStartFullscreenUI->setEnabled(false);
m_ui.actionStartFullscreenUI2->setEnabled(false);
updateDisplayWidgetCursor();
m_display_widget->setFocus();
return m_display_widget;
return wi;
}
void MainWindow::createDisplayWidget(bool fullscreen, bool render_to_main, bool is_exclusive_fullscreen)
void MainWindow::createDisplayWidget(bool fullscreen, bool render_to_main)
{
// If we're rendering to main and were hidden (e.g. coming back from fullscreen),
// make sure we're visible before trying to add ourselves. Otherwise Wayland breaks.
@@ -2301,10 +1869,7 @@ void MainWindow::createDisplayWidget(bool fullscreen, bool render_to_main, bool
restoreDisplayWindowGeometryFromConfig();
}
if (!is_exclusive_fullscreen)
container->showFullScreen();
else
container->showNormal();
container->showFullScreen();
}
else if (!render_to_main)
{
@@ -2365,7 +1930,7 @@ void MainWindow::relativeMouseModeRequested(bool enabled)
updateDisplayWidgetCursor();
}
void MainWindow::destroyDisplay()
void MainWindow::releaseRenderWindow()
{
// Now we can safely destroy the display window.
destroyDisplayWidget(true);
@@ -2485,23 +2050,6 @@ void MainWindow::restoreDisplayWindowGeometryFromConfig()
}
}
void MainWindow::setDisplayFullscreen(const std::string& fullscreen_mode)
{
u32 width, height;
float refresh_rate;
if (HostDisplay::ParseFullscreenMode(fullscreen_mode, &width, &height, &refresh_rate))
{
if (g_host_display->SetFullscreen(true, width, height, refresh_rate))
{
Host::AddOSDMessage("Acquired exclusive fullscreen.", Host::OSD_INFO_DURATION);
}
else
{
Host::AddOSDMessage("Failed to acquire exclusive fullscreen.", Host::OSD_WARNING_DURATION);
}
}
}
SettingsDialog* MainWindow::getSettingsDialog()
{
if (!m_settings_dialog)
@@ -2897,11 +2445,23 @@ void MainWindow::doStartFile(std::optional<CDVD_SourceType> source, const QStrin
void MainWindow::doDiscChange(CDVD_SourceType source, const QString& path)
{
const bool is_gs_dump = VMManager::IsGSDumpFileName(path.toStdString());
if (is_gs_dump != GSDumpReplayer::IsReplayingDump())
{
QMessageBox::critical(this, tr("Error"), tr("Cannot switch from game to GS dump or vice versa."));
return;
}
else if (is_gs_dump)
{
Host::RunOnCPUThread([path = path.toStdString()]() { GSDumpReplayer::ChangeDump(path.c_str()); });
return;
}
bool reset_system = false;
if (!m_was_disc_change_request)
{
QMessageBox message(QMessageBox::Question, tr("Confirm Disc Change"),
tr("Do you want to swap discs or boot the new image (via system reset)?"));
tr("Do you want to swap discs or boot the new image (via system reset)?"), QMessageBox::NoButton, this);
message.addButton(tr("Swap Disc"), QMessageBox::ActionRole);
QPushButton* reset_button = message.addButton(tr("Reset"), QMessageBox::ActionRole);
QPushButton* cancel_button = message.addButton(QMessageBox::Cancel);
@@ -2922,19 +2482,33 @@ void MainWindow::doDiscChange(CDVD_SourceType source, const QString& path)
MainWindow::VMLock MainWindow::pauseAndLockVM()
{
const bool was_fullscreen = isRenderingFullscreen();
// To switch out of fullscreen when displaying a popup, or not to?
// For Windows, with driver's direct scanout, what renders behind tends to be hit and miss.
// We can't draw anything over exclusive fullscreen, so get out of it in that case.
// Wayland's a pain as usual, we need to recreate the window, which means there'll be a brief
// period when there's no window, and Qt might shut us down. So avoid it there.
// On MacOS, it forces a workspace switch, which is kinda jarring.
#ifndef __APPLE__
const bool was_fullscreen = g_emu_thread->isFullscreen() && !s_use_central_widget;
#else
const bool was_fullscreen = false;
#endif
const bool was_paused = s_vm_paused;
// We use surfaceless rather than switching out of fullscreen, because
// we're paused, so we're not going to be rendering anyway.
if (was_fullscreen)
g_emu_thread->setSurfaceless(true);
if (!was_paused)
g_emu_thread->setVMPaused(true);
// We want to parent dialogs to the display widget, except if we were fullscreen,
// since it's going to get destroyed by the surfaceless call above.
QWidget* dialog_parent = was_fullscreen ? static_cast<QWidget*>(this) : getDisplayContainer();
// We need to switch out of exclusive fullscreen before we can display our popup.
// However, we do not want to switch back to render-to-main, the window might have generated this event.
if (was_fullscreen)
{
g_emu_thread->setFullscreen(false, false);
while (QtHost::IsVMValid() && g_emu_thread->isFullscreen())
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 1);
}
// Now we'll either have a borderless window, or a regular window (if we were exclusive fullscreen).
QWidget* dialog_parent = getDisplayContainer();
return VMLock(dialog_parent, was_paused, was_fullscreen);
}
@@ -2964,7 +2538,8 @@ MainWindow::VMLock::VMLock(VMLock&& lock)
MainWindow::VMLock::~VMLock()
{
if (m_was_fullscreen)
g_emu_thread->setSurfaceless(false);
g_emu_thread->setFullscreen(true, true);
if (!m_was_paused)
g_emu_thread->setVMPaused(false);
}
+9 -13
View File
@@ -19,6 +19,7 @@
#include <QtWidgets/QLabel>
#include <QtWidgets/QMainWindow>
#include <QtWidgets/QMenu>
#include <functional>
#include <optional>
@@ -68,7 +69,7 @@ public:
void cancelResume();
private:
VMLock(QWidget* dialog_parent, bool was_paused, bool was_fullscreen);
VMLock(QWidget* dialog_parent, bool was_paused, bool was_exclusive_fullscreen);
friend MainWindow;
QWidget* m_dialog_parent;
@@ -76,9 +77,6 @@ public:
bool m_was_fullscreen;
};
/// Default theme name for the platform.
static const char* DEFAULT_THEME_NAME;
/// Default filter for opening a file.
static const char* OPEN_FILE_FILTER;
@@ -89,9 +87,6 @@ public:
MainWindow();
~MainWindow();
/// Sets application theme according to settings.
static void updateApplicationTheme();
void initialize();
void connectVMThreadSignals(EmuThread* thread);
void startupUpdateCheck();
@@ -127,11 +122,10 @@ public Q_SLOTS:
private Q_SLOTS:
void onUpdateCheckComplete();
DisplayWidget* createDisplay(bool fullscreen, bool render_to_main);
DisplayWidget* updateDisplay(bool fullscreen, bool render_to_main, bool surfaceless);
std::optional<WindowInfo> acquireRenderWindow(bool recreate_window, bool fullscreen, bool render_to_main, bool surfaceless);
void displayResizeRequested(qint32 width, qint32 height);
void relativeMouseModeRequested(bool enabled);
void destroyDisplay();
void releaseRenderWindow();
void focusDisplayWidget();
void onGameListRefreshComplete();
@@ -170,6 +164,7 @@ private Q_SLOTS:
void onBlockDumpActionToggled(bool checked);
void onShowAdvancedSettingsToggled(bool checked);
void onToolsVideoCaptureToggled(bool checked);
void onSettingsTriggeredFromToolbar();
// Input Recording
void onInputRecNewActionTriggered();
@@ -211,7 +206,7 @@ private:
void saveStateToConfig();
void restoreStateFromConfig();
void updateEmulationActions(bool starting, bool running);
void updateEmulationActions(bool starting, bool running, bool stopping);
void updateDisplayRelatedActions(bool has_surface, bool render_to_main, bool fullscreen);
void updateStatusBarWidgetVisibility();
void updateWindowTitle();
@@ -231,10 +226,9 @@ private:
QWidget* getDisplayContainer() const;
void saveDisplayWindowGeometryToConfig();
void restoreDisplayWindowGeometryFromConfig();
void createDisplayWidget(bool fullscreen, bool render_to_main, bool is_exclusive_fullscreen);
void createDisplayWidget(bool fullscreen, bool render_to_main);
void destroyDisplayWidget(bool show_game_list);
void updateDisplayWidgetCursor();
void setDisplayFullscreen(const std::string& fullscreen_mode);
SettingsDialog* getSettingsDialog();
void doSettings(const char* category = nullptr);
@@ -283,6 +277,8 @@ private:
QLabel* m_status_vps_widget = nullptr;
QLabel* m_status_resolution_widget = nullptr;
QMenu* m_settings_toolbar_menu = nullptr;
QString m_current_disc_path;
QString m_current_elf_override;
QString m_current_game_serial;
+38 -9
View File
@@ -79,13 +79,15 @@
<addaction name="menuLoadState"/>
<addaction name="menuSaveState"/>
<addaction name="separator"/>
<addaction name="actionSettings"/>
<addaction name="actionSettings"/> <!-- Please consult with macOS users before removing -->
<addaction name="actionExit"/>
</widget>
<widget class="QMenu" name="menuSettings">
<property name="title">
<string>S&amp;ettings</string>
</property>
<addaction name="actionViewGameProperties"/>
<addaction name="separator"/>
<addaction name="actionInterfaceSettings"/>
<addaction name="actionGameListSettings"/>
<addaction name="actionBIOSSettings"/>
@@ -156,7 +158,6 @@
<addaction name="actionViewGameList"/>
<addaction name="actionViewGameGrid"/>
<addaction name="actionViewSystemDisplay"/>
<addaction name="actionViewGameProperties"/>
<addaction name="separator"/>
<addaction name="actionFullscreen"/>
<addaction name="menuWindowSize"/>
@@ -245,7 +246,7 @@
<addaction name="separator"/>
<addaction name="actionFullscreen"/>
<addaction name="separator"/>
<addaction name="actionSettings"/>
<addaction name="actionSettings2"/>
<addaction name="actionControllerSettings"/>
</widget>
<widget class="QStatusBar" name="statusBar"/>
@@ -437,16 +438,28 @@
<property name="text">
<string>&amp;GitHub Repository...</string>
</property>
<property name="icon">
<iconset theme="github">
<normaloff>.</normaloff>.</iconset>
</property>
</action>
<action name="actionSupportForums">
<property name="text">
<string>Support &amp;Forums...</string>
</property>
<property name="icon">
<iconset theme="at">
<normaloff>.</normaloff>.</iconset>
</property>
</action>
<action name="actionDiscordServer">
<property name="text">
<string>&amp;Discord Server...</string>
</property>
<property name="icon">
<iconset theme="discord">
<normaloff>.</normaloff>.</iconset>
</property>
</action>
<action name="actionCheckForUpdates">
<property name="icon">
@@ -470,6 +483,10 @@
<property name="text">
<string>&amp;About PCSX2...</string>
</property>
<property name="icon">
<iconset resource="resources/resources.qrc">
<normaloff>:/icons/AppIcon.png</normaloff>:/icons/AppIcon.png</iconset>
</property>
</action>
<action name="actionChangeDisc">
<property name="icon">
@@ -522,7 +539,19 @@
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Settings...</string>
<string>&amp;Settings</string>
</property>
<property name="menuRole">
<enum>QAction::PreferencesRole</enum>
</property>
</action>
<action name="actionSettings2">
<property name="icon">
<iconset theme="settings-3-line">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Settings</string>
</property>
<property name="menuRole">
<enum>QAction::PreferencesRole</enum>
@@ -651,7 +680,7 @@
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>System &amp;Display</string>
<string extracomment="This grayed-out at first option will become available while there is a game emulated and the game list is displayed over the actual emulation, to let users display the system emulation once more.">System &amp;Display</string>
</property>
</action>
<action name="actionViewGameProperties">
@@ -774,7 +803,7 @@
<bool>false</bool>
</property>
<property name="text">
<string>New</string>
<string extracomment="This section refers to the Input Recording submenu.">New</string>
</property>
</action>
<action name="actionInputRecPlay">
@@ -782,7 +811,7 @@
<bool>false</bool>
</property>
<property name="text">
<string>Play</string>
<string extracomment="This section refers to the Input Recording submenu.">Play</string>
</property>
</action>
<action name="actionInputRecStop">
@@ -790,7 +819,7 @@
<bool>false</bool>
</property>
<property name="text">
<string>Stop</string>
<string extracomment="This section refers to the Input Recording submenu.">Stop</string>
</property>
</action>
<action name="actionInputRecOpenSettings">
@@ -798,7 +827,7 @@
<bool>false</bool>
</property>
<property name="text">
<string>Settings</string>
<string extracomment="This section refers to the Input Recording submenu.">Settings</string>
</property>
</action>
<action name="actionRecording_Console_Logs">
+47 -119
View File
@@ -41,7 +41,6 @@
#include "pcsx2/GS.h"
#include "pcsx2/GS/GS.h"
#include "pcsx2/GSDumpReplayer.h"
#include "pcsx2/HostDisplay.h"
#include "pcsx2/HostSettings.h"
#include "pcsx2/INISettingsInterface.h"
#include "pcsx2/PAD/Host/PAD.h"
@@ -56,6 +55,7 @@
#include "fmt/core.h"
#include "AutoUpdaterDialog.h"
#include "DisplayWidget.h"
#include "GameList/GameListWidget.h"
#include "MainWindow.h"
@@ -190,12 +190,14 @@ void EmuThread::startFullscreenUI(bool fullscreen)
return;
}
if (VMManager::HasValidVM())
if (VMManager::HasValidVM() || GetMTGS().IsOpen())
return;
// this should just set the flag so it gets automatically started
ImGuiManager::InitializeFullscreenUI();
m_run_fullscreen_ui = true;
if (fullscreen)
m_is_fullscreen = true;
m_is_rendering_to_main = shouldRenderToMain();
m_is_fullscreen = fullscreen;
if (!GetMTGS().WaitForOpen())
{
@@ -215,13 +217,13 @@ void EmuThread::stopFullscreenUI()
QMetaObject::invokeMethod(this, &EmuThread::stopFullscreenUI, Qt::QueuedConnection);
// wait until the host display is gone
while (g_host_display)
while (GetMTGS().IsOpen())
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 1);
return;
}
if (!g_host_display)
if (!GetMTGS().IsOpen())
return;
pxAssertRel(!VMManager::HasValidVM(), "VM is not valid at FSUI shutdown time");
@@ -240,6 +242,7 @@ void EmuThread::startVM(std::shared_ptr<VMBootParameters> boot_params)
pxAssertRel(!VMManager::HasValidVM(), "VM is shut down");
// Determine whether to start fullscreen or not.
m_is_rendering_to_main = shouldRenderToMain();
if (boot_params->fullscreen.has_value())
m_is_fullscreen = boot_params->fullscreen.value();
else
@@ -490,14 +493,14 @@ void EmuThread::toggleFullscreen()
return;
}
setFullscreen(!m_is_fullscreen);
setFullscreen(!m_is_fullscreen, true);
}
void EmuThread::setFullscreen(bool fullscreen)
void EmuThread::setFullscreen(bool fullscreen, bool allow_render_to_main)
{
if (!isOnEmuThread())
{
QMetaObject::invokeMethod(this, "setFullscreen", Qt::QueuedConnection, Q_ARG(bool, fullscreen));
QMetaObject::invokeMethod(this, "setFullscreen", Qt::QueuedConnection, Q_ARG(bool, fullscreen), Q_ARG(bool, allow_render_to_main));
return;
}
@@ -506,11 +509,12 @@ void EmuThread::setFullscreen(bool fullscreen)
// This will call back to us on the MTGS thread.
m_is_fullscreen = fullscreen;
m_is_rendering_to_main = allow_render_to_main && shouldRenderToMain();
GetMTGS().UpdateDisplayWindow();
GetMTGS().WaitGS();
// If we're using exclusive fullscreen, the refresh rate may have changed.
UpdateVSyncRate();
UpdateVSyncRate(true);
}
void EmuThread::setSurfaceless(bool surfaceless)
@@ -589,7 +593,7 @@ void EmuThread::checkForSettingChanges(const Pcsx2Config& old_config)
{
QMetaObject::invokeMethod(g_main_window, &MainWindow::checkForSettingChanges, Qt::QueuedConnection);
if (g_host_display)
if (GetMTGS().IsOpen())
{
const bool render_to_main = shouldRenderToMain();
if (!m_is_fullscreen && m_is_rendering_to_main != render_to_main)
@@ -786,7 +790,7 @@ void EmuThread::connectDisplaySignals(DisplayWidget* widget)
void EmuThread::onDisplayWindowResized(int width, int height, float scale)
{
if (!g_host_display)
if (!GetMTGS().IsOpen())
return;
GetMTGS().ResizeDisplayWindow(width, height, scale);
@@ -795,17 +799,22 @@ void EmuThread::onDisplayWindowResized(int width, int height, float scale)
void EmuThread::onApplicationStateChanged(Qt::ApplicationState state)
{
// NOTE: This is executed on the emu thread, not UI thread.
if (!m_pause_on_focus_loss || !VMManager::HasValidVM())
if (!VMManager::HasValidVM())
return;
const bool focus_loss = (state != Qt::ApplicationActive);
if (focus_loss)
{
if (!m_was_paused_by_focus_loss && VMManager::GetState() == VMState::Running)
if (m_pause_on_focus_loss && !m_was_paused_by_focus_loss && VMManager::GetState() == VMState::Running)
{
m_was_paused_by_focus_loss = true;
VMManager::SetPaused(true);
}
// Clear the state of all keyboard binds.
// That way, if we had a key held down, and lost focus, the bind won't be stuck enabled because we never
// got the key release message, because it happened in another window which "stole" the event.
InputManager::ClearBindStateFromSource(InputManager::MakeHostKeyboardKey(0));
}
else
{
@@ -886,126 +895,38 @@ void EmuThread::endCapture()
GetMTGS().RunOnGSThread(&GSEndCapture);
}
void EmuThread::updateDisplay()
std::optional<WindowInfo> EmuThread::acquireRenderWindow(bool recreate_window)
{
pxAssertRel(!isOnEmuThread(), "Not on emu thread");
// Check if we're wanting to get exclusive fullscreen. This should be safe to read, since we're going to be calling from the GS thread.
m_is_exclusive_fullscreen = m_is_fullscreen && GSWantsExclusiveFullscreen();
const bool window_fullscreen = m_is_fullscreen && !m_is_exclusive_fullscreen;
const bool render_to_main = !m_is_exclusive_fullscreen && !window_fullscreen && m_is_rendering_to_main;
// finished with the display for now
g_host_display->DoneCurrent();
// but we should get it back after this call
onUpdateDisplayRequested(m_is_fullscreen, !m_is_fullscreen && m_is_rendering_to_main, m_is_surfaceless);
if (!g_host_display->MakeCurrent())
{
pxFailRel("Failed to recreate context after updating");
return;
}
return emit onAcquireRenderWindowRequested(recreate_window, window_fullscreen, render_to_main, m_is_surfaceless);
}
bool EmuThread::acquireHostDisplay(RenderAPI api, bool clear_state_on_fail)
void EmuThread::releaseRenderWindow()
{
pxAssertRel(!g_host_display, "Host display does not exist on create");
m_is_rendering_to_main = shouldRenderToMain();
m_is_surfaceless = false;
g_host_display = HostDisplay::CreateForAPI(api);
if (!g_host_display)
return false;
DisplayWidget* widget = emit onCreateDisplayRequested(m_is_fullscreen, m_is_rendering_to_main);
if (!widget)
{
g_host_display.reset();
return false;
}
connectDisplaySignals(widget);
if (!g_host_display->MakeCurrent())
{
Console.Error("Failed to make render context current");
releaseHostDisplay(clear_state_on_fail);
return false;
}
if (!g_host_display->SetupDevice() || !ImGuiManager::Initialize())
{
Console.Error("Failed to initialize device/imgui");
releaseHostDisplay(clear_state_on_fail);
return false;
}
Console.WriteLn(Color_StrongGreen, "%s Graphics Driver Info:", HostDisplay::RenderAPIToString(g_host_display->GetRenderAPI()));
Console.Indent().WriteLn(g_host_display->GetDriverInfo());
if (m_run_fullscreen_ui && !ImGuiManager::InitializeFullscreenUI())
{
Console.Error("Failed to initialize fullscreen UI");
releaseHostDisplay(clear_state_on_fail);
m_run_fullscreen_ui = false;
return false;
}
return true;
emit onReleaseRenderWindowRequested();
}
void EmuThread::releaseHostDisplay(bool clear_state)
std::optional<WindowInfo> Host::AcquireRenderWindow(bool recreate_window)
{
ImGuiManager::Shutdown(clear_state);
g_host_display.reset();
emit onDestroyDisplayRequested();
return g_emu_thread->acquireRenderWindow(recreate_window);
}
bool Host::AcquireHostDisplay(RenderAPI api, bool clear_state_on_fail)
void Host::ReleaseRenderWindow()
{
return g_emu_thread->acquireHostDisplay(api, clear_state_on_fail);
return g_emu_thread->releaseRenderWindow();
}
void Host::ReleaseHostDisplay(bool clear_state)
void Host::BeginPresentFrame()
{
g_emu_thread->releaseHostDisplay(clear_state);
}
HostDisplay::PresentResult Host::BeginPresentFrame(bool frame_skip)
{
const HostDisplay::PresentResult result = g_host_display->BeginPresent(frame_skip);
if (result != HostDisplay::PresentResult::OK)
{
// if we're skipping a frame, we need to reset imgui's state, since
// we won't be calling EndPresentFrame().
ImGuiManager::SkipFrame();
}
return result;
}
void Host::EndPresentFrame()
{
if (GSDumpReplayer::IsReplayingDump())
GSDumpReplayer::RenderUI();
FullscreenUI::Render();
ImGuiManager::RenderOSD();
g_host_display->EndPresent();
ImGuiManager::NewFrame();
}
void Host::ResizeHostDisplay(u32 new_window_width, u32 new_window_height, float new_window_scale)
{
g_host_display->ResizeWindow(new_window_width, new_window_height, new_window_scale);
ImGuiManager::WindowResized();
}
void Host::RequestResizeHostDisplay(s32 width, s32 height)
{
g_emu_thread->onResizeDisplayRequested(width, height);
}
void Host::UpdateHostDisplay()
{
g_emu_thread->updateDisplay();
ImGuiManager::WindowResized();
g_emu_thread->onResizeRenderWindowRequested(width, height);
}
void Host::OnVMStarting()
@@ -1267,7 +1188,7 @@ bool Host::IsFullscreen()
void Host::SetFullscreen(bool enabled)
{
g_emu_thread->setFullscreen(enabled);
g_emu_thread->setFullscreen(enabled, true);
}
alignas(16) static SysMtgsThread s_mtgs_thread;
@@ -1323,7 +1244,7 @@ void Host::SetDefaultUISettings(SettingsInterface& si)
si.SetBoolValue("UI", "RenderToSeparateWindow", false);
si.SetBoolValue("UI", "HideMainWindowWhenRunning", false);
si.SetBoolValue("UI", "DisableWindowResize", false);
si.SetStringValue("UI", "Theme", MainWindow::DEFAULT_THEME_NAME);
si.SetStringValue("UI", "Theme", QtHost::GetDefaultThemeName());
}
void QtHost::SaveSettings()
@@ -1750,6 +1671,13 @@ bool QtHost::ParseCommandLineOptions(const QStringList& args, std::shared_ptr<VM
s_boot_and_debug = true;
continue;
}
else if (CHECK_ARG(QStringLiteral("-updatecleanup")))
{
if (AutoUpdaterDialog::isSupported())
AutoUpdaterDialog::cleanupAfterUpdate();
continue;
}
#ifdef ENABLE_RAINTEGRATION
else if (CHECK_ARG(QStringLiteral("-raintegration")))
{
@@ -1863,7 +1791,7 @@ int main(int argc, char* argv[])
return EXIT_SUCCESS;
// Set theme before creating any windows.
MainWindow::updateApplicationTheme();
QtHost::UpdateApplicationTheme();
MainWindow* main_window = new MainWindow();
// Start up the CPU thread.
+14 -9
View File
@@ -21,7 +21,6 @@
#include <optional>
#include "pcsx2/Host.h"
#include "pcsx2/HostDisplay.h"
#include "pcsx2/HostSettings.h"
#include "pcsx2/Frontend/InputManager.h"
#include "pcsx2/VMManager.h"
@@ -62,6 +61,7 @@ public:
__fi QEventLoop* getEventLoop() const { return m_event_loop; }
__fi bool isFullscreen() const { return m_is_fullscreen; }
__fi bool isExclusiveFullscreen() const { return m_is_exclusive_fullscreen; }
__fi bool isRenderingToMain() const { return m_is_rendering_to_main; }
__fi bool isSurfaceless() const { return m_is_surfaceless; }
__fi bool isRunningFullscreenUI() const { return m_run_fullscreen_ui; }
@@ -70,10 +70,9 @@ public:
bool shouldRenderToMain() const;
/// Called back from the GS thread when the display state changes (e.g. fullscreen, render to main).
bool acquireHostDisplay(RenderAPI api, bool clear_state_on_fail);
std::optional<WindowInfo> acquireRenderWindow(bool recreate_window);
void connectDisplaySignals(DisplayWidget* widget);
void releaseHostDisplay(bool clear_state);
void updateDisplay();
void releaseRenderWindow();
void startBackgroundControllerPollTimer();
void stopBackgroundControllerPollTimer();
@@ -94,7 +93,7 @@ public Q_SLOTS:
void saveState(const QString& filename);
void saveStateToSlot(qint32 slot);
void toggleFullscreen();
void setFullscreen(bool fullscreen);
void setFullscreen(bool fullscreen, bool allow_render_to_main);
void setSurfaceless(bool surfaceless);
void applySettings();
void reloadGameSettings();
@@ -118,10 +117,9 @@ public Q_SLOTS:
Q_SIGNALS:
bool messageConfirmed(const QString& title, const QString& message);
DisplayWidget* onCreateDisplayRequested(bool fullscreen, bool render_to_main);
DisplayWidget* onUpdateDisplayRequested(bool fullscreen, bool render_to_main, bool surfaceless);
void onResizeDisplayRequested(qint32 width, qint32 height);
void onDestroyDisplayRequested();
std::optional<WindowInfo> onAcquireRenderWindowRequested(bool recreate_window, bool fullscreen, bool render_to_main, bool surfaceless);
void onResizeRenderWindowRequested(qint32 width, qint32 height);
void onReleaseRenderWindowRequested();
void onRelativeMouseModeRequested(bool enabled);
/// Called when the VM is starting initialization, but has not been completed yet.
@@ -196,6 +194,7 @@ private:
bool m_run_fullscreen_ui = false;
bool m_is_rendering_to_main = false;
bool m_is_fullscreen = false;
bool m_is_exclusive_fullscreen = false;
bool m_is_surfaceless = false;
bool m_save_state_on_shutdown = false;
bool m_pause_on_focus_loss = false;
@@ -214,6 +213,12 @@ extern EmuThread* g_emu_thread;
namespace QtHost
{
/// Default theme name for the platform.
const char* GetDefaultThemeName();
/// Sets application theme according to settings.
void UpdateApplicationTheme();
/// Sets batch mode (exit after game shutdown).
bool InBatchMode();
+3
View File
@@ -124,7 +124,9 @@ namespace SettingWidgetBinder
static void setBoolValue(QComboBox* widget, bool value) { widget->setCurrentIndex(value ? 1 : 0); }
static void makeNullableBool(QComboBox* widget, bool globalValue)
{
//: THIS STRING IS SHARED ACROSS MULTIPLE OPTIONS. Be wary about gender/number. Also, ignore Crowdin's warning regarding [Enabled]: the text must be translated.
widget->insertItem(0, globalValue ? qApp->translate("SettingsDialog", "Use Global Setting [Enabled]") :
//: THIS STRING IS SHARED ACROSS MULTIPLE OPTIONS. Be wary about gender/number. Also, ignore Crowdin's warning regarding [Disabled]: the text must be translated.
qApp->translate("SettingsDialog", "Use Global Setting [Disabled]"));
}
@@ -1045,6 +1047,7 @@ namespace SettingWidgetBinder
{
QObject::connect(browse_button, &QAbstractButton::clicked, browse_button, [widget, key]() {
const QString path(QDir::toNativeSeparators(QFileDialog::getExistingDirectory(QtUtils::GetRootWidget(widget),
//It seems that the latter half should show the types of folders that can be selected within Settings -> Folders, but right now it's broken. It would be best for localization purposes to duplicate this into multiple lines, each per type of folder.
qApp->translate("SettingWidgetBinder", "Select folder for %1").arg(QString::fromStdString(key)))));
if (path.isEmpty())
return;
@@ -56,8 +56,8 @@ AchievementSettingsWidget::AchievementSettingsWidget(SettingsDialog* dialog, QWi
dialog->registerWidgetHelp(m_ui.unofficialTestMode, tr("Test Unofficial Achievements"), tr("Unchecked"),
tr("When enabled, PCSX2 will list achievements from unofficial sets. Please note that these achievements are "
"not tracked by RetroAchievements, so they unlock every time."));
dialog->registerWidgetHelp(m_ui.richPresence, tr("Enable Rich Presence"), tr("Unchecked"),
tr("When enabled, rich presence information will be collected and sent to the server where supported."));
dialog->registerWidgetHelp(m_ui.richPresence, tr("Enable RA's Rich Presence"), tr("Unchecked"),
tr("When enabled, rich presence information will be collected and sent to the RetroAchievements servers where supported."));
dialog->registerWidgetHelp(m_ui.challengeMode, tr("Enable Hardcore Mode"), tr("Unchecked"),
tr("\"Challenge\" mode for achievements, including leaderboard tracking. Disables save state, cheats, and slowdown functions."));
dialog->registerWidgetHelp(m_ui.leaderboards, tr("Enable Leaderboards"), tr("Checked"),
@@ -149,6 +149,7 @@ void AchievementSettingsWidget::updateLoginState()
const u64 login_unix_timestamp =
StringUtil::FromChars<u64>(Host::GetBaseStringSettingValue("Achievements", "LoginTimestamp", "0")).value_or(0);
const QDateTime login_timestamp(QDateTime::fromSecsSinceEpoch(static_cast<qint64>(login_unix_timestamp)));
//: Variable %1 is an username, variable %2 is a timestamp.
m_ui.loginStatus->setText(tr("Username: %1\nLogin token generated on %2.")
.arg(QString::fromStdString(username))
.arg(login_timestamp.toString(Qt::TextDate)));
@@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
<string notr="true">Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
@@ -49,7 +49,7 @@
<item row="0" column="1">
<widget class="QCheckBox" name="richPresence">
<property name="text">
<string>Enable Rich Presence</string>
<string extracomment="This &quot;Rich Presence&quot; is not Discord's, but rather RetroAchivements own system.">Enable RA's Rich Presence</string>
</property>
</widget>
</item>
+11 -5
View File
@@ -74,15 +74,18 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsDialog* dialog, QWidget*
dialog->registerWidgetHelp(m_ui.eeRecompiler, tr("Enable Recompiler"), tr("Checked"),
tr("Performs just-in-time binary translation of 64-bit MIPS-IV machine code to x86."));
//: Wait loop: When the game makes the CPU do nothing (loop/spin) while it waits for something to happen (usually an interrupt).
dialog->registerWidgetHelp(m_ui.eeWaitLoopDetection, tr("Wait Loop Detection"), tr("Checked"),
tr("Moderate speedup for some games, with no known side effects."));
dialog->registerWidgetHelp(m_ui.eeCache, tr("Enable Cache (Slow)"), tr("Unchecked"), tr("Interpreter only, provided for diagnostic."));
//: INTC = Name of a PS2 register, leave as-is. "spin" = to make a cpu (or gpu) actively do nothing while you wait for something. Like spinning in a circle, you're moving but not actually going anywhere.
dialog->registerWidgetHelp(m_ui.eeINTCSpinDetection, tr("INTC Spin Detection"), tr("Checked"),
tr("Huge speedup for some games, with almost no compatibility side effects."));
dialog->registerWidgetHelp(m_ui.eeFastmem, tr("Enable Fast Memory Access"), tr("Checked"),
//: "Backpatching" = To edit previously generated code to change what it does (in this case, we generate direct memory accesses, then backpatch them to jump to a fancier handler function when we realize they need the fancier handler function)
tr("Uses backpatching to avoid register flushing on every memory access."));
dialog->registerWidgetHelp(m_ui.pauseOnTLBMiss, tr("Pause On TLB Miss"), tr("Unchecked"),
@@ -90,24 +93,27 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsDialog* dialog, QWidget*
"end of the block, not on the instruction which caused the exception. Refer to the console to see the address where the invalid "
"access occurred."));
dialog->registerWidgetHelp(m_ui.vu0RoundingMode, tr("Rounding Mode"), tr("Chop / Zero (Default)"), tr(""));
dialog->registerWidgetHelp(m_ui.vu1RoundingMode, tr("Rounding Mode"), tr("Chop / Zero (Default)"), tr(""));
dialog->registerWidgetHelp(m_ui.vu0RoundingMode, tr("VU0 Rounding Mode"), tr("Chop / Zero (Default)"), tr(""));
dialog->registerWidgetHelp(m_ui.vu1RoundingMode, tr("VU1 Rounding Mode"), tr("Chop / Zero (Default)"), tr(""));
dialog->registerWidgetHelp(m_ui.vu0ClampMode, tr("Clamping Mode"), tr("Normal (Default)"), tr(""));
dialog->registerWidgetHelp(m_ui.vu1ClampMode, tr("Clamping Mode"), tr("Normal (Default)"), tr(""));
dialog->registerWidgetHelp(m_ui.vu0ClampMode, tr("VU0 Clamping Mode"), tr("Normal (Default)"), tr(""));
dialog->registerWidgetHelp(m_ui.vu1ClampMode, tr("VU1 Clamping Mode"), tr("Normal (Default)"), tr(""));
//: VU0 = Vector Unit 0. One of the PS2's processors.
dialog->registerWidgetHelp(m_ui.vu0Recompiler, tr("Enable VU0 Recompiler (Micro Mode)"), tr("Checked"), tr("Enables VU0 Recompiler."));
//: VU1 = Vector Unit 1. One of the PS2's processors.
dialog->registerWidgetHelp(m_ui.vu1Recompiler, tr("Enable VU1 Recompiler"), tr("Checked"), tr("Enables VU1 Recompiler."));
dialog->registerWidgetHelp(
//: mVU = PCSX2's recompiler for VU (Vector Unit) code (full name: microVU)
m_ui.vuFlagHack, tr("mVU Flag Hack"), tr("Checked"), tr("Good speedup and high compatibility, may cause graphical errors."));
dialog->registerWidgetHelp(m_ui.iopRecompiler, tr("Enable Recompiler"), tr("Checked"),
tr("Performs just-in-time binary translation of 32-bit MIPS-I machine code to x86."));
dialog->registerWidgetHelp(m_ui.gameFixes, tr("Enable Game Fixes"), tr("Checked"),
tr("Automatically loads and applies gamefixes to known problematic games on game start."));
tr("Automatically loads and applies fixes to known problematic games on game start."));
dialog->registerWidgetHelp(m_ui.patches, tr("Enable Compatibility Patches"), tr("Checked"),
tr("Automatically loads and applies compatibility patches to known problematic games."));

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