Compare commits

...

85 commits

Author SHA1 Message Date
elad335
8437a5f5ac PPU Debugger/Memory: STDCX/STWCX breakpoints, make vm::_ref const
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-19 16:14:00 +03:00
kd-11
564c903fbd rsx: Fix arm64 build
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-19 01:04:00 +03:00
kd-11
268de3cd24 rsx/vk: Retire the concept of heap being in "critical" state
- We waste a lot of time trying to manage that. We just swap out the buffer anyway as long as the client has enough RAM.
- This was more of an issue in early days when corrupt allocation requests were common trying to take gigabytes in one draw.
2025-04-19 01:04:00 +03:00
kd-11
d20f48f876 vk: Fix extension wrangling 2025-04-19 01:04:00 +03:00
kd-11
88e2a3761c vk: Rework multi-heap health checks for performance 2025-04-19 01:04:00 +03:00
kd-11
e136c2eadf vk: Rework heap checks to be explicit 2025-04-19 01:04:00 +03:00
kd-11
b2b50f5e82 vk: Optimize heap check iterator
- Significant boost in some scenarios
2025-04-19 01:04:00 +03:00
kd-11
26a7e9653f rsx: Optimize static heap allocations 2025-04-19 01:04:00 +03:00
kd-11
76948b6364 vk: Use robin_hood for renderpass caches 2025-04-19 01:04:00 +03:00
kd-11
0f57624a61 vk: Rework extension wrangling 2025-04-19 01:04:00 +03:00
kd-11
8aaf2f8577 vk: Implement EXT_multi_draw support 2025-04-19 01:04:00 +03:00
kd-11
8ce8410a5b vk: Use garbage collector to handle buffer views
- Legacy stuff left over from almost a decade ago
2025-04-19 01:04:00 +03:00
kd-11
a0ce9e52fa vk: Refactor the heap manager 2025-04-19 01:04:00 +03:00
kd-11
53288309a5 vk: Add automatic heap management 2025-04-19 01:04:00 +03:00
Nick Renieris
275f7e15c0 PPU: Fix memory write breakpoints for 13 instructions
Specifically: `STVX`, `STVXL`, `STDBRX`, `STWBRX`, `STFSX`, `STFSUX`, `STFDX`, `STFDUX`, `STHBRX`, `STFS`, `STFSU`, `STFD`, `STFDU`.

Closes https://github.com/RPCS3/rpcs3/issues/17062.
2025-04-18 20:52:37 +02:00
elad335
7de2869a53 Implement sys_spu_image_open_by_fd
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-18 13:53:50 +03:00
elad335
ab7a1a6ec4 sys_spu: Fix sys_spu_image_open 2025-04-18 13:53:50 +03:00
Antonino Di Guardo
b8d1d7cdf1
Fix game list update for auto-detection VFS games folder (#17051)
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-17 12:14:54 +02:00
Megamouse
8b2b74c34b Qt: Add checkboxes to vfs list to make selection more user friendly
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-17 07:23:36 +02:00
Ani
a004ebfffb git: Remove unused code
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-16 13:36:56 +03:00
Megamouse
b51d6e9d92 Qt: use image_change_callback function to ensure the member is valid
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-16 03:19:15 +02:00
Megamouse
b96e41285c Qt: use unique_ptr in qt_video_source 2025-04-16 03:19:15 +02:00
Megamouse
9295e6f5c8 Qt: Fix gamelist icon after stopping a movie
Do not set an icon if it's null. This happens because we save memory
by clearing the pixmap of non-movie items.
Also don't stop the movie here, as it should be stopped already anyway.
2025-04-16 03:19:15 +02:00
Megamouse
e80809f629 Qt: fix game list image reset after a movie was stopped
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-15 18:47:54 +02:00
elad335
5ac4db752d sceNpTrophy: Send signals asynchronously
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-14 15:08:01 +03:00
Megamouse
746b438500 Qt/input: accumulate button presses between gui refresh
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
Fixes dropped input between gui refreshes
2025-04-14 09:31:52 +02:00
Fredrik Hubinette
0964c0356b Add Menu Key (used by 8bitdo Pro 2 controller 2025-04-14 07:36:17 +02:00
kd-11
7500d16524 rsx: Avoid reallocating scratch buffers every draw call when processing instancing data
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-14 03:16:37 +03:00
kd-11
b3bdff741c rsx: Fix simple_array<T>::erase_if 2025-04-14 03:16:37 +03:00
Megamouse
fcb6bc70f8 evdev: log positive axis config
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-13 11:40:01 +02:00
Megamouse
9c5b3a2300 Update to Qt 6.9.0
Some checks failed
Generate Translation Template / Generate Translation Template (push) Has been cancelled
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Has been cancelled
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Has been cancelled
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Has been cancelled
Build RPCS3 / RPCS3 Windows (push) Has been cancelled
2025-04-11 23:11:38 +02:00
kd-11
2d7ffaf07f vk: Fix typo in NVIDIA-specific stencil unresolve path
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-11 14:05:28 +03:00
Megamouse
9b7d5cd1a9 Qt: fix visibility check of table widget items
Some checks failed
Generate Translation Template / Generate Translation Template (push) Has been cancelled
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Has been cancelled
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Has been cancelled
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Has been cancelled
Build RPCS3 / RPCS3 Windows (push) Has been cancelled
2025-04-10 02:23:16 +02:00
RipleyTom
bcb5041df2 use fixed uruntime version 2025-04-10 00:22:04 +02:00
Escary
235707278f
reduce appimage size
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-09 21:17:16 +02:00
Ani
db85595124 rsx: Replace robin_hood with ankerl::unordered_dense 2025-04-09 20:55:35 +02:00
Ani
15758171f0 glext: Update from 2022.05.30 to 2025.02.03 2025-04-09 20:19:42 +02:00
kd-11
d08610882a rsx: Remove superfluous log
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
- Back-to-back range with no barrier will already be logged in draw_call::append
2025-04-09 16:17:51 +03:00
kd-11
21434c471b rsx: Track command barrier types during recording for faster instancing compatibility checks 2025-04-09 16:17:51 +03:00
elad335
87d8bebd0d PPU LLVM: Fixup MTFSF
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-08 11:29:06 +03:00
Ani
e4d84e2c1c Qt: Fix multi package install dialog on Linux 2025-04-08 09:28:10 +02:00
Ani
16036e0419 ppu: Remove redundant checks on MTFSF
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
Closes #11176
2025-04-08 07:04:37 +02:00
Ani
58714d8c68 docker: Update ffmpeg to 7.1.1 2025-04-08 06:43:28 +02:00
Megamouse
ddf684c4d2 Update curl to 8.13.0
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-07 21:37:59 +02:00
Megamouse
daa76be77e Update soundtouch to 2.4.0 2025-04-07 21:37:59 +02:00
Megamouse
600e460416 Fix compilation with newer Qt 2025-04-07 21:37:59 +02:00
Megamouse
e095904e1b cellMic: Use full device name registration and comparison 2025-04-07 20:38:59 +02:00
Megamouse
599d5c17a0 cellMic: Try to open device with different sample rates 2025-04-07 20:38:59 +02:00
elad335
6f98b8c5ae Silence sys_spu_thread_write_spu_mb 2025-04-07 17:54:27 +03:00
elad335
eb2eb9ccf5 Improve lwmutex_lock error logging 2025-04-07 17:54:27 +03:00
elad335
19d01835d3 sys_spu: Fix HW schedular limits 2025-04-07 17:54:27 +03:00
kd-11
f38a61bdb3 Try msvc workaround
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-07 00:46:09 +03:00
kd-11
ed280cdbfe vk: Use dynamic constant buffer offset via push constant 2025-04-07 00:46:09 +03:00
kd-11
66909168ac vk: Silence compiler warning 2025-04-07 00:46:09 +03:00
kd-11
38a1c8becb vk: Use dynamic constants offset for transform constants 2025-04-07 00:46:09 +03:00
kd-11
1816a1eb34 vk: Switch transform constants from UBO to SSBO 2025-04-07 00:46:09 +03:00
kd-11
dad9a2b916 vk: Add support for dynamic buffer offsets 2025-04-07 00:46:09 +03:00
Ani
b3bbd939e3 appimage: Do not bundle libQt6OpenGL
Some checks are pending
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-06 19:37:36 +02:00
Ani
cc84ebf8c2 appimage: Do not bundle Qt6VirtualKeyboard 2025-04-06 19:37:36 +02:00
Ani
2438e975e7 appimage: Do not bundle unused Qt6 libraries 2025-04-06 19:37:36 +02:00
elad335
04d833d3e6 Fix #17000
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-06 08:58:24 +03:00
elad335
2f872b3755 vm.cpp: Remove redundant cache hint 2025-04-06 08:58:24 +03:00
elad335
bd1f5ff194 PPU LLVM: Fix VMAXFP, VMINFP 2025-04-06 08:58:24 +03:00
Ani
613212f9e1 .github: Remove outdated pull request template
Some checks failed
Generate Translation Template / Generate Translation Template (push) Has been cancelled
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Has been cancelled
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Has been cancelled
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Has been cancelled
Build RPCS3 / RPCS3 Windows (push) Has been cancelled
2025-04-04 23:10:21 +02:00
Ani
4aff4a9c82 README: Update VC_redist from 2019 to 2022 2025-04-04 23:10:21 +02:00
Ani
264af550d5 .github: Update log path in issue templates 2025-04-04 23:10:21 +02:00
Ani
822546bf7d Discord: Use vanity URL 2025-04-04 23:10:21 +02:00
nastys
2ac2439c33 Fix macOS SDK path
Some checks are pending
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-04 05:38:48 +02:00
Megamouse
37dbd77628 Update FAudio to 25.04
Some checks are pending
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-03 07:59:49 +02:00
Megamouse
733ceada5e Update SDL to 3.2.10 2025-04-03 07:59:49 +02:00
Megamouse
847f92956f Qt: remove discontinued QWinTaskbar code
Some checks failed
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
Generate Translation Template / Generate Translation Template (push) Has been cancelled
Also remove some strange relics from the includes
2025-04-02 10:48:09 +02:00
Megamouse
73f2aaf9d8 Windows: fix updating with unicode user name
Some checks are pending
Generate Translation Template / Generate Translation Template (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-01 14:31:21 +02:00
Zion Nimchuk
c86a250795 Fix mac build with cmake 4.0
Some checks are pending
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
2025-04-01 09:02:27 +03:00
Zion Nimchuk
c6170aa4c7 Update Windows ccache version 2025-04-01 09:02:27 +03:00
Zion Nimchuk
89ae495c36 Update docker cmake to 3.28 and update minimum to 3.28, as well as remove uneeded minimum 2025-04-01 09:02:27 +03:00
Megamouse
5526c33d69 Review fixes + warning fixes
Some checks failed
Build RPCS3 / RPCS3 Linux ubuntu-24.04 gcc (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04-arm clang (push) Waiting to run
Build RPCS3 / RPCS3 Linux ubuntu-24.04 clang (push) Waiting to run
Build RPCS3 / RPCS3 Windows (push) Waiting to run
Generate Translation Template / Generate Translation Template (push) Has been cancelled
2025-03-31 18:27:54 +02:00
Megamouse
e816636676 overlays: play ICON1.PAM in save data list if possible 2025-03-31 18:27:54 +02:00
Megamouse
40e8bc530c overlays: propagate item selection to children 2025-03-31 18:27:54 +02:00
Megamouse
9684467dc0 overlays: implement video overlay class 2025-03-31 18:27:54 +02:00
Megamouse
8e83fd7d50 Qt/overlays: expose qt_video_source_wrapper as emu callback 2025-03-31 18:27:54 +02:00
Megamouse
fac1cc57d7 Overlays: set layouts dirty if children are dirty
This fixes updates of widget items in lists.
Only set text dirty if it changed.
Properly mark spacers as compiled.
2025-03-31 18:27:54 +02:00
Megamouse
6511e0f3e6 cellSaveData: properly initialize SaveDataEntry 2025-03-31 12:21:40 +02:00
Megamouse
9c1c932e68 Update OpenAL to 1.24.3 2025-03-31 12:01:55 +02:00
Megamouse
82c85c1a9c Qt: disable shortcuts completely if disable kb hotkeys is enabled 2025-03-31 11:41:11 +02:00
Megamouse
7cec2d0e18 Qt: set audio hotkey defaults to additionally need Ctrl pressed 2025-03-31 11:41:11 +02:00
174 changed files with 4401 additions and 18125 deletions

View file

@ -72,13 +72,13 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then
git clone https://github.com/engnr/qt-downloader.git
cd qt-downloader
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
# nested Qt 6.8.3 URL workaround
# nested Qt 6.9.0 URL workaround
# sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
# sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
cd "/tmp/Qt"
"$BREW_X64_PATH/bin/pipenv" run pip3 install py7zr requests semantic_version lxml
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
# sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.8.3 workaround
# sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.9.0 workaround
"$BREW_X64_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64"
fi
@ -145,6 +145,8 @@ export MACOSX_DEPLOYMENT_TARGET=14.0
-DCMAKE_SYSTEM_PROCESSOR=arm64 \
-DCMAKE_TOOLCHAIN_FILE=buildfiles/cmake/TCDarwinARM64.cmake \
-DCMAKE_CXX_FLAGS="-D__MAC_OS_X_VERSION_MIN_REQUIRED=140000" \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
-DCMAKE_OSX_SYSROOT="$(xcrun --sdk macosx --show-sdk-path)" \
-G Ninja
"$BREW_PATH/bin/ninja"; build_status=$?;

View file

@ -39,13 +39,13 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then
git clone https://github.com/engnr/qt-downloader.git
cd qt-downloader
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
# nested Qt 6.8.3 URL workaround
# nested Qt 6.9.0 URL workaround
# sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
# sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
cd "/tmp/Qt"
"$BREW_X64_PATH/bin/pipenv" run pip3 install py7zr requests semantic_version lxml
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
# sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.8.3 workaround
# sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.9.0 workaround
"$BREW_X64_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64"
fi
@ -108,6 +108,8 @@ export MACOSX_DEPLOYMENT_TARGET=14.0
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
-DCMAKE_IGNORE_PATH="$BREW_PATH/lib" \
-DCMAKE_CXX_FLAGS="-D__MAC_OS_X_VERSION_MIN_REQUIRED=140000" \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
-DCMAKE_OSX_SYSROOT="$(xcrun --sdk macosx --show-sdk-path)" \
-G Ninja
"$BREW_PATH/bin/ninja"; build_status=$?;

View file

@ -25,11 +25,20 @@ if [ "$DEPLOY_APPIMAGE" = "true" ]; then
# Remove libvulkan because it causes issues with gamescope
rm -f ./AppDir/usr/lib/libvulkan.so*
# Remove unused Qt6 libraries
rm -f ./AppDir/usr/lib/libQt6OpenGL.so*
rm -f ./AppDir/usr/lib/libQt6Qml*.so*
rm -f ./AppDir/usr/lib/libQt6Quick.so*
rm -f ./AppDir/usr/lib/libQt6VirtualKeyboard.so*
rm -f ./AppDir/usr/plugins/platforminputcontexts/libqtvirtualkeyboardplugin.so*
# Remove git directory containing local commit history file
rm -rf ./AppDir/usr/share/rpcs3/git
linuxdeploy --appimage-extract
./squashfs-root/plugins/linuxdeploy-plugin-appimage/usr/bin/appimagetool AppDir -g
curl -fsSLo /uruntime "https://github.com/VHSgunzo/uruntime/releases/download/v0.3.4/uruntime-appimage-dwarfs-$CPU_ARCH"
chmod +x /uruntime
/uruntime --appimage-mkdwarfs -f --set-owner 0 --set-group 0 --no-history --no-create-timestamp \
--compression zstd:level=22 -S26 -B32 --header /uruntime -i AppDir -o RPCS3.AppImage
APPIMAGE_SUFFIX="linux_${CPU_ARCH}"
if [ "$CPU_ARCH" = "x86_64" ]; then

View file

@ -8,7 +8,6 @@ ARTIFACT_DIR="$BUILD_ARTIFACTSTAGINGDIRECTORY"
# Remove unecessary files
rm -f ./bin/rpcs3.exp ./bin/rpcs3.lib ./bin/rpcs3.pdb ./bin/vc_redist.x64.exe
rm -rf ./bin/git
# Prepare compatibility and SDL database for packaging
mkdir ./bin/config

View file

@ -22,7 +22,7 @@ QT_SVG_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qtsvg${QT_SUFFIX}"
LLVMLIBS_URL="https://github.com/RPCS3/llvm-mirror/releases/download/custom-build-win-${LLVM_VER}/llvmlibs_mt.7z"
GLSLANG_URL='https://github.com/RPCS3/glslang/releases/latest/download/glslanglibs_mt.7z'
VULKAN_SDK_URL="https://www.dropbox.com/scl/fi/sjjh0fc4ld281pjbl2xzu/VulkanSDK-${VULKAN_VER}-Installer.exe?rlkey=f6wzc0lvms5vwkt2z3qabfv9d&dl=1"
CCACHE_URL="https://github.com/ccache/ccache/releases/download/v4.10.2/ccache-4.10.2-windows-x86_64.zip"
CCACHE_URL="https://github.com/ccache/ccache/releases/download/v4.11.2/ccache-4.11.2-windows-x86_64.zip"
DEP_URLS=" \
$QT_BASE_URL \

View file

@ -7,7 +7,7 @@ env:
BUILD_SOURCEBRANCHNAME: $CIRRUS_BRANCH
RPCS3_TOKEN: ENCRYPTED[100ebb8e3552bf2021d0ef55dccda3e58d27be5b6cab0b0b92843ef490195d3c4edaefa087e4a3b425caa6392300b9b1]
QT_VER_MAIN: '6'
QT_VER: '6.8.3'
QT_VER: '6.9.0'
LLVM_COMPILER_VER: '19'
LLVM_VER: '19.1.7'
@ -23,7 +23,7 @@ env:
# COMPILER: msvc
# BUILD_ARTIFACTSTAGINGDIRECTORY: ${CIRRUS_WORKING_DIR}\artifacts\
# QT_VER_MSVC: 'msvc2022'
# QT_DATE: '202503201308'
# QT_DATE: '202503301022'
# QTDIR: C:\Qt\${QT_VER}\${QT_VER_MSVC}_64
# VULKAN_VER: '1.3.268.0'
# VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5'
@ -58,7 +58,7 @@ env:
# linux_task:
# container:
# image: rpcs3/rpcs3-ci-jammy:1.2
# image: rpcs3/rpcs3-ci-jammy:1.5
# cpu: 4
# memory: 16G
# env:
@ -134,7 +134,7 @@ freebsd_task:
# matrix:
# - name: Cirrus Linux AArch64 Clang
# arm_container:
# image: 'docker.io/rpcs3/rpcs3-ci-jammy-aarch64:1.2'
# image: 'docker.io/rpcs3/rpcs3-ci-jammy-aarch64:1.5'
# cpu: 8
# memory: 8G
# clang_script:

View file

@ -16,4 +16,4 @@ Submitting your test results for Commercial Games must be done on our forums. Pl
# Contributing
Check the [Coding Style Guidelines](https://github.com/RPCS3/rpcs3/wiki/Coding-Style) and [Developer Information](https://github.com/RPCS3/rpcs3/wiki/Developer-Information). If you have any questions, hit us up on our [Discord Server](https://discord.me/RPCS3) in the **#development** channel.
Check the [Coding Style Guidelines](https://github.com/RPCS3/rpcs3/wiki/Coding-Style) and [Developer Information](https://github.com/RPCS3/rpcs3/wiki/Developer-Information). If you have any questions, hit us up on our [Discord Server](https://discord.gg/rpcs3) in the **#development** channel.

View file

@ -7,7 +7,7 @@ body:
attributes:
value: |
# Summary
Please do not ask for help or report compatibility regressions here, use [RPCS3 Discord server](https://discord.me/RPCS3) or [forums](https://forums.rpcs3.net/) instead.
Please do not ask for help or report compatibility regressions here, use [RPCS3 Discord server](https://discord.gg/rpcs3) or [forums](https://forums.rpcs3.net/) instead.
- type: textarea
id: quick-summary
attributes:
@ -50,7 +50,7 @@ body:
* Completely close RPCS3 and locate the log file.
RPCS3's Log file will be ```RPCS3.log.gz``` (sometimes shows as RPCS3.log with zip icon) or ```RPCS3.log``` (sometimes shows as RPCS3 wtih notepad icon).
* On Windows it will be in the RPCS3 directory near the executable
* On Windows it will be in the ```log``` folder inside your RPCS3 folder.
* On Linux it will be in ```~/.cache/rpcs3/```
* On MacOS it will be in ```~/Library/Caches/rpcs3```. If you're unable to locate it copy paste the path in Spotlight and hit enter.
- type: textarea

View file

@ -7,7 +7,7 @@ body:
attributes:
value: |
# Summary
Please do not ask for help or report compatibility regressions here, use [RPCS3 Discord server](https://discord.me/RPCS3) or [forums](https://forums.rpcs3.net/) instead.
Please do not ask for help or report compatibility regressions here, use [RPCS3 Discord server](https://discord.gg/rpcs3) or [forums](https://forums.rpcs3.net/) instead.
- type: textarea
id: quick-summary
attributes:
@ -36,7 +36,7 @@ body:
* Completely close RPCS3 and locate the log file.
RPCS3's Log file will be ```RPCS3.log.gz``` (sometimes shows as RPCS3.log with zip icon) or ```RPCS3.log``` (sometimes shows as RPCS3 wtih notepad icon).
* On Windows it will be in the RPCS3 directory near the executable
* On Windows it will be in the ```log``` folder inside your RPCS3 folder.
* On Linux it will be in ```~/.cache/rpcs3/```
* On MacOS it will be in ```~/Library/Caches/rpcs3```. If you're unable to locate it copy paste the path in Spotlight and hit enter.
- type: textarea

View file

@ -6,7 +6,7 @@ body:
- type: markdown
attributes:
value: |
Please do not ask for help or report compatibility regressions here, use [RPCS3 Discord server](https://discord.me/RPCS3) or [forums](https://forums.rpcs3.net/) instead.
Please do not ask for help or report compatibility regressions here, use [RPCS3 Discord server](https://discord.gg/rpcs3) or [forums](https://forums.rpcs3.net/) instead.
- type: textarea
id: quick-summary
attributes:
@ -31,6 +31,6 @@ body:
* If this feature is something that a game is trying to use, upload a log file for it.
RPCS3's Log file will be ```RPCS3.log.gz``` (sometimes shows as RPCS3.log with zip icon) or ```RPCS3.log``` (sometimes shows as RPCS3 wtih notepad icon).
* On Windows it will be in the RPCS3 directory near the executable
* On Windows it will be in the ```log``` folder inside your RPCS3 folder.
* On Linux it will be in ```~/.cache/rpcs3/```
* On MacOS it will be in ```~/Library/Caches/rpcs3```. If you're unable to locate it copy paste the path in Spotlight and hit enter.

View file

@ -7,7 +7,7 @@ assignees: ''
---
## Please do not ask for help or report compatibility regressions here, use [RPCS3 Discord server](https://discord.me/RPCS3) or [forums](https://forums.rpcs3.net/) instead.
## Please do not ask for help or report compatibility regressions here, use [RPCS3 Discord server](https://discord.gg/rpcs3) or [forums](https://forums.rpcs3.net/) instead.
You're using the advanced template. You're expected to know what to write in order to fill in all the required information for proper report.

View file

@ -4,7 +4,7 @@ contact_links:
url: https://rpcs3.net/quickstart
about: Everything you need to know to install and configure emulator, and add games
- name: Ask for help
url: https://discord.me/RPCS3
url: https://discord.gg/rpcs3
about: If you have some questions or need help, please use our Discord server instead of GitHub
- name: Report game compatibility
url: https://forums.rpcs3.net/thread-196671.html

18
.github/PR-BUILD.md vendored
View file

@ -1,18 +0,0 @@
## How to test a PR build
Please take into account, that RPCS3 build usually takes some time (about 15 mins), so you can't access a build if a PR was just submitted.
- Open a PR you want to test
- Scroll to the very bottom and locate the **Checks** section
- Click on **Show all checks**
You are supposed to see something like this
![image](https://user-images.githubusercontent.com/10283761/116630952-2cd99e00-a94c-11eb-933e-986d6020ca92.png)
- Click on __Details__ on either **Cirrus Linux GCC** or **Cirrus Windows**
- Click **View more details on Cirrus CI** at the very bottom
![image](https://user-images.githubusercontent.com/10283761/116631111-5e526980-a94c-11eb-95f7-751e6f15e1ea.png)
- Click on the download button for **Artifact** on the **Artifacts** block
![image](https://user-images.githubusercontent.com/10283761/116631322-bee1a680-a94c-11eb-89a3-be365783582e.png)
- Congratulations! You are now downloading an RPCS3 build for that specific PR.
__Please note that PR builds are not supposed to be stable because they contain new changesets.__

View file

@ -1,3 +0,0 @@
<!-- Please include a summary of the change and which issue is fixed. -->
[How to test this PR](.github/PR-BUILD.md)

View file

@ -25,17 +25,17 @@ jobs:
matrix:
include:
- os: ubuntu-24.04
docker_img: "rpcs3/rpcs3-ci-jammy:1.3"
docker_img: "rpcs3/rpcs3-ci-jammy:1.5"
build_sh: "/rpcs3/.ci/build-linux.sh"
compiler: clang
UPLOAD_COMMIT_HASH: d812f1254a1157c80fd402f94446310560f54e5f
UPLOAD_REPO_FULL_NAME: "rpcs3/rpcs3-binaries-linux"
- os: ubuntu-24.04
docker_img: "rpcs3/rpcs3-ci-jammy:1.3"
docker_img: "rpcs3/rpcs3-ci-jammy:1.5"
build_sh: "/rpcs3/.ci/build-linux.sh"
compiler: gcc
- os: ubuntu-24.04-arm
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.3"
docker_img: "rpcs3/rpcs3-ci-jammy-aarch64:1.5"
build_sh: "/rpcs3/.ci/build-linux-aarch64.sh"
compiler: clang
UPLOAD_COMMIT_HASH: a1d35836e8d45bfc6f63c26f0a3e5d46ef622fe1
@ -105,13 +105,13 @@ jobs:
env:
COMPILER: msvc
QT_VER_MAIN: '6'
QT_VER: '6.8.3'
QT_VER: '6.9.0'
QT_VER_MSVC: 'msvc2022'
QT_DATE: '202503201308'
QT_DATE: '202503301022'
LLVM_VER: '19.1.7'
VULKAN_VER: '1.3.268.0'
VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5'
CCACHE_SHA: '6252f081876a9a9f700fae13a5aec5d0d486b28261d7f1f72ac11c7ad9df4da9'
CCACHE_SHA: '1f39f3ad5aae3fe915e99ad1302633bc8f6718e58fa7c0de2b0ba7e080f0f08c'
CCACHE_BIN_DIR: 'C:\ccache_bin'
CCACHE_DIR: 'C:\ccache'
CCACHE_INODECACHE: 'true'

3
.gitignore vendored
View file

@ -55,9 +55,6 @@
/bin/GuiConfigs/*.dat
/bin/GuiConfigs/*.dat.*
# Some data from git
!/bin/git/
# Visual Studio Files
.vs/*
.vscode/*

2
3rdparty/FAudio vendored

@ -1 +1 @@
Subproject commit 486e33eef3f282e4ce3d29f32ded3e67bacdbe5c
Subproject commit 091c6b4693ce507ac48037836a5a884e35cd2860

51
3rdparty/GL/glext.h vendored
View file

@ -32,7 +32,7 @@ extern "C" {
#define GLAPI extern
#endif
#define GL_GLEXT_VERSION 20220530
#define GL_GLEXT_VERSION 20250203
#include <KHR/khrplatform.h>
@ -5397,12 +5397,12 @@ typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severi
typedef void (APIENTRYP PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf);
typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void *userParam);
typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufSize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufSize, GLenum *categories, GLenum *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glDebugMessageEnableAMD (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
GLAPI void APIENTRY glDebugMessageInsertAMD (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf);
GLAPI void APIENTRY glDebugMessageCallbackAMD (GLDEBUGPROCAMD callback, void *userParam);
GLAPI GLuint APIENTRY glGetDebugMessageLogAMD (GLuint count, GLsizei bufSize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
GLAPI GLuint APIENTRY glGetDebugMessageLogAMD (GLuint count, GLsizei bufSize, GLenum *categories, GLenum *severities, GLuint *ids, GLsizei *lengths, GLchar *message);
#endif
#endif /* GL_AMD_debug_output */
@ -7370,6 +7370,16 @@ GLAPI void APIENTRY glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1,
#endif
#endif /* GL_EXT_framebuffer_blit */
#ifndef GL_EXT_framebuffer_blit_layers
#define GL_EXT_framebuffer_blit_layers 1
typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERLAYERSEXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERLAYEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint srcLayer, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLint dstLayer, GLbitfield mask, GLenum filter);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glBlitFramebufferLayersEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
GLAPI void APIENTRY glBlitFramebufferLayerEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint srcLayer, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLint dstLayer, GLbitfield mask, GLenum filter);
#endif
#endif /* GL_EXT_framebuffer_blit_layers */
#ifndef GL_EXT_framebuffer_multisample
#define GL_EXT_framebuffer_multisample 1
#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
@ -9394,6 +9404,11 @@ GLAPI void APIENTRY glResizeBuffersMESA (void);
#define GL_MESA_shader_integer_functions 1
#endif /* GL_MESA_shader_integer_functions */
#ifndef GL_MESA_texture_const_bandwidth
#define GL_MESA_texture_const_bandwidth 1
#define GL_CONST_BW_TILING_MESA 0x8BBE
#endif /* GL_MESA_texture_const_bandwidth */
#ifndef GL_MESA_tile_raster_order
#define GL_MESA_tile_raster_order 1
#define GL_TILE_RASTER_ORDER_FIXED_MESA 0x8BB8
@ -10248,12 +10263,6 @@ typedef void (APIENTRYP PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s,
typedef void (APIENTRYP PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV *v);
typedef void (APIENTRYP PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
typedef void (APIENTRYP PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV *v);
typedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog);
typedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog);
typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v);
typedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight);
typedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight);
typedef void (APIENTRYP PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x);
typedef void (APIENTRYP PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y);
@ -10266,6 +10275,12 @@ typedef void (APIENTRYP PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, c
typedef void (APIENTRYP PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
typedef void (APIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v);
typedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog);
typedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog);
typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v);
typedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight);
typedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glVertex2hNV (GLhalfNV x, GLhalfNV y);
GLAPI void APIENTRY glVertex2hvNV (const GLhalfNV *v);
@ -10295,12 +10310,6 @@ GLAPI void APIENTRY glMultiTexCoord3hNV (GLenum target, GLhalfNV s, GLhalfNV t,
GLAPI void APIENTRY glMultiTexCoord3hvNV (GLenum target, const GLhalfNV *v);
GLAPI void APIENTRY glMultiTexCoord4hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q);
GLAPI void APIENTRY glMultiTexCoord4hvNV (GLenum target, const GLhalfNV *v);
GLAPI void APIENTRY glFogCoordhNV (GLhalfNV fog);
GLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *fog);
GLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
GLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *v);
GLAPI void APIENTRY glVertexWeighthNV (GLhalfNV weight);
GLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *weight);
GLAPI void APIENTRY glVertexAttrib1hNV (GLuint index, GLhalfNV x);
GLAPI void APIENTRY glVertexAttrib1hvNV (GLuint index, const GLhalfNV *v);
GLAPI void APIENTRY glVertexAttrib2hNV (GLuint index, GLhalfNV x, GLhalfNV y);
@ -10313,6 +10322,12 @@ GLAPI void APIENTRY glVertexAttribs1hvNV (GLuint index, GLsizei n, const GLhalfN
GLAPI void APIENTRY glVertexAttribs2hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
GLAPI void APIENTRY glVertexAttribs3hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint index, GLsizei n, const GLhalfNV *v);
GLAPI void APIENTRY glFogCoordhNV (GLhalfNV fog);
GLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *fog);
GLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue);
GLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *v);
GLAPI void APIENTRY glVertexWeighthNV (GLhalfNV weight);
GLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *weight);
#endif
#endif /* GL_NV_half_float */
@ -11449,6 +11464,10 @@ GLAPI void APIENTRY glDrawTransformFeedbackNV (GLenum mode, GLuint id);
#endif
#endif /* GL_NV_transform_feedback2 */
#ifndef GL_NV_uniform_buffer_std430_layout
#define GL_NV_uniform_buffer_std430_layout 1
#endif /* GL_NV_uniform_buffer_std430_layout */
#ifndef GL_NV_uniform_buffer_unified_memory
#define GL_NV_uniform_buffer_unified_memory 1
#define GL_UNIFORM_BUFFER_UNIFIED_NV 0x936E
@ -11964,8 +11983,10 @@ GLAPI void APIENTRY glViewportSwizzleNV (GLuint index, GLenum swizzlex, GLenum s
#define GL_MAX_VIEWS_OVR 0x9631
#define GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR 0x9633
typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
#ifdef GL_GLEXT_PROTOTYPES
GLAPI void APIENTRY glFramebufferTextureMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
GLAPI void APIENTRY glNamedFramebufferTextureMultiviewOVR (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
#endif
#endif /* GL_OVR_multiview */

View file

@ -1,4 +1,3 @@
cmake_minimum_required(VERSION 2.8.12)
project(moltenvk NONE)
include(ExternalProject)

@ -1 +1 @@
Subproject commit 90191edd20bb877c5cbddfdac7ec0fe49ad93727
Subproject commit dc7d7054a5b4f3bec1dc23a42fd616a0847af948

@ -1 +1 @@
Subproject commit 394e1f58b23dc80599214d2e9b6a5e0dfd0bbe07
Subproject commit 3982730833b6daefe77dcfb32b5c282851640c17

2
3rdparty/curl/curl vendored

@ -1 +1 @@
Subproject commit 57495c64871d18905a0941db9196ef90bafe9a29
Subproject commit 1c3149881769e7bd79b072e48374e4c2b3678b2f

View file

@ -76,6 +76,7 @@
<ClCompile Include="curl\lib\connect.c" />
<ClCompile Include="curl\lib\content_encoding.c" />
<ClCompile Include="curl\lib\cookie.c" />
<ClCompile Include="curl\lib\cshutdn.c" />
<ClCompile Include="curl\lib\curl_addrinfo.c" />
<ClCompile Include="curl\lib\curl_des.c" />
<ClCompile Include="curl\lib\curl_endian.c" />
@ -94,7 +95,9 @@
<ClCompile Include="curl\lib\curl_threads.c" />
<ClCompile Include="curl\lib\curl_trc.c" />
<ClCompile Include="curl\lib\cw-out.c" />
<ClCompile Include="curl\lib\cw-pause.c" />
<ClCompile Include="curl\lib\dict.c" />
<ClCompile Include="curl\lib\dllmain.c" />
<ClCompile Include="curl\lib\doh.c" />
<ClCompile Include="curl\lib\dynbuf.c" />
<ClCompile Include="curl\lib\dynhds.c" />
@ -112,6 +115,7 @@
<ClCompile Include="curl\lib\getinfo.c" />
<ClCompile Include="curl\lib\gopher.c" />
<ClCompile Include="curl\lib\hash.c" />
<ClCompile Include="curl\lib\hash_offt.c" />
<ClCompile Include="curl\lib\headers.c" />
<ClCompile Include="curl\lib\hmac.c" />
<ClCompile Include="curl\lib\hostasyn.c" />
@ -138,6 +142,7 @@
<ClCompile Include="curl\lib\krb5.c" />
<ClCompile Include="curl\lib\ldap.c" />
<ClCompile Include="curl\lib\llist.c" />
<ClCompile Include="curl\lib\macos.c" />
<ClCompile Include="curl\lib\md4.c" />
<ClCompile Include="curl\lib\md5.c" />
<ClCompile Include="curl\lib\memdebug.c" />
@ -145,6 +150,7 @@
<ClCompile Include="curl\lib\mprintf.c" />
<ClCompile Include="curl\lib\mqtt.c" />
<ClCompile Include="curl\lib\multi.c" />
<ClCompile Include="curl\lib\multi_ev.c" />
<ClCompile Include="curl\lib\netrc.c" />
<ClCompile Include="curl\lib\nonblock.c" />
<ClCompile Include="curl\lib\noproxy.c" />
@ -174,10 +180,9 @@
<ClCompile Include="curl\lib\splay.c" />
<ClCompile Include="curl\lib\strcase.c" />
<ClCompile Include="curl\lib\strdup.c" />
<ClCompile Include="curl\lib\strequal.c" />
<ClCompile Include="curl\lib\strerror.c" />
<ClCompile Include="curl\lib\strparse.c" />
<ClCompile Include="curl\lib\strtok.c" />
<ClCompile Include="curl\lib\strtoofft.c" />
<ClCompile Include="curl\lib\system_win32.c" />
<ClCompile Include="curl\lib\telnet.c" />
<ClCompile Include="curl\lib\tftp.c" />
@ -260,6 +265,7 @@
<ClInclude Include="curl\lib\connect.h" />
<ClInclude Include="curl\lib\content_encoding.h" />
<ClInclude Include="curl\lib\cookie.h" />
<ClInclude Include="curl\lib\cshutdn.h" />
<ClInclude Include="curl\lib\curlx.h" />
<ClInclude Include="curl\lib\curl_addrinfo.h" />
<ClInclude Include="curl\lib\curl_base64.h" />
@ -291,6 +297,7 @@
<ClInclude Include="curl\lib\curl_threads.h" />
<ClInclude Include="curl\lib\curl_trc.h" />
<ClInclude Include="curl\lib\cw-out.h" />
<ClInclude Include="curl\lib\cw-pause.h" />
<ClInclude Include="curl\lib\dict.h" />
<ClInclude Include="curl\lib\doh.h" />
<ClInclude Include="curl\lib\dynbuf.h" />
@ -309,6 +316,7 @@
<ClInclude Include="curl\lib\getinfo.h" />
<ClInclude Include="curl\lib\gopher.h" />
<ClInclude Include="curl\lib\hash.h" />
<ClInclude Include="curl\lib\hash_offt.h" />
<ClInclude Include="curl\lib\headers.h" />
<ClInclude Include="curl\lib\hostip.h" />
<ClInclude Include="curl\lib\hsts.h" />
@ -328,11 +336,13 @@
<ClInclude Include="curl\lib\inet_ntop.h" />
<ClInclude Include="curl\lib\inet_pton.h" />
<ClInclude Include="curl\lib\llist.h" />
<ClInclude Include="curl\lib\macos.h" />
<ClInclude Include="curl\lib\memdebug.h" />
<ClInclude Include="curl\lib\mime.h" />
<ClInclude Include="curl\lib\mqtt.h" />
<ClInclude Include="curl\lib\multihandle.h" />
<ClInclude Include="curl\lib\multiif.h" />
<ClInclude Include="curl\lib\multi_ev.h" />
<ClInclude Include="curl\lib\netrc.h" />
<ClInclude Include="curl\lib\nonblock.h" />
<ClInclude Include="curl\lib\noproxy.h" />

View file

@ -291,12 +291,6 @@
<ClCompile Include="curl\lib\strerror.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\strtok.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\strtoofft.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\system_win32.c">
<Filter>Source Files</Filter>
</ClCompile>
@ -522,6 +516,27 @@
<ClCompile Include="curl\lib\vtls\vtls_spack.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\cshutdn.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\cw-pause.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\dllmain.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\hash_offt.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\macos.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\multi_ev.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="curl\lib\strequal.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="curl\include\curl\curl.h">
@ -1055,6 +1070,21 @@
<ClInclude Include="curl\lib\vtls\vtls_spack.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\cshutdn.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\cw-pause.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\hash_offt.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\macos.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="curl\lib\multi_ev.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="curl\lib\libcurl.rc">

@ -1 +1 @@
Subproject commit 171b2142ac8acdf016c231e36dc7a8d48daff19c
Subproject commit 3dc2c326cb4dc5815c6069970c13154898f58d48

@ -1 +1 @@
Subproject commit f6864924f76e1a0b4abaefc76ae2ed22b1a8916e
Subproject commit 877399b2b2cf21e67554ed9046410f268ce1d1b2

View file

@ -1,5 +1,3 @@
cmake_minimum_required(VERSION 3.0)
project(libusb)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -19,26 +19,26 @@ The following tools are required to build RPCS3 on Windows 10 or later:
with standalone **CMake** tool.
- [Python 3.6+](https://www.python.org/downloads/) (add to PATH)
- [Qt 6.8.3](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt)
- [Qt 6.9.0](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt)
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (see "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
The `sln` solution available only on **Visual Studio** is the preferred building solution. It easily allows to build the **RPCS3** application in `Release` and `Debug` mode.
In order to build **RPCS3** with the `sln` solution (with **Visual Studio**), **Qt** libs need to be detected. To detect the libs:
- add and set the `QTDIR` environment variable, e.g. `<QtInstallFolder>\6.8.3\msvc2022_64\`
- add and set the `QTDIR` environment variable, e.g. `<QtInstallFolder>\6.9.0\msvc2022_64\`
- or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2022)
**NOTE:** If you have issues with the **Visual Studio Qt Plugin**, you may want to uninstall it and install the [Legacy Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.LEGACYQtVisualStudioTools2022) instead.
In order to build **RPCS3** with the `CMake` solution (with both **Visual Studio** and standalone **CMake** tool):
- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `<QtInstallFolder>\6.8.3\msvc2022_64\`
- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `<QtInstallFolder>\6.9.0\msvc2022_64\`
### Linux
These are the essentials tools to build RPCS3 on Linux. Some of them can be installed through your favorite package manager:
- Clang 17+ or GCC 13+
- [CMake 3.28.0+](https://www.cmake.org/download/)
- [Qt 6.8.3](https://www.qt.io/download-qt-installer)
- [Qt 6.9.0](https://www.qt.io/download-qt-installer)
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
- [SDL3](https://github.com/libsdl-org/SDL/releases) (for the FAudio backend)
@ -121,7 +121,7 @@ Start **Visual Studio**, click on `Open a project or solution` and select the `r
##### Configuring the Qt Plugin (if used)
1) go to `Extensions->Qt VS Tools->Qt Versions`
2) add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\6.8.3\msvc2022_64`, version will fill in automatically
2) add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\6.9.0\msvc2022_64`, version will fill in automatically
3) go to `Extensions->Qt VS Tools->Options->Legacy Project Format`. (Only available in the **Legacy Qt Plugin**)
4) set `Build: Run pre-build setup` to `true`. (Only available in the **Legacy Qt Plugin**)

View file

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.16.9)
cmake_minimum_required(VERSION 3.28)
project(rpcs3 LANGUAGES C CXX)

View file

@ -4,7 +4,7 @@ RPCS3
[![Azure Build Status](https://dev.azure.com/nekotekina/nekotekina/_apis/build/status/RPCS3.rpcs3?branchName=master)](https://dev.azure.com/nekotekina/nekotekina/_build?definitionId=8&_a=summary&repositoryFilter=4)
[![Cirrus CI - Base Branch Build Status](https://img.shields.io/cirrus/github/RPCS3/rpcs3/master?label=Cirrus%20CI&logo=cirrus-ci)](https://cirrus-ci.com/github/RPCS3/rpcs3)
[![GitHub Actions](https://img.shields.io/github/actions/workflow/status/RPCS3/rpcs3/rpcs3.yml?branch=master&logo=github&label=Actions)](https://github.com/RPCS3/rpcs3/actions/workflows/rpcs3.yml)
[![RPCS3 Discord Server](https://img.shields.io/discord/272035812277878785?color=5865F2&label=RPCS3%20Discord&logo=discord&logoColor=white)](https://discord.me/rpcs3)
[![RPCS3 Discord Server](https://img.shields.io/discord/272035812277878785?color=5865F2&label=RPCS3%20Discord&logo=discord&logoColor=white)](https://discord.gg/rpcs3)
The world's first free and open-source PlayStation 3 emulator/debugger, written in C++ for Windows, Linux, macOS and FreeBSD.
@ -34,7 +34,7 @@ See [BUILDING.md](BUILDING.md) for more information about how to setup an enviro
Check our friendly [quickstart](https://rpcs3.net/quickstart) guide to make sure your computer meets the minimum system requirements to run RPCS3.
Don't forget to have your graphics driver up to date and to install the [Visual C++ Redistributable Packages for Visual Studio 2019](https://aka.ms/vs/16/release/VC_redist.x64.exe) if you are a Windows user.
Don't forget to have your graphics driver up to date and to install the [Visual C++ Redistributable Packages for Visual Studio 2022](https://aka.ms/vs/17/release/VC_redist.x64.exe) if you are a Windows user.
## License

View file

@ -40,13 +40,13 @@ jobs:
# displayName: ccache
# - bash: |
# docker pull --quiet rpcs3/rpcs3-ci-jammy:1.3
# docker pull --quiet rpcs3/rpcs3-ci-jammy:1.5
# docker run \
# -v $(pwd):/rpcs3 \
# --env-file .ci/docker.env \
# -v $CCACHE_DIR:/root/.ccache \
# -v $BUILD_ARTIFACTSTAGINGDIRECTORY:/root/artifacts \
# rpcs3/rpcs3-ci-jammy:1.3 \
# rpcs3/rpcs3-ci-jammy:1.5 \
# /rpcs3/.ci/build-linux.sh
# displayName: Docker setup and build
@ -71,9 +71,9 @@ jobs:
# variables:
# COMPILER: msvc
# QT_VER_MAIN: '6'
# QT_VER: '6.8.3'
# QT_VER: '6.9.0'
# QT_VER_MSVC: 'msvc2022'
# QT_DATE: '202503201308'
# QT_DATE: '202503301022'
# QTDIR: C:\Qt\$(QT_VER)\$(QT_VER_MSVC)_64
# LLVM_VER: '19.1.7'
# VULKAN_VER: '1.3.268.0'

View file

@ -1 +0,0 @@
Cached data from GitHub API.

File diff suppressed because one or more lines are too long

View file

@ -158,19 +158,16 @@ if (NOT ANDROID)
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/rpcs3.icns $<TARGET_FILE_DIR:rpcs3>/../Resources/rpcs3.icns
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/Icons $<TARGET_FILE_DIR:rpcs3>/../Resources/Icons
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/GuiConfigs $<TARGET_FILE_DIR:rpcs3>/../Resources/GuiConfigs
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/git $<TARGET_FILE_DIR:rpcs3>/../Resources/git
COMMAND "${MACDEPLOYQT_EXECUTABLE}" "${PROJECT_BINARY_DIR}/bin/rpcs3.app" "${QT_DEPLOY_FLAGS}")
elseif(UNIX)
add_custom_command(TARGET rpcs3 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/Icons $<TARGET_FILE_DIR:rpcs3>/Icons
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/GuiConfigs $<TARGET_FILE_DIR:rpcs3>/GuiConfigs
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/git $<TARGET_FILE_DIR:rpcs3>/git)
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/GuiConfigs $<TARGET_FILE_DIR:rpcs3>/GuiConfigs)
elseif(WIN32)
add_custom_command(TARGET rpcs3 POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:OpenAL::OpenAL> $<TARGET_FILE_DIR:rpcs3>
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/Icons $<TARGET_FILE_DIR:rpcs3>/Icons
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/GuiConfigs $<TARGET_FILE_DIR:rpcs3>/GuiConfigs
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/bin/git $<TARGET_FILE_DIR:rpcs3>/git
COMMAND "${WINDEPLOYQT_EXECUTABLE}" --no-compiler-runtime --no-opengl-sw --no-patchqt
--no-translations --no-system-d3d-compiler --no-system-dxc-compiler --no-ffmpeg --no-quick-import
--plugindir "$<IF:$<CXX_COMPILER_ID:MSVC>,$<TARGET_FILE_DIR:rpcs3>/plugins,$<TARGET_FILE_DIR:rpcs3>/share/qt6/plugins>"
@ -195,8 +192,6 @@ if (NOT ANDROID)
DESTINATION ${CMAKE_INSTALL_DATADIR}/rpcs3)
install(DIRECTORY ../bin/GuiConfigs
DESTINATION ${CMAKE_INSTALL_DATADIR}/rpcs3)
install(DIRECTORY ../bin/git
DESTINATION ${CMAKE_INSTALL_DATADIR}/rpcs3)
install(DIRECTORY ../bin/test
DESTINATION ${CMAKE_INSTALL_DATADIR}/rpcs3)
endif()

View file

@ -1343,10 +1343,13 @@ static fs::file CheckDebugSelf(const fs::file& s)
fs::file e = fs::make_stream<std::vector<u8>>();
// Copy the data.
char buf[2048];
while (const u64 size = s.read(buf, 2048))
std::vector<u8> buf(std::min<usz>(s.size(), 4096));
usz read_pos = 0;
while (const u64 size = s.read_at(read_pos, buf.data(), buf.size()))
{
e.write(buf, size);
e.write(buf.data(), size);
read_pos += size;
}
return e;
@ -1371,7 +1374,10 @@ fs::file decrypt_self(const fs::file& elf_or_self, const u8* klic_key, SelfAddit
elf_or_self.seek(0);
// Check SELF header first. Check for a debug SELF.
if (elf_or_self.size() >= 4 && elf_or_self.read<u32>() == "SCE\0"_u32)
u32 file_type = umax;
elf_or_self.read_at(0, &file_type, sizeof(file_type));
if (file_type == "SCE\0"_u32)
{
if (fs::file res = CheckDebugSelf(elf_or_self))
{
@ -1409,6 +1415,23 @@ fs::file decrypt_self(const fs::file& elf_or_self, const u8* klic_key, SelfAddit
// Make a new ELF file from this SELF.
return self_dec.MakeElf(isElf32);
}
else if (Emu.GetBoot().ends_with(".elf") || Emu.GetBoot().ends_with(".ELF"))
{
// Write the file back if the main executable is not signed
fs::file e = fs::make_stream<std::vector<u8>>();
// Copy the data.
std::vector<u8> buf(std::min<usz>(elf_or_self.size(), 4096));
usz read_pos = 0;
while (const u64 size = elf_or_self.read_at(read_pos, buf.data(), buf.size()))
{
e.write(buf.data(), size);
read_pos += size;
}
return e;
}
return {};
}

View file

@ -546,6 +546,7 @@ target_sources(rpcs3_emu PRIVATE
RSX/Overlays/overlay_trophy_notification.cpp
RSX/Overlays/overlay_user_list_dialog.cpp
RSX/Overlays/overlay_utils.cpp
RSX/Overlays/overlay_video.cpp
RSX/Overlays/Shaders/shader_loading_dialog.cpp
RSX/Overlays/Shaders/shader_loading_dialog_native.cpp
RSX/Program/CgBinaryFragmentProgram.cpp
@ -626,6 +627,7 @@ if(TARGET 3rdparty_vulkan)
RSX/VK/VKCommonDecompiler.cpp
RSX/VK/VKCommonPipelineLayout.cpp
RSX/VK/VKCompute.cpp
RSX/VK/VKDataHeapManager.cpp
RSX/VK/VKDMA.cpp
RSX/VK/VKDraw.cpp
RSX/VK/VKFormats.cpp
@ -648,6 +650,7 @@ if(TARGET 3rdparty_vulkan)
RSX/VK/VKVertexBuffers.cpp
RSX/VK/VKVertexProgram.cpp
RSX/VK/VKTextureCache.cpp
RSX/VK/VulkanAPI.cpp
)
endif()

View file

@ -195,7 +195,7 @@ struct audio_port
// Handle copy ctor of atomic var
audio_port(const audio_port& r)
{
std::memcpy(this, &r, sizeof(r));
std::memcpy(static_cast<void*>(this), &r, sizeof(r));
}
ENABLE_BITWISE_SERIALIZATION;

View file

@ -75,7 +75,7 @@ struct CellAudioInDeviceInfo
u8 reserved[12];
be_t<u64> deviceId;
be_t<u64> type;
char name[64];
char name[64]; // Not necessarily null terminated!
CellAudioInSoundMode availableModes[16];
};

View file

@ -38,11 +38,17 @@ void fmt_class_string<CellAudioInError>::format(std::string& out, u64 arg)
struct avconf_manager
{
shared_mutex mutex;
std::vector<CellAudioInDeviceInfo> devices;
struct device_info
{
CellAudioInDeviceInfo info {};
std::string full_device_name; // The device name may be too long for CellAudioInDeviceInfo, so we additionally save the full name.
};
std::vector<device_info> devices;
CellAudioInDeviceMode inDeviceMode = CELL_AUDIO_IN_SINGLE_DEVICE_MODE; // TODO: use somewhere
void copy_device_info(u32 num, vm::ptr<CellAudioInDeviceInfo> info) const;
std::optional<CellAudioInDeviceInfo> get_device_info(vm::cptr<char> name) const;
std::optional<device_info> get_device_info(vm::cptr<char> name) const;
avconf_manager();
@ -62,78 +68,89 @@ avconf_manager::avconf_manager()
switch (g_cfg.audio.microphone_type)
{
case microphone_handler::standard:
{
for (u32 index = 0; index < mic_list.size(); index++)
{
devices.emplace_back();
devices[curindex].portType = CELL_AUDIO_IN_PORT_USB;
devices[curindex].availableModeCount = 1;
devices[curindex].state = CELL_AUDIO_IN_DEVICE_STATE_AVAILABLE;
devices[curindex].deviceId = 0xE11CC0DE + curindex;
devices[curindex].type = 0xC0DEE11C;
devices[curindex].availableModes[0].type = CELL_AUDIO_IN_CODING_TYPE_LPCM;
devices[curindex].availableModes[0].channel = CELL_AUDIO_IN_CHNUM_2;
devices[curindex].availableModes[0].fs = CELL_AUDIO_IN_FS_8KHZ | CELL_AUDIO_IN_FS_12KHZ | CELL_AUDIO_IN_FS_16KHZ | CELL_AUDIO_IN_FS_24KHZ | CELL_AUDIO_IN_FS_32KHZ | CELL_AUDIO_IN_FS_48KHZ;
devices[curindex].deviceNumber = curindex;
strcpy_trunc(devices[curindex].name, mic_list[index]);
device_info device {};
device.info.portType = CELL_AUDIO_IN_PORT_USB;
device.info.availableModeCount = 1;
device.info.state = CELL_AUDIO_IN_DEVICE_STATE_AVAILABLE;
device.info.deviceId = 0xE11CC0DE + curindex;
device.info.type = 0xC0DEE11C;
device.info.availableModes[0].type = CELL_AUDIO_IN_CODING_TYPE_LPCM;
device.info.availableModes[0].channel = CELL_AUDIO_IN_CHNUM_2;
device.info.availableModes[0].fs = CELL_AUDIO_IN_FS_8KHZ | CELL_AUDIO_IN_FS_12KHZ | CELL_AUDIO_IN_FS_16KHZ | CELL_AUDIO_IN_FS_24KHZ | CELL_AUDIO_IN_FS_32KHZ | CELL_AUDIO_IN_FS_48KHZ;
device.info.deviceNumber = curindex;
device.full_device_name = mic_list[index];
strcpy_trunc(device.info.name, device.full_device_name);
devices.push_back(std::move(device));
curindex++;
}
break;
}
case microphone_handler::real_singstar:
case microphone_handler::singstar:
{
// Only one device for singstar device
devices.emplace_back();
devices[curindex].portType = CELL_AUDIO_IN_PORT_USB;
devices[curindex].availableModeCount = 1;
devices[curindex].state = CELL_AUDIO_IN_DEVICE_STATE_AVAILABLE;
devices[curindex].deviceId = 0x00000001;
devices[curindex].type = 0x14150000;
devices[curindex].availableModes[0].type = CELL_AUDIO_IN_CODING_TYPE_LPCM;
devices[curindex].availableModes[0].channel = CELL_AUDIO_IN_CHNUM_2;
devices[curindex].availableModes[0].fs = CELL_AUDIO_IN_FS_8KHZ | CELL_AUDIO_IN_FS_12KHZ | CELL_AUDIO_IN_FS_16KHZ | CELL_AUDIO_IN_FS_24KHZ | CELL_AUDIO_IN_FS_32KHZ | CELL_AUDIO_IN_FS_48KHZ;
devices[curindex].deviceNumber = curindex;
strcpy_trunc(devices[curindex].name, mic_list[0]);
device_info device {};
device.info.portType = CELL_AUDIO_IN_PORT_USB;
device.info.availableModeCount = 1;
device.info.state = CELL_AUDIO_IN_DEVICE_STATE_AVAILABLE;
device.info.deviceId = 0x00000001;
device.info.type = 0x14150000;
device.info.availableModes[0].type = CELL_AUDIO_IN_CODING_TYPE_LPCM;
device.info.availableModes[0].channel = CELL_AUDIO_IN_CHNUM_2;
device.info.availableModes[0].fs = CELL_AUDIO_IN_FS_8KHZ | CELL_AUDIO_IN_FS_12KHZ | CELL_AUDIO_IN_FS_16KHZ | CELL_AUDIO_IN_FS_24KHZ | CELL_AUDIO_IN_FS_32KHZ | CELL_AUDIO_IN_FS_48KHZ;
device.info.deviceNumber = curindex;
device.full_device_name = mic_list[0];
strcpy_trunc(device.info.name, device.full_device_name);
devices.push_back(std::move(device));
curindex++;
break;
}
case microphone_handler::rocksmith:
devices.emplace_back();
devices[curindex].portType = CELL_AUDIO_IN_PORT_USB;
devices[curindex].availableModeCount = 1;
devices[curindex].state = CELL_AUDIO_IN_DEVICE_STATE_AVAILABLE;
devices[curindex].deviceId = 0x12BA00FF; // Specific to rocksmith usb input
devices[curindex].type = 0xC0DE73C4;
devices[curindex].availableModes[0].type = CELL_AUDIO_IN_CODING_TYPE_LPCM;
devices[curindex].availableModes[0].channel = CELL_AUDIO_IN_CHNUM_1;
devices[curindex].availableModes[0].fs = CELL_AUDIO_IN_FS_8KHZ | CELL_AUDIO_IN_FS_12KHZ | CELL_AUDIO_IN_FS_16KHZ | CELL_AUDIO_IN_FS_24KHZ | CELL_AUDIO_IN_FS_32KHZ | CELL_AUDIO_IN_FS_48KHZ;
devices[curindex].deviceNumber = curindex;
strcpy_trunc(devices[curindex].name, mic_list[0]);
{
device_info device {};
device.info.portType = CELL_AUDIO_IN_PORT_USB;
device.info.availableModeCount = 1;
device.info.state = CELL_AUDIO_IN_DEVICE_STATE_AVAILABLE;
device.info.deviceId = 0x12BA00FF; // Specific to rocksmith usb input
device.info.type = 0xC0DE73C4;
device.info.availableModes[0].type = CELL_AUDIO_IN_CODING_TYPE_LPCM;
device.info.availableModes[0].channel = CELL_AUDIO_IN_CHNUM_1;
device.info.availableModes[0].fs = CELL_AUDIO_IN_FS_8KHZ | CELL_AUDIO_IN_FS_12KHZ | CELL_AUDIO_IN_FS_16KHZ | CELL_AUDIO_IN_FS_24KHZ | CELL_AUDIO_IN_FS_32KHZ | CELL_AUDIO_IN_FS_48KHZ;
device.info.deviceNumber = curindex;
device.full_device_name = mic_list[0];
strcpy_trunc(device.info.name, device.full_device_name);
devices.push_back(std::move(device));
curindex++;
break;
}
case microphone_handler::null:
default: break;
default:
break;
}
}
if (g_cfg.io.camera != camera_handler::null)
{
devices.emplace_back();
devices[curindex].portType = CELL_AUDIO_IN_PORT_USB;
devices[curindex].availableModeCount = 1;
devices[curindex].state = CELL_AUDIO_IN_DEVICE_STATE_AVAILABLE;
devices[curindex].deviceId = 0xDEADBEEF;
devices[curindex].type = 0xBEEFDEAD;
devices[curindex].availableModes[0].type = CELL_AUDIO_IN_CODING_TYPE_LPCM;
devices[curindex].availableModes[0].channel = CELL_AUDIO_IN_CHNUM_NONE;
devices[curindex].availableModes[0].fs = CELL_AUDIO_IN_FS_8KHZ | CELL_AUDIO_IN_FS_12KHZ | CELL_AUDIO_IN_FS_16KHZ | CELL_AUDIO_IN_FS_24KHZ | CELL_AUDIO_IN_FS_32KHZ | CELL_AUDIO_IN_FS_48KHZ;
devices[curindex].deviceNumber = curindex;
strcpy_trunc(devices[curindex].name, "USB Camera");
device_info device {};
device.info.portType = CELL_AUDIO_IN_PORT_USB;
device.info.availableModeCount = 1;
device.info.state = CELL_AUDIO_IN_DEVICE_STATE_AVAILABLE;
device.info.deviceId = 0xDEADBEEF;
device.info.type = 0xBEEFDEAD;
device.info.availableModes[0].type = CELL_AUDIO_IN_CODING_TYPE_LPCM;
device.info.availableModes[0].channel = CELL_AUDIO_IN_CHNUM_NONE;
device.info.availableModes[0].fs = CELL_AUDIO_IN_FS_8KHZ | CELL_AUDIO_IN_FS_12KHZ | CELL_AUDIO_IN_FS_16KHZ | CELL_AUDIO_IN_FS_24KHZ | CELL_AUDIO_IN_FS_32KHZ | CELL_AUDIO_IN_FS_48KHZ;
device.info.deviceNumber = curindex;
device.full_device_name = "USB Camera";
strcpy_trunc(device.info.name, device.full_device_name);
devices.push_back(std::move(device));
curindex++;
}
}
@ -142,14 +159,14 @@ void avconf_manager::copy_device_info(u32 num, vm::ptr<CellAudioInDeviceInfo> in
{
memset(info.get_ptr(), 0, sizeof(CellAudioInDeviceInfo));
ensure(num < devices.size());
*info = devices[num];
*info = devices[num].info;
}
std::optional<CellAudioInDeviceInfo> avconf_manager::get_device_info(vm::cptr<char> name) const
std::optional<avconf_manager::device_info> avconf_manager::get_device_info(vm::cptr<char> name) const
{
for (const CellAudioInDeviceInfo& device : devices)
for (const device_info& device : devices)
{
if (strncmp(device.name, name.get_ptr(), sizeof(device.name)) == 0)
if (strncmp(device.info.name, name.get_ptr(), sizeof(device.info.name)) == 0)
{
return device;
}
@ -398,8 +415,8 @@ error_code cellAudioInRegisterDevice(u64 deviceType, vm::cptr<char> name, vm::pt
auto& av_manager = g_fxo->get<avconf_manager>();
const std::lock_guard lock(av_manager.mutex);
std::optional<CellAudioInDeviceInfo> info = av_manager.get_device_info(name);
if (!info || !memchr(info->name, '\0', sizeof(info->name)))
std::optional<avconf_manager::device_info> device = av_manager.get_device_info(name);
if (!device)
{
// TODO
return CELL_AUDIO_IN_ERROR_DEVICE_NOT_FOUND;
@ -407,7 +424,7 @@ error_code cellAudioInRegisterDevice(u64 deviceType, vm::cptr<char> name, vm::pt
auto& mic_thr = g_fxo->get<mic_thread>();
const std::lock_guard mic_lock(mic_thr.mutex);
const u32 device_number = mic_thr.register_device(info->name);
const u32 device_number = mic_thr.register_device(device->full_device_name);
return not_an_error(device_number);
}

View file

@ -446,7 +446,7 @@ error_code _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> contex
gcm_cfg.zculls_addr = vm::alloc(sizeof(CellGcmZcullInfo) * 8, vm::main);
gcm_cfg.tiles_addr = vm::alloc(sizeof(CellGcmTileInfo) * 15, vm::main);
vm::_ref<CellGcmContextData>(gcm_cfg.gcm_info.context_addr) = gcm_cfg.current_context;
vm::write<CellGcmContextData>(gcm_cfg.gcm_info.context_addr, gcm_cfg.current_context);
context->set(gcm_cfg.gcm_info.context_addr);
// 0x40 is to offset CellGcmControl from RsxDmaControl
@ -590,7 +590,7 @@ ret_type gcmSetPrepareFlip(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctxt, u3
if (!old_api && ctxt.addr() == gcm_cfg.gcm_info.context_addr)
{
vm::_ref<CellGcmControl>(gcm_cfg.gcm_info.control_addr).put += cmd_size;
vm::_ptr<CellGcmControl>(gcm_cfg.gcm_info.control_addr)->put += cmd_size;
}
return static_cast<ret_type>(not_an_error(id));
@ -1463,7 +1463,7 @@ s32 cellGcmCallback(ppu_thread& ppu, vm::ptr<CellGcmContextData> context, u32 co
auto& gcm_cfg = g_fxo->get<gcm_config>();
auto& ctrl = vm::_ref<CellGcmControl>(gcm_cfg.gcm_info.control_addr);
auto& ctrl = *vm::_ptr<CellGcmControl>(gcm_cfg.gcm_info.control_addr);
// Flush command buffer (ie allow RSX to read up to context->current)
ctrl.put.exchange(getOffsetFromAddress(context->current.addr()));

View file

@ -322,6 +322,8 @@ error_code microphone_device::open_microphone(const u8 type, const u32 dsp_r, co
num_channels = channels;
#ifndef WITHOUT_OPENAL
enumerate_devices();
// Adjust number of channels depending on microphone type
switch (device_type)
{
@ -423,36 +425,40 @@ error_code microphone_device::open_microphone(const u8 type, const u32 dsp_r, co
break;
}
ALCdevice* device = nullptr;
// Make sure we use a proper sampling rate
const auto fixup_samplingrate = [this](u32& rate) -> bool
// TODO: The used sample rate may vary for Sony's camera devices
const std::array<u32, 7> samplingrates = { raw_samplingrate, 48000u, 32000u, 24000u, 16000u, 12000u, 8000u };
for (u32 samplingrate : samplingrates)
{
// TODO: The used sample rate may vary for Sony's camera devices
const std::array<u32, 7> samplingrates = { rate, 48000u, 32000u, 24000u, 16000u, 12000u, 8000u };
const auto test_samplingrate = [&samplingrates](const u32& rate)
if (!std::any_of(samplingrates.cbegin() + 1, samplingrates.cend(), [samplingrate](u32 r){ return r == samplingrate; }))
{
// TODO: actually check if device supports sampling rates
return std::any_of(samplingrates.cbegin() + 1, samplingrates.cend(), [&rate](const u32& r){ return r == rate; });
};
for (u32 samplingrate : samplingrates)
{
if (test_samplingrate(samplingrate))
{
// Use this sampling rate
raw_samplingrate = samplingrate;
cellMic.notice("Using sampling rate %d.", samplingrate);
return true;
}
cellMic.warning("Requested sampling rate %d, but we do not support it. Trying next sampling rate...", samplingrate);
continue;
}
return false;
};
cellMic.notice("Trying sampling rate %d with %d channel(s)", samplingrate, num_channels);
if (!fixup_samplingrate(raw_samplingrate))
device = open_device(devices[0].name, samplingrate, num_al_channels, inbuf_size);
if (!device)
{
continue;
}
// Use this sampling rate
raw_samplingrate = samplingrate;
cellMic.notice("Using sampling rate %d and %d channel(s)", raw_samplingrate, num_channels);
break;
}
if (!device)
{
cellMic.error("Failed to open capture device '%s' (raw_samplingrate=%d, num_al_channels=0x%x, inbuf_size=%d)", devices[0].name, raw_samplingrate, num_al_channels, inbuf_size);
#ifdef _WIN32
cellMic.error("Make sure microphone use is authorized under \"Microphone privacy settings\" in windows configuration");
#endif
return CELL_MICIN_ERROR_DEVICE_NOT_SUPPORT;
}
@ -460,29 +466,19 @@ error_code microphone_device::open_microphone(const u8 type, const u32 dsp_r, co
ensure(!devices.empty());
ALCdevice* device = alcCaptureOpenDevice(devices[0].name.c_str(), raw_samplingrate, num_al_channels, inbuf_size);
if (ALCenum err = alcGetError(device); err != ALC_NO_ERROR || !device)
{
cellMic.error("Error opening capture device %s (error=%s, device=*0x%x)", devices[0].name, fmt::alc_error{device, err}, device);
#ifdef _WIN32
cellMic.error("Make sure microphone use is authorized under \"Microphone privacy settings\" in windows configuration");
#endif
return CELL_MICIN_ERROR_DEVICE_NOT_SUPPORT;
}
devices[0].device = device;
devices[0].buf.resize(inbuf_size, 0);
if (device_type == microphone_handler::singstar && devices.size() >= 2)
{
// Open a 2nd microphone into the same device
device = alcCaptureOpenDevice(devices[1].name.c_str(), raw_samplingrate, AL_FORMAT_MONO16, inbuf_size);
num_al_channels = AL_FORMAT_MONO16;
device = open_device(devices[1].name, raw_samplingrate, num_al_channels, inbuf_size);
if (ALCenum err = alcGetError(device); err != ALC_NO_ERROR || !device)
if (!device)
{
// Ignore it and move on
cellMic.error("Error opening 2nd SingStar capture device %s (error=%s, device=*0x%x)", devices[1].name, fmt::alc_error{device, err}, device);
cellMic.error("Failed to open 2nd SingStar capture device '%s' (raw_samplingrate=%d, num_al_channels=0x%x, inbuf_size=%d)", devices[1].name, raw_samplingrate, num_al_channels, inbuf_size);
}
else
{
@ -517,7 +513,7 @@ error_code microphone_device::close_microphone()
{
if (alcCaptureCloseDevice(micdevice.device) != ALC_TRUE)
{
cellMic.error("Error closing capture device %s", micdevice.name);
cellMic.error("Error closing capture device '%s'", micdevice.name);
}
micdevice.device = nullptr;
@ -539,7 +535,7 @@ error_code microphone_device::start_microphone()
alcCaptureStart(micdevice.device);
if (ALCenum err = alcGetError(micdevice.device); err != ALC_NO_ERROR)
{
cellMic.error("Error starting capture of device %s (error=%s)", micdevice.name, fmt::alc_error{micdevice.device, err});
cellMic.error("Error starting capture of device '%s' (error=%s)", micdevice.name, fmt::alc_error{micdevice.device, err});
stop_microphone();
return CELL_MICIN_ERROR_FATAL;
}
@ -558,7 +554,7 @@ error_code microphone_device::stop_microphone()
alcCaptureStop(micdevice.device);
if (ALCenum err = alcGetError(micdevice.device); err != ALC_NO_ERROR)
{
cellMic.error("Error stopping capture of device %s (error=%s)", micdevice.name, fmt::alc_error{micdevice.device, err});
cellMic.error("Error stopping capture of device '%s' (error=%s)", micdevice.name, fmt::alc_error{micdevice.device, err});
}
}
#endif
@ -637,7 +633,7 @@ u32 microphone_device::capture_audio()
if (ALCenum err = alcGetError(micdevice.device); err != ALC_NO_ERROR)
{
cellMic.error("Error getting number of captured samples of device %s (error=%s)", micdevice.name, fmt::alc_error{micdevice.device, err});
cellMic.error("Error getting number of captured samples of device '%s' (error=%s)", micdevice.name, fmt::alc_error{micdevice.device, err});
return CELL_MICIN_ERROR_FATAL;
}
@ -655,7 +651,7 @@ u32 microphone_device::capture_audio()
if (ALCenum err = alcGetError(micdevice.device); err != ALC_NO_ERROR)
{
cellMic.error("Error capturing samples of device %s (error=%s)", micdevice.name, fmt::alc_error{micdevice.device, err});
cellMic.error("Error capturing samples of device '%s' (error=%s)", micdevice.name, fmt::alc_error{micdevice.device, err});
}
}
@ -667,6 +663,56 @@ u32 microphone_device::capture_audio()
// Private functions
#ifndef WITHOUT_OPENAL
void microphone_device::enumerate_devices()
{
cellMic.notice("Enumerating capture devices...");
enumerated_devices.clear();
if (alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT") == AL_TRUE)
{
if (const char* alc_devices = alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER))
{
while (alc_devices && *alc_devices != 0)
{
cellMic.notice("Found capture device: '%s'", alc_devices);
enumerated_devices.push_back(alc_devices);
alc_devices += strlen(alc_devices) + 1;
}
}
}
else
{
// Without enumeration we can only use one device
cellMic.error("OpenAl extension ALC_ENUMERATION_EXT not supported. The enumerated capture devices will only contain the default capture device.");
if (const char* alc_device = alcGetString(nullptr, ALC_DEFAULT_DEVICE_SPECIFIER))
{
cellMic.notice("Found default capture device: '%s'", alc_device);
enumerated_devices.push_back(alc_device);
}
}
}
ALCdevice* microphone_device::open_device(const std::string& name, u32 samplingrate, ALCenum num_al_channels, u32 buf_size)
{
if (std::none_of(enumerated_devices.cbegin(), enumerated_devices.cend(), [&name](const std::string& dev){ return dev == name; }))
{
cellMic.error("Capture device '%s' not in enumerated devices", name);
}
ALCdevice* device = alcCaptureOpenDevice(name.c_str(), samplingrate, num_al_channels, buf_size);
if (ALCenum err = alcGetError(device); err != ALC_NO_ERROR || !device)
{
cellMic.warning("Failed to open capture device '%s' (error=%s, device=*0x%x, samplingrate=%d, num_al_channels=0x%x, buf_size=%d)", name, fmt::alc_error{device, err}, device, samplingrate, num_al_channels, buf_size);
device = nullptr;
}
return device;
}
#endif
void microphone_device::get_data(const u32 num_samples)
{
if (num_samples == 0)

View file

@ -326,6 +326,11 @@ private:
static inline void variable_byteswap(const void* src, void* dst);
inline u32 convert_16_bit_pcm_to_float(const std::vector<u8>& buffer, u32 num_bytes);
#ifndef WITHOUT_OPENAL
void enumerate_devices();
ALCdevice* open_device(const std::string& name, u32 samplingrate, ALCenum num_al_channels, u32 buf_size);
#endif
u32 capture_audio();
void get_data(const u32 num_samples);
@ -345,6 +350,7 @@ private:
std::vector<u8> buf;
};
std::vector<std::string> enumerated_devices;
std::vector<mic_device> devices;
std::vector<u8> temp_buf;
std::vector<u8> float_buf;
@ -376,7 +382,7 @@ public:
void wake_up();
// Returns index of registered device
u32 register_device(const std::string& name);
u32 register_device(const std::string& device_name);
void unregister_device(u32 dev_num);
bool check_device(u32 dev_num);

View file

@ -244,7 +244,7 @@ static std::vector<SaveDataEntry> get_save_entries(const std::string& base_dir,
continue;
}
SaveDataEntry save_entry;
SaveDataEntry save_entry {};
save_entry.dirName = psf::get_string(psf, "SAVEDATA_DIRECTORY");
save_entry.listParam = psf::get_string(psf, "SAVEDATA_LIST_PARAM");
save_entry.title = psf::get_string(psf, "TITLE");
@ -307,7 +307,7 @@ static error_code select_and_delete(ppu_thread& ppu)
// Display a blocking Save Data List asynchronously in the GUI thread.
if (auto save_dialog = Emu.GetCallbacks().get_save_dialog())
{
selected = save_dialog->ShowSaveDataList(save_entries, focused, SAVEDATA_OP_LIST_DELETE, vm::null, g_fxo->get<savedata_manager>().enable_overlay);
selected = save_dialog->ShowSaveDataList(base_dir, save_entries, focused, SAVEDATA_OP_LIST_DELETE, vm::null, g_fxo->get<savedata_manager>().enable_overlay);
}
// Reschedule after a blocking dialog returns
@ -326,7 +326,7 @@ static error_code select_and_delete(ppu_thread& ppu)
focused = save_entries.empty() ? -1 : selected;
// Get information from the selected entry
SaveDataEntry entry = save_entries[selected];
const SaveDataEntry& entry = ::at32(save_entries, selected);
const std::string info = entry.title + "\n" + entry.subtitle + "\n" + entry.details;
// Reusable display message string
@ -760,7 +760,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
result->userdata = userdata; // probably should be assigned only once (allows the callback to change it)
SaveDataEntry save_entry;
SaveDataEntry save_entry {};
if (setList)
{
@ -820,7 +820,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
break;
}
SaveDataEntry save_entry2;
SaveDataEntry save_entry2 {};
save_entry2.dirName = psf::get_string(psf, "SAVEDATA_DIRECTORY");
save_entry2.listParam = psf::get_string(psf, "SAVEDATA_LIST_PARAM");
save_entry2.title = psf::get_string(psf, "TITLE");
@ -1183,7 +1183,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
// Display a blocking Save Data List asynchronously in the GUI thread.
if (auto save_dialog = Emu.GetCallbacks().get_save_dialog())
{
selected = save_dialog->ShowSaveDataList(save_entries, focused, operation, listSet, g_fxo->get<savedata_manager>().enable_overlay);
selected = save_dialog->ShowSaveDataList(base_dir, save_entries, focused, operation, listSet, g_fxo->get<savedata_manager>().enable_overlay);
}
else
{
@ -1214,8 +1214,7 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
else
{
// Get information from the selected entry
SaveDataEntry entry = save_entries[selected];
message = get_confirmation_message(operation, entry);
message = get_confirmation_message(operation, ::at32(save_entries, selected));
}
// Yield before a blocking dialog is being spawned
@ -1345,14 +1344,14 @@ static NEVER_INLINE error_code savedata_op(ppu_thread& ppu, u32 operation, u32 v
else
{
// Get information from the selected entry
SaveDataEntry entry = save_entries[selected];
message = get_confirmation_message(operation, entry);
message = get_confirmation_message(operation, ::at32(save_entries, selected));
}
// Yield before a blocking dialog is being spawned
lv2_obj::sleep(ppu);
// Get user confirmation by opening a blocking dialog
// TODO: show fixedSet->newIcon
s32 return_code = CELL_MSGDIALOG_BUTTON_NONE;
error_code res = open_msg_dialog(true, CELL_MSGDIALOG_TYPE_SE_TYPE_NORMAL | CELL_MSGDIALOG_TYPE_BUTTON_TYPE_YESNO, vm::make_str(message), msg_dialog_source::_cellSaveData, vm::null, vm::null, vm::null, &return_code);

View file

@ -361,5 +361,5 @@ class SaveDialogBase
public:
virtual ~SaveDialogBase();
virtual s32 ShowSaveDataList(std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay) = 0;
virtual s32 ShowSaveDataList(const std::string& base_dir, std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay) = 0;
};

View file

@ -4134,7 +4134,7 @@ s32 _spurs::create_task(vm::ptr<CellSpursTaskset> taskset, vm::ptr<u32> task_id,
u32 tmp_task_id;
vm::light_op(vm::_ref<atomic_be_t<v128>>(taskset.ptr(&CellSpursTaskset::enabled).addr()), [&](atomic_be_t<v128>& ptr)
vm::light_op(*vm::_ptr<atomic_be_t<v128>>(taskset.ptr(&CellSpursTaskset::enabled).addr()), [&](atomic_be_t<v128>& ptr)
{
// NOTE: Realfw processes this using 4 32-bits atomic loops
// But here its processed within a single 128-bit atomic op

View file

@ -1594,12 +1594,12 @@ s32 spursTasksetProcessRequest(spu_thread& spu, s32 request, u32* taskId, u32* i
spursHalt(spu);
}
vm::_ref<v128>(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::waiting)) = waiting;
vm::_ref<v128>(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::running)) = running;
vm::_ref<v128>(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::ready)) = ready;
vm::_ref<v128>(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::pending_ready)) = v128{};
vm::_ref<v128>(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::enabled)) = enabled;
vm::_ref<v128>(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::signalled)) = signalled;
// vm::_ref<v128>(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::waiting)) = waiting;
// vm::_ref<v128>(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::running)) = running;
// vm::_ref<v128>(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::ready)) = ready;
// vm::_ref<v128>(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::pending_ready)) = v128{};
// vm::_ref<v128>(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::enabled)) = enabled;
// vm::_ref<v128>(ctxt->taskset.addr() + ::offset32(&CellSpursTaskset::signalled)) = signalled;
std::memcpy(spu._ptr<void>(0x2700), spu._ptr<void>(0x100), 128); // Copy data
}//);

View file

@ -546,6 +546,11 @@ error_code sceNpTrophyDestroyContext(u32 context)
return CELL_OK;
}
struct register_context_thread_name
{
static constexpr std::string_view thread_name = "Trophy Register Thread";
};
error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle, vm::ptr<SceNpTrophyStatusCallback> statusCb, vm::ptr<void> arg, u64 options)
{
sceNpTrophy.warning("sceNpTrophyRegisterContext(context=0x%x, handle=0x%x, statusCb=*0x%x, arg=*0x%x, options=0x%llx)", context, handle, statusCb, arg, options);
@ -709,57 +714,77 @@ error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle,
ensure(tropusr->Load(trophyUsrPath, trophyConfPath).success);
// This emulates vsh sending the events and ensures that not 2 events are processed at once
const std::pair<u32, s32> statuses[] =
{
{ SCE_NP_TROPHY_STATUS_PROCESSING_SETUP, 3 },
{ SCE_NP_TROPHY_STATUS_PROCESSING_PROGRESS, ::narrow<s32>(tropusr->GetTrophiesCount()) - 1 },
{ SCE_NP_TROPHY_STATUS_PROCESSING_FINALIZE, 4 },
{ SCE_NP_TROPHY_STATUS_PROCESSING_COMPLETE, 0 }
};
lock2.unlock();
struct register_context_thread : register_context_thread_name
{
void operator()(s32 progress_cb_count, u32 context, vm::ptr<SceNpTrophyStatusCallback> statusCb, vm::ptr<void> arg) const
{
// This emulates vsh sending the events and ensures that not 2 events are processed at once
const std::pair<SceNpTrophyStatus, s32> statuses[] =
{
{ SCE_NP_TROPHY_STATUS_PROCESSING_SETUP, 3 },
{ SCE_NP_TROPHY_STATUS_PROCESSING_PROGRESS, progress_cb_count },
{ SCE_NP_TROPHY_STATUS_PROCESSING_FINALIZE, std::max<s32>(progress_cb_count, 9) - 5 }, // Seems varying, little bit less than progress_cb_count
{ SCE_NP_TROPHY_STATUS_PROCESSING_COMPLETE, 0 }
};
// Create a counter which is destroyed after the function ends
const auto queued = std::make_shared<atomic_t<u32>>(0);
for (auto status : statuses)
{
for (s32 completed = 0; completed <= status.second; completed++)
{
// One status max per cellSysutilCheckCallback call
*queued += 1;
sysutil_register_cb([statusCb, status, context, completed, arg, queued](ppu_thread& cb_ppu) -> s32
{
// TODO: it is possible that we need to check the return value here as well.
statusCb(cb_ppu, context, status.first, completed, status.second, arg);
if (queued && (*queued)-- == 1)
{
queued->notify_one();
}
return 0;
});
u64 current = get_system_time();
const u64 until_max = current + 300'000;
const u64 until_min = current + 100'000;
// If too much time passes just send the rest of the events anyway
for (u32 old_value = *queued; current < (old_value ? until_max : until_min);
current = get_system_time(), old_value = *queued)
{
if (!old_value)
{
thread_ctrl::wait_for(until_min - current);
}
else
{
thread_ctrl::wait_on(*queued, old_value, until_max - current);
}
if (thread_ctrl::state() == thread_state::aborting)
{
return;
}
}
}
}
}
};
lv2_obj::sleep(ppu);
// Create a counter which is destroyed after the function ends
const auto queued = std::make_shared<atomic_t<u32>>(0);
g_fxo->get<named_thread<register_context_thread>>()(::narrow<s32>(tropusr->GetTrophiesCount()) - 1, context, statusCb, arg);
for (auto status : statuses)
{
// One status max per cellSysutilCheckCallback call
*queued += status.second;
for (s32 completed = 0; completed <= status.second; completed++)
{
sysutil_register_cb([statusCb, status, context, completed, arg, queued](ppu_thread& cb_ppu) -> s32
{
// TODO: it is possible that we need to check the return value here as well.
statusCb(cb_ppu, context, status.first, completed, status.second, arg);
if (queued && (*queued)-- == 1)
{
queued->notify_one();
}
return 0;
});
}
u64 current = get_system_time();
const u64 until = current + 300'000;
// If too much time passes just send the rest of the events anyway
for (u32 old_value; current < until && (old_value = *queued);
current = get_system_time())
{
thread_ctrl::wait_on(*queued, old_value, until - current);
if (ppu.is_stopped())
{
return {};
}
}
}
thread_ctrl::wait_for(200'000);
return CELL_OK;
}

View file

@ -135,7 +135,7 @@ struct SceNpTrophyFlagArray
be_t<u32> flag_bits[SCE_NP_TROPHY_FLAG_SETSIZE >> SCE_NP_TROPHY_FLAG_BITS_SHIFT];
};
enum
enum SceNpTrophyStatus : u32
{
SCE_NP_TROPHY_STATUS_UNKNOWN = 0,
SCE_NP_TROPHY_STATUS_NOT_INSTALLED = 1,

View file

@ -38,11 +38,13 @@ void ppubreak(ppu_thread& ppu)
}
}
#define PPU_WRITE(type, addr, value) vm::write<type>(addr, value, &ppu);
#define PPU_WRITE_8(addr, value) vm::write8(addr, value, &ppu);
#define PPU_WRITE_16(addr, value) vm::write16(addr, value, &ppu);
#define PPU_WRITE_32(addr, value) vm::write32(addr, value, &ppu);
#define PPU_WRITE_64(addr, value) vm::write64(addr, value, &ppu);
#else
#define PPU_WRITE(type, addr, value) vm::write<type>(addr, value);
#define PPU_WRITE_8(addr, value) vm::write8(addr, value);
#define PPU_WRITE_16(addr, value) vm::write16(addr, value);
#define PPU_WRITE_32(addr, value) vm::write32(addr, value);
@ -4573,7 +4575,7 @@ auto STVX()
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
const u64 addr = (op.ra ? ppu.gpr[op.ra] + ppu.gpr[op.rb] : ppu.gpr[op.rb]) & ~0xfull;
vm::_ref<v128>(vm::cast(addr)) = ppu.vr[op.vs];
PPU_WRITE(v128, vm::cast(addr), ppu.vr[op.vs]);
};
RETURN_(ppu, op);
}
@ -5074,7 +5076,7 @@ auto STVXL()
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
const u64 addr = (op.ra ? ppu.gpr[op.ra] + ppu.gpr[op.rb] : ppu.gpr[op.rb]) & ~0xfull;
vm::_ref<v128>(vm::cast(addr)) = ppu.vr[op.vs];
PPU_WRITE(v128, vm::cast(addr), ppu.vr[op.vs]);
};
RETURN_(ppu, op);
}
@ -5363,7 +5365,7 @@ auto STDBRX()
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
const u64 addr = op.ra ? ppu.gpr[op.ra] + ppu.gpr[op.rb] : ppu.gpr[op.rb];
vm::_ref<le_t<u64>>(vm::cast(addr)) = ppu.gpr[op.rs];
PPU_WRITE(le_t<u64>, vm::cast(addr), ppu.gpr[op.rs]);
};
RETURN_(ppu, op);
}
@ -5402,7 +5404,7 @@ auto STWBRX()
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
const u64 addr = op.ra ? ppu.gpr[op.ra] + ppu.gpr[op.rb] : ppu.gpr[op.rb];
vm::_ref<le_t<u32>>(vm::cast(addr)) = static_cast<u32>(ppu.gpr[op.rs]);
PPU_WRITE(le_t<u32>, vm::cast(addr), static_cast<u32>(ppu.gpr[op.rs]));
};
RETURN_(ppu, op);
}
@ -5415,7 +5417,7 @@ auto STFSX()
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
const u64 addr = op.ra ? ppu.gpr[op.ra] + ppu.gpr[op.rb] : ppu.gpr[op.rb];
vm::_ref<f32>(vm::cast(addr)) = static_cast<float>(ppu.fpr[op.frs]);
PPU_WRITE(f32, vm::cast(addr), static_cast<float>(ppu.fpr[op.frs]));
};
RETURN_(ppu, op);
}
@ -5446,7 +5448,7 @@ auto STFSUX()
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
const u64 addr = ppu.gpr[op.ra] + ppu.gpr[op.rb];
vm::_ref<f32>(vm::cast(addr)) = static_cast<float>(ppu.fpr[op.frs]);
PPU_WRITE(f32, vm::cast(addr), static_cast<float>(ppu.fpr[op.frs]));
ppu.gpr[op.ra] = addr;
};
RETURN_(ppu, op);
@ -5496,7 +5498,7 @@ auto STFDX()
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
const u64 addr = op.ra ? ppu.gpr[op.ra] + ppu.gpr[op.rb] : ppu.gpr[op.rb];
vm::_ref<f64>(vm::cast(addr)) = ppu.fpr[op.frs];
PPU_WRITE(f64, vm::cast(addr), ppu.fpr[op.frs]);
};
RETURN_(ppu, op);
}
@ -5509,7 +5511,7 @@ auto STFDUX()
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
const u64 addr = ppu.gpr[op.ra] + ppu.gpr[op.rb];
vm::_ref<f64>(vm::cast(addr)) = ppu.fpr[op.frs];
PPU_WRITE(f64, vm::cast(addr), ppu.fpr[op.frs]);
ppu.gpr[op.ra] = addr;
};
RETURN_(ppu, op);
@ -5664,7 +5666,7 @@ auto STHBRX()
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
const u64 addr = op.ra ? ppu.gpr[op.ra] + ppu.gpr[op.rb] : ppu.gpr[op.rb];
vm::_ref<le_t<u16>>(vm::cast(addr)) = static_cast<u16>(ppu.gpr[op.rs]);
PPU_WRITE(le_t<u16>, vm::cast(addr), static_cast<u16>(ppu.gpr[op.rs]));
};
RETURN_(ppu, op);
}
@ -6054,7 +6056,7 @@ auto STFS()
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
const u64 addr = op.ra || 1 ? ppu.gpr[op.ra] + op.simm16 : op.simm16;
vm::_ref<f32>(vm::cast(addr)) = static_cast<float>(ppu.fpr[op.frs]);
PPU_WRITE(f32, vm::cast(addr), static_cast<float>(ppu.fpr[op.frs]));
};
RETURN_(ppu, op);
}
@ -6067,7 +6069,7 @@ auto STFSU()
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
const u64 addr = ppu.gpr[op.ra] + op.simm16;
vm::_ref<f32>(vm::cast(addr)) = static_cast<float>(ppu.fpr[op.frs]);
PPU_WRITE(f32, vm::cast(addr), static_cast<float>(ppu.fpr[op.frs]));
ppu.gpr[op.ra] = addr;
};
RETURN_(ppu, op);
@ -6081,7 +6083,7 @@ auto STFD()
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
const u64 addr = op.ra || 1 ? ppu.gpr[op.ra] + op.simm16 : op.simm16;
vm::_ref<f64>(vm::cast(addr)) = ppu.fpr[op.frs];
PPU_WRITE(f64, vm::cast(addr), ppu.fpr[op.frs]);
};
RETURN_(ppu, op);
}
@ -6094,7 +6096,7 @@ auto STFDU()
static const auto exec = [](ppu_thread& ppu, ppu_opcode_t op) {
const u64 addr = ppu.gpr[op.ra] + op.simm16;
vm::_ref<f64>(vm::cast(addr)) = ppu.fpr[op.frs];
PPU_WRITE(f64, vm::cast(addr), ppu.fpr[op.frs]);
ppu.gpr[op.ra] = addr;
};
RETURN_(ppu, op);

View file

@ -3367,7 +3367,10 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
fmt::throw_exception("PPU %s: Unaligned address: 0x%08x", sizeof(T) == 4 ? "STWCX" : "STDCX", addr);
}
auto& data = vm::_ref<atomic_be_t<u64>>(addr & -8);
// Notify breakpoint handler
vm::write<void>(addr, T{0}, &ppu);
auto& data = const_cast<atomic_be_t<u64>&>(vm::_ref<atomic_be_t<u64>>(addr & -8));
auto& res = vm::reservation_acquire(addr);
const u64 rtime = ppu.rtime;
@ -4956,9 +4959,9 @@ bool ppu_initialize(const ppu_module<lv2_obj>& info, bool check_only, u64 file_s
return +code_ptr;
}
constexpr auto abs_diff = [](u64 a, u64 b) { return a <= b ? b - a : a - b; };
[[maybe_unused]] constexpr auto abs_diff = [](u64 a, u64 b) { return a <= b ? b - a : a - b; };
auto write_le = [](u8*& code, auto value)
[[maybe_unused]] auto write_le = [](u8*& code, auto value)
{
write_to_ptr<le_t<std::remove_cvref_t<decltype(value)>>>(code, value);
code += sizeof(value);
@ -5823,7 +5826,7 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module<lv2_obj>& module
min_addr = std::min<u32>(min_addr, mod_func.addr);
// Translate
if (const auto func = translator.Translate(mod_func))
if ([[maybe_unused]] const auto func = translator.Translate(mod_func))
{
#ifdef ARCH_X64 // TODO
// Run optimization passes
@ -5841,7 +5844,7 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module<lv2_obj>& module
// Run this only in one module for all functions compiled
if (module_part.jit_bounds)
{
if (const auto func = translator.GetSymbolResolver(module_part))
if ([[maybe_unused]] const auto func = translator.GetSymbolResolver(module_part))
{
#ifdef ARCH_X64 // TODO
// Run optimization passes

View file

@ -1290,7 +1290,7 @@ void PPUTranslator::VMADDFP(ppu_opcode_t op)
void PPUTranslator::VMAXFP(ppu_opcode_t op)
{
const auto [a, b] = get_vrs<f32[4]>(op.va, op.vb);
set_vr(op.vd, vec_handle_result(bitcast<f32[4]>(bitcast<u32[4]>(fmax(a, b)) & bitcast<u32[4]>(fmax(b, a)))));
set_vr(op.vd, vec_handle_result(select(fcmp_ord(a < b) | fcmp_uno(b != b), b, a)));
}
void PPUTranslator::VMAXSB(ppu_opcode_t op)
@ -1352,7 +1352,7 @@ void PPUTranslator::VMHRADDSHS(ppu_opcode_t op)
void PPUTranslator::VMINFP(ppu_opcode_t op)
{
const auto [a, b] = get_vrs<f32[4]>(op.va, op.vb);
set_vr(op.vd, vec_handle_result(bitcast<f32[4]>(bitcast<u32[4]>(fmin(a, b)) | bitcast<u32[4]>(fmin(b, a)))));
set_vr(op.vd, vec_handle_result(select(fcmp_ord(a > b) | fcmp_uno(b != b), b, a)));
}
void PPUTranslator::VMINSB(ppu_opcode_t op)
@ -4653,7 +4653,7 @@ void PPUTranslator::MTFSF(ppu_opcode_t op)
for (u32 i = 16; i < 20; i++)
{
if (i != 1 && i != 2 && (op.flm & (128 >> (i / 4))) != 0)
if ((op.flm & (128 >> (i / 4))) != 0)
{
SetFPSCRBit(i, Trunc(m_ir->CreateLShr(value, i ^ 31), GetType<bool>()), false);
}

View file

@ -1237,7 +1237,7 @@ void spu_thread::dump_regs(std::string& ret, std::any& /*custom_data*/) const
if (const_value != r)
{
// Expectation of pretictable code path has not been met (such as a branch directly to the instruction)
// Expectation of predictable code path has not been met (such as a branch directly to the instruction)
is_const = false;
}
@ -1447,7 +1447,7 @@ std::vector<std::pair<u32, u32>> spu_thread::dump_callstack_list() const
if (v != v128::from32r(addr))
{
// 1) Non-zero lower words are invalid (because BRSL-like instructions generate only zeroes)
// 2) Bits normally masked out by indirect braches are considered invalid
// 2) Bits normally masked out by indirect branches are considered invalid
return true;
}
@ -3833,14 +3833,14 @@ bool spu_thread::do_putllc(const spu_mfc_cmd& args)
{
if (addr - spurs_addr <= 0x80)
{
mov_rdata(vm::_ref<spu_rdata_t>(addr), to_write);
mov_rdata(*vm::_ptr<spu_rdata_t>(addr), to_write);
res += 64;
return true;
}
}
else if (!g_use_rtm)
{
vm::_ref<atomic_t<u32>>(addr) += 0;
*vm::_ptr<atomic_t<u32>>(addr) += 0;
}
if (g_use_rtm) [[likely]]

View file

@ -373,7 +373,7 @@ const std::array<std::pair<ppu_intrp_func_t, std::string_view>, 1024> g_ppu_sysc
uns_func, uns_func, uns_func, uns_func, uns_func, //255-259 UNS
NULL_FUNC(sys_spu_image_open_by_fd), //260 (0x104)
BIND_SYSC(sys_spu_image_open_by_fd), //260 (0x104)
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //261-269 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //270-279 UNS

View file

@ -502,7 +502,7 @@ error_code _sys_lwcond_queue_wait(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id
if (!cond || !mutex)
{
return CELL_ESRCH;
return { CELL_ESRCH, fmt::format("lwmutex_id: 0x%x, lwcond_id: 0x%x", lwmutex_id, lwcond_id) };
}
if (ppu.state & cpu_flag::again)

View file

@ -183,7 +183,12 @@ error_code _sys_lwmutex_lock(ppu_thread& ppu, u32 lwmutex_id, u64 timeout)
if (!mutex)
{
return CELL_ESRCH;
if (lwmutex_id >> 24 == lv2_lwmutex::id_base >> 24)
{
return { CELL_ESRCH, lwmutex_id };
}
return { CELL_ESRCH, "Invalid ID" };
}
if (mutex.ret)
@ -313,7 +318,12 @@ error_code _sys_lwmutex_trylock(ppu_thread& ppu, u32 lwmutex_id)
if (!mutex)
{
return CELL_ESRCH;
if (lwmutex_id >> 24 == lv2_lwmutex::id_base >> 24)
{
return { CELL_ESRCH, lwmutex_id };
}
return { CELL_ESRCH, "Invalid ID" };
}
if (!mutex.ret)

View file

@ -181,7 +181,7 @@ error_code sys_rsx_memory_allocate(cpu_thread& cpu, vm::ptr<u32> mem_handle, vm:
if (u32 addr = rsx::get_current_renderer()->driver_info)
{
vm::_ref<RsxDriverInfo>(addr).memory_size = size;
vm::_ptr<RsxDriverInfo>(addr)->memory_size = size;
}
*mem_addr = rsx::constants::local_mem_base;
@ -265,7 +265,7 @@ error_code sys_rsx_context_allocate(cpu_thread& cpu, vm::ptr<u32> context_id, vm
*lpar_driver_info = dma_address + 0x100000;
*lpar_reports = dma_address + 0x200000;
auto &reports = vm::_ref<RsxReports>(vm::cast(*lpar_reports));
auto &reports = *vm::_ptr<RsxReports>(vm::cast(*lpar_reports));
std::memset(&reports, 0, sizeof(RsxReports));
for (usz i = 0; i < std::size(reports.notify); ++i)
@ -273,10 +273,10 @@ error_code sys_rsx_context_allocate(cpu_thread& cpu, vm::ptr<u32> context_id, vm
for (usz i = 0; i < std::size(reports.semaphore); i += 4)
{
reports.semaphore[i + 0].val.raw() = 0x1337C0D3;
reports.semaphore[i + 1].val.raw() = 0x1337BABE;
reports.semaphore[i + 2].val.raw() = 0x1337BEEF;
reports.semaphore[i + 3].val.raw() = 0x1337F001;
reports.semaphore[i + 0] = 0x1337C0D3;
reports.semaphore[i + 1] = 0x1337BABE;
reports.semaphore[i + 2] = 0x1337BEEF;
reports.semaphore[i + 3] = 0x1337F001;
}
for (usz i = 0; i < std::size(reports.report); ++i)
@ -286,7 +286,7 @@ error_code sys_rsx_context_allocate(cpu_thread& cpu, vm::ptr<u32> context_id, vm
reports.report[i].pad = -1;
}
auto &driverInfo = vm::_ref<RsxDriverInfo>(vm::cast(*lpar_driver_info));
auto &driverInfo = *vm::_ptr<RsxDriverInfo>(vm::cast(*lpar_driver_info));
std::memset(&driverInfo, 0, sizeof(RsxDriverInfo));
@ -303,7 +303,7 @@ error_code sys_rsx_context_allocate(cpu_thread& cpu, vm::ptr<u32> context_id, vm
render->driver_info = vm::cast(*lpar_driver_info);
auto &dmaControl = vm::_ref<RsxDmaControl>(vm::cast(*lpar_dma_control));
auto &dmaControl = *vm::_ptr<RsxDmaControl>(vm::cast(*lpar_dma_control));
dmaControl.get = 0;
dmaControl.put = 0;
dmaControl.ref = 0; // Set later to -1 by cellGcmSys
@ -527,7 +527,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
return { CELL_EINVAL, "context_id is 0x%x", context_id };
}
auto &driverInfo = vm::_ref<RsxDriverInfo>(render->driver_info);
auto &driverInfo = *vm::_ptr<RsxDriverInfo>(render->driver_info);
switch (package_id)
{
case 0x001: // FIFO
@ -862,7 +862,7 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
// seems gcmSysWaitLabel uses this offset, so lets set it to 0 every flip
// NOTE: Realhw resets 16 bytes of this semaphore for some reason
vm::_ref<atomic_t<u128>>(render->label_addr + 0x10).store(u128{});
vm::_ptr<atomic_t<u128>>(render->label_addr + 0x10)->store(u128{});
render->send_event(0, SYS_RSX_EVENT_FLIP_BASE << 1, 0);
break;

View file

@ -87,10 +87,7 @@ struct RsxDmaControl
be_t<u32> unk1;
};
struct RsxSemaphore
{
atomic_be_t<u32> val;
};
using RsxSemaphore = be_t<u32>;
struct alignas(16) RsxNotify
{

View file

@ -66,13 +66,14 @@ void fmt_class_string<spu_stop_syscall>::format(std::string& out, u64 arg)
});
}
void sys_spu_image::load(const fs::file& stream)
bool sys_spu_image::load(const fs::file& stream)
{
const spu_exec_object obj{stream, 0, elf_opt::no_sections + elf_opt::no_data};
if (obj != elf_error::ok)
{
fmt::throw_exception("Failed to load SPU image: %s", obj.get_error());
sys_spu.error("Failed to load SPU image: %s", obj.get_error());
return false;
}
for (const auto& shdr : obj.shdrs)
@ -94,7 +95,7 @@ void sys_spu_image::load(const fs::file& stream)
const s32 nsegs = sys_spu_image::get_nsegs(obj.progs);
const u32 mem_size = nsegs * sizeof(sys_spu_segment) + ::size32(stream);
const vm::ptr<sys_spu_segment> segs = vm::cast(vm::alloc(mem_size, vm::main));
const vm::ptr<sys_spu_segment> segs = vm::cast(vm::reserve_map(vm::user64k, 0, 0x10000000)->alloc(mem_size));
//const u32 entry = obj.header.e_entry;
@ -116,6 +117,7 @@ void sys_spu_image::load(const fs::file& stream)
this->segs = vm::null;
vm::page_protect(segs.addr(), utils::align(mem_size, 4096), 0, 0, vm::page_writable);
return true;
}
void sys_spu_image::free() const
@ -388,19 +390,43 @@ struct spu_limits_t
SAVESTATE_INIT_POS(47);
bool check(const limits_data& init) const
bool check_valid(const limits_data& init) const
{
const u32 physical_spus_count = init.physical;
const u32 controllable_spu_count = init.controllable;
const u32 spu_limit = init.spu_limit != umax ? init.spu_limit : max_spu;
const u32 raw_limit = init.raw_limit != umax ? init.raw_limit : max_raw;
if (spu_limit + raw_limit > 6 || physical_spus_count > spu_limit || controllable_spu_count > spu_limit)
{
return false;
}
return true;
}
bool check_busy(const limits_data& init) const
{
u32 physical_spus_count = init.physical;
u32 raw_spu_count = init.raw_spu;
u32 controllable_spu_count = init.controllable;
u32 system_coop = init.controllable != 0 && init.physical != 0 ? 1 : 0;
const u32 spu_limit = init.spu_limit != umax ? init.spu_limit : max_spu;
const u32 raw_limit = init.raw_limit != umax ? init.raw_limit : max_raw;
idm::select<lv2_spu_group>([&](u32, lv2_spu_group& group)
{
if (group.has_scheduler_context)
if (group.type & SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)
{
controllable_spu_count = std::max(controllable_spu_count, group.max_num);
system_coop++;
controllable_spu_count = std::max<u32>(controllable_spu_count, 1);
physical_spus_count += group.max_num - 1;
}
else if (group.has_scheduler_context)
{
controllable_spu_count = std::max<u32>(controllable_spu_count, group.max_num);
}
else
{
@ -410,11 +436,18 @@ struct spu_limits_t
raw_spu_count += spu_thread::g_raw_spu_ctr;
if (spu_limit + raw_limit > 6 || raw_spu_count > raw_limit || physical_spus_count >= spu_limit || physical_spus_count + controllable_spu_count > spu_limit)
// physical_spus_count >= spu_limit returns EBUSY, not EINVAL!
if (spu_limit + raw_limit > 6 || raw_spu_count > raw_limit || physical_spus_count >= spu_limit || physical_spus_count > spu_limit || controllable_spu_count > spu_limit)
{
return false;
}
if (system_coop > 1)
{
// Cannot have more than one SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM group at a time
return false;
}
return true;
}
};
@ -437,7 +470,7 @@ error_code sys_spu_initialize(ppu_thread& ppu, u32 max_usable_spu, u32 max_raw_s
std::lock_guard lock(limits.mutex);
if (!limits.check(limits_data{.spu_limit = max_usable_spu - max_raw_spu, .raw_limit = max_raw_spu}))
if (!limits.check_busy(limits_data{.spu_limit = max_usable_spu - max_raw_spu, .raw_limit = max_raw_spu}))
{
return CELL_EBUSY;
}
@ -486,15 +519,52 @@ error_code sys_spu_image_open(ppu_thread& ppu, vm::ptr<sys_spu_image> img, vm::c
u128 klic = g_fxo->get<loaded_npdrm_keys>().last_key();
const fs::file elf_file = decrypt_self(std::move(file), reinterpret_cast<u8*>(&klic));
const fs::file elf_file = decrypt_self(file, reinterpret_cast<const u8*>(&klic));
if (!elf_file)
if (!elf_file || !img->load(elf_file))
{
sys_spu.error("sys_spu_image_open(): file %s is illegal for SPU image!", path);
return {CELL_ENOEXEC, path};
}
img->load(elf_file);
return CELL_OK;
}
error_code sys_spu_image_open_by_fd(ppu_thread& ppu, vm::ptr<sys_spu_image> img, s32 fd, s64 offset)
{
ppu.state += cpu_flag::wait;
sys_spu.warning("sys_spu_image_open_by_fd(img=*0x%x, fd=%d, offset=0x%x)", img, fd, offset);
const auto file = idm::get_unlocked<lv2_fs_object, lv2_file>(fd);
if (!file)
{
return CELL_EBADF;
}
if (offset < 0)
{
return CELL_ENOEXEC;
}
std::lock_guard lock(file->mp->mutex);
if (!file->file)
{
return CELL_EBADF;
}
u128 klic = g_fxo->get<loaded_npdrm_keys>().last_key();
const fs::file elf_file = decrypt_self(lv2_file::make_view(file, offset), reinterpret_cast<const u8*>(&klic));
if (!img->load(elf_file))
{
sys_spu.error("sys_spu_image_open(): file %s is illegal for SPU image!", file->name.data());
return {CELL_ENOEXEC, file->name.data()};
}
return CELL_OK;
}
@ -526,7 +596,7 @@ error_code _sys_spu_image_close(ppu_thread& ppu, vm::ptr<sys_spu_image> img)
return CELL_ESRCH;
}
ensure(vm::dealloc(handle->segs.addr(), vm::main));
ensure(vm::dealloc(handle->segs.addr(), vm::user64k));
return CELL_OK;
}
@ -845,23 +915,24 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num
switch (type)
{
case 0x0:
case 0x4:
case 0x18:
case SYS_SPU_THREAD_GROUP_TYPE_MEMORY_FROM_CONTAINER:
case SYS_SPU_THREAD_GROUP_TYPE_EXCLUSIVE_NON_CONTEXT:
{
break;
}
case 0x20:
case 0x22:
case 0x24:
case 0x26:
case SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM:
case (SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM | 0x2):
case (SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM | 0x4):
case (SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM | 0x6):
{
if (type == 0x22 || type == 0x26)
{
needs_root = true;
}
min_threads = 2; // That's what appears from reversing
// For a single thread that is being shared with system (the cooperative victim)
min_threads = 2;
break;
}
@ -901,7 +972,7 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num
if (is_system_coop)
{
// Constant size, unknown what it means
// For a single thread that is being shared with system (the cooperative victim)
mem_size = SPU_LS_SIZE;
}
else if (type & SYS_SPU_THREAD_GROUP_TYPE_NON_CONTEXT)
@ -952,7 +1023,29 @@ error_code sys_spu_thread_group_create(ppu_thread& ppu, vm::ptr<u32> id, u32 num
std::unique_lock lock(limits.mutex);
if (!limits.check(use_scheduler ? limits_data{.controllable = num} : limits_data{.physical = num}))
limits_data group_limits{};
if (is_system_coop)
{
group_limits.controllable = 1;
group_limits.physical = num - 1;
}
else if (use_scheduler)
{
group_limits.controllable = num;
}
else
{
group_limits.physical = num;
}
if (!limits.check_valid(group_limits))
{
ct->free(mem_size);
return CELL_EINVAL;
}
if (!limits.check_busy(group_limits))
{
ct->free(mem_size);
return CELL_EBUSY;
@ -1135,6 +1228,11 @@ error_code sys_spu_thread_group_suspend(ppu_thread& ppu, u32 id)
return CELL_EINVAL;
}
if (group->type & SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)
{
return CELL_EINVAL;
}
std::lock_guard lock(group->mutex);
CellError error;
@ -1218,6 +1316,11 @@ error_code sys_spu_thread_group_resume(ppu_thread& ppu, u32 id)
return CELL_EINVAL;
}
if (group->type & SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)
{
return CELL_EINVAL;
}
struct notify_on_exit
{
usz index = umax;
@ -1565,6 +1668,11 @@ error_code sys_spu_thread_group_set_priority(ppu_thread& ppu, u32 id, s32 priori
return CELL_EINVAL;
}
if (group->type & SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)
{
return CELL_EINVAL;
}
group->prio.atomic_op([&](std::common_type_t<decltype(lv2_spu_group::prio)>& prio)
{
prio.prio = priority;
@ -1592,6 +1700,11 @@ error_code sys_spu_thread_group_get_priority(ppu_thread& ppu, u32 id, vm::ptr<s3
{
*priority = 0;
}
else if (group->type & SYS_SPU_THREAD_GROUP_TYPE_COOPERATE_WITH_SYSTEM)
{
// Regardless of the value being set in group creation
*priority = 15;
}
else
{
*priority = group->prio.load().prio;
@ -1751,7 +1864,7 @@ error_code sys_spu_thread_write_spu_mb(ppu_thread& ppu, u32 id, u32 value)
{
ppu.state += cpu_flag::wait;
sys_spu.warning("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x)", id, value);
sys_spu.trace("sys_spu_thread_write_spu_mb(id=0x%x, value=0x%x)", id, value);
const auto [thread, group] = lv2_spu_group::get_thread(id);
@ -2275,7 +2388,7 @@ error_code sys_raw_spu_create(ppu_thread& ppu, vm::ptr<u32> id, vm::ptr<void> at
std::lock_guard lock(limits.mutex);
if (!limits.check(limits_data{.raw_spu = 1}))
if (!limits.check_busy(limits_data{.raw_spu = 1}))
{
return CELL_EAGAIN;
}
@ -2331,7 +2444,7 @@ error_code sys_isolated_spu_create(ppu_thread& ppu, vm::ptr<u32> id, vm::ptr<voi
std::lock_guard lock(limits.mutex);
if (!limits.check(limits_data{.raw_spu = 1}))
if (!limits.check_busy(limits_data{.raw_spu = 1}))
{
return CELL_EAGAIN;
}

View file

@ -225,7 +225,7 @@ struct sys_spu_image
return num_segs;
}
void load(const fs::file& stream);
bool load(const fs::file& stream);
void free() const;
static void deploy(u8* loc, std::span<const sys_spu_segment> segs, bool is_verbose = true);
};
@ -354,6 +354,7 @@ class ppu_thread;
error_code sys_spu_initialize(ppu_thread&, u32 max_usable_spu, u32 max_raw_spu);
error_code _sys_spu_image_get_information(ppu_thread&, vm::ptr<sys_spu_image> img, vm::ptr<u32> entry_point, vm::ptr<s32> nsegs);
error_code sys_spu_image_open(ppu_thread&, vm::ptr<sys_spu_image> img, vm::cptr<char> path);
error_code sys_spu_image_open_by_fd(ppu_thread&, vm::ptr<sys_spu_image> img, s32 fd, s64 offset);
error_code _sys_spu_image_import(ppu_thread&, vm::ptr<sys_spu_image> img, u32 src, u32 size, u32 arg4);
error_code _sys_spu_image_close(ppu_thread&, vm::ptr<sys_spu_image> img);
error_code _sys_spu_image_get_segments(ppu_thread&, vm::ptr<sys_spu_image> img, vm::ptr<sys_spu_segment> segments, s32 nseg);

View file

@ -553,7 +553,7 @@ error_code sys_ss_individual_info_manager(u64 pkg_id, u64 a2, vm::ptr<u64> out_s
case 0x17002:
{
// TODO
vm::_ref<u64>(a5) = a4; // Write back size of buffer
vm::write<u64>(a5, a4); // Write back size of buffer
break;
}
// Get EID size

View file

@ -483,8 +483,6 @@ namespace vm
}
}
bool to_prepare_memory = true;
for (u64 i = 0;; i++)
{
auto& bits = get_range_lock_bits(true);
@ -512,22 +510,11 @@ namespace vm
if (i < 100)
{
if (to_prepare_memory)
{
// We have some spare time, prepare cache lines (todo: reservation tests here)
utils::prefetch_write(vm::get_super_ptr(addr));
utils::prefetch_write(vm::get_super_ptr(addr) + 64);
to_prepare_memory = false;
}
busy_wait(200);
}
else
{
std::this_thread::yield();
// Thread may have been switched or the cache clue has been undermined, cache needs to be prapred again
to_prepare_memory = true;
}
}
@ -591,13 +578,6 @@ namespace vm
break;
}
if (to_prepare_memory)
{
utils::prefetch_write(vm::get_super_ptr(addr));
utils::prefetch_write(vm::get_super_ptr(addr) + 64);
to_prepare_memory = false;
}
utils::pause();
}
@ -607,13 +587,6 @@ namespace vm
{
while (!(ptr->state & cpu_flag::wait))
{
if (to_prepare_memory)
{
utils::prefetch_write(vm::get_super_ptr(addr));
utils::prefetch_write(vm::get_super_ptr(addr) + 64);
to_prepare_memory = false;
}
utils::pause();
}
}

View file

@ -8,14 +8,14 @@
#include "util/to_endian.hpp"
class ppu_thread;
#ifdef RPCS3_HAS_MEMORY_BREAKPOINTS
#include "rpcs3qt/breakpoint_handler.h"
#include "util/logs.hpp"
LOG_CHANNEL(debugbp_log, "DebugBP");
class ppu_thread;
void ppubreak(ppu_thread& ppu);
#endif
@ -282,9 +282,10 @@ namespace vm
}
// Convert specified PS3 address to a reference of specified (possibly converted to BE) type
template <typename T, typename U> inline to_be_t<T>& _ref(const U& addr)
// Const lvalue: prevent abused writes
template <typename T, typename U> inline const to_be_t<T>& _ref(const U& addr)
{
return *static_cast<to_be_t<T>*>(base(addr));
return *static_cast<const to_be_t<T>*>(base(addr));
}
// Access memory bypassing memory protection
@ -300,42 +301,43 @@ namespace vm
}
#ifdef RPCS3_HAS_MEMORY_BREAKPOINTS
inline void write16(u32 addr, be_t<u16> value, ppu_thread* ppu = nullptr)
template <typename T, typename U = T>
inline void write(u32 addr, U value, ppu_thread* ppu = nullptr)
#else
inline void write16(u32 addr, be_t<u16> value)
template <typename T, typename U = T>
inline void write(u32 addr, U value, ppu_thread* = nullptr)
#endif
{
_ref<u16>(addr) = value;
using dest_t = std::conditional_t<std::is_void_v<T>, U, T>;
if constexpr (!std::is_void_v<T>)
{
*_ptr<dest_t>(addr) = value;
}
#ifdef RPCS3_HAS_MEMORY_BREAKPOINTS
if (ppu && g_breakpoint_handler.HasBreakpoint(addr, breakpoint_types::bp_write))
{
debugbp_log.success("BPMW: breakpoint writing(16) 0x%x at 0x%x", value, addr);
debugbp_log.success("BPMW: breakpoint writing(%d) 0x%x at 0x%x",
sizeof(dest_t) * CHAR_BIT, value, addr);
ppubreak(*ppu);
}
#endif
}
inline void write16(u32 addr, be_t<u16> value, ppu_thread* ppu = nullptr)
{
write<be_t<u16>>(addr, value, ppu);
}
inline const be_t<u32>& read32(u32 addr)
{
return _ref<u32>(addr);
}
#ifdef RPCS3_HAS_MEMORY_BREAKPOINTS
inline void write32(u32 addr, be_t<u32> value, ppu_thread* ppu = nullptr)
#else
inline void write32(u32 addr, be_t<u32> value)
#endif
{
_ref<u32>(addr) = value;
#ifdef RPCS3_HAS_MEMORY_BREAKPOINTS
if (ppu && g_breakpoint_handler.HasBreakpoint(addr, breakpoint_types::bp_write))
{
debugbp_log.success("BPMW: breakpoint writing(32) 0x%x at 0x%x", value, addr);
ppubreak(*ppu);
}
#endif
write<be_t<u32>>(addr, value, ppu);
}
inline const be_t<u64>& read64(u32 addr)
@ -343,21 +345,9 @@ namespace vm
return _ref<u64>(addr);
}
#ifdef RPCS3_HAS_MEMORY_BREAKPOINTS
inline void write64(u32 addr, be_t<u64> value, ppu_thread* ppu = nullptr)
#else
inline void write64(u32 addr, be_t<u64> value)
#endif
{
_ref<u64>(addr) = value;
#ifdef RPCS3_HAS_MEMORY_BREAKPOINTS
if (ppu && g_breakpoint_handler.HasBreakpoint(addr, breakpoint_types::bp_write))
{
debugbp_log.success("BPMW: breakpoint writing(64) 0x%x at 0x%x", value, addr);
ppubreak(*ppu);
}
#endif
write<be_t<u64>>(addr, value, ppu);
}
void init();

View file

@ -6,6 +6,14 @@
#include "util/v128.hpp"
#include "util/simd.hpp"
#if defined(ARCH_ARM64)
#if !defined(_MSC_VER)
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif
#undef FORCE_INLINE
#include "Emu/CPU/sse2neon.h"
#endif
#if !defined(_MSC_VER)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
@ -404,57 +412,76 @@ namespace
}
};
template <typename T>
NEVER_INLINE std::tuple<T, T, u32> upload_untouched_skip_restart(std::span<to_be_t<const T>> src, std::span<T> dst, T restart_index)
{
T min_index = index_limit<T>();
T max_index = 0;
u32 written = 0;
u32 length = ::size32(src);
for (u32 i = written; i < length; ++i)
template <typename T>
NEVER_INLINE std::tuple<T, T, u32> upload_untouched_skip_restart(std::span<to_be_t<const T>> src, std::span<T> dst, T restart_index)
{
T index = src[i];
if (index != restart_index)
T min_index = index_limit<T>();
T max_index = 0;
u32 written = 0;
u32 length = ::size32(src);
for (u32 i = written; i < length; ++i)
{
dst[written++] = min_max(min_index, max_index, index);
T index = src[i];
if (index != restart_index)
{
dst[written++] = min_max(min_index, max_index, index);
}
}
return std::make_tuple(min_index, max_index, written);
}
return std::make_tuple(min_index, max_index, written);
}
template<typename T>
std::tuple<T, T, u32> upload_untouched(std::span<to_be_t<const T>> src, std::span<T> dst, rsx::primitive_type draw_mode, bool is_primitive_restart_enabled, u32 primitive_restart_index)
{
if (!is_primitive_restart_enabled)
template<typename T>
std::tuple<T, T, u32> upload_untouched(std::span<to_be_t<const T>> src, std::span<T> dst, rsx::primitive_type draw_mode, bool is_primitive_restart_enabled, u32 primitive_restart_index)
{
return untouched_impl::upload_untouched(src, dst);
}
else if constexpr (std::is_same_v<T, u16>)
{
if (primitive_restart_index > 0xffff)
if (!is_primitive_restart_enabled)
{
return untouched_impl::upload_untouched(src, dst);
}
else if constexpr (std::is_same_v<T, u16>)
{
if (primitive_restart_index > 0xffff)
{
return untouched_impl::upload_untouched(src, dst);
}
else if (is_primitive_disjointed(draw_mode))
{
return upload_untouched_skip_restart(src, dst, static_cast<u16>(primitive_restart_index));
}
else
{
return primitive_restart_impl::upload_untouched(src, dst, static_cast<u16>(primitive_restart_index));
}
}
else if (is_primitive_disjointed(draw_mode))
{
return upload_untouched_skip_restart(src, dst, static_cast<u16>(primitive_restart_index));
return upload_untouched_skip_restart(src, dst, primitive_restart_index);
}
else
{
return primitive_restart_impl::upload_untouched(src, dst, static_cast<u16>(primitive_restart_index));
return primitive_restart_impl::upload_untouched(src, dst, primitive_restart_index);
}
}
else if (is_primitive_disjointed(draw_mode))
void iota16(u16* dst, u32 count)
{
return upload_untouched_skip_restart(src, dst, primitive_restart_index);
unsigned i = 0;
#if defined(ARCH_X64) || defined(ARCH_ARM64)
const unsigned step = 8; // We do 8 entries per step
const __m128i vec_step = _mm_set1_epi16(8); // Constant to increment the raw values
__m128i values = _mm_set_epi16(7, 6, 5, 4, 3, 2, 1, 0);
__m128i* vec_ptr = reinterpret_cast<__m128i*>(dst);
for (; (i + step) <= count; i += step, vec_ptr++)
{
_mm_stream_si128(vec_ptr, values);
_mm_add_epi16(values, vec_step);
}
#endif
for (; i < count; ++i)
dst[i] = i;
}
else
{
return primitive_restart_impl::upload_untouched(src, dst, primitive_restart_index);
}
}
template<typename T>
std::tuple<T, T, u32> expand_indexed_triangle_fan(std::span<to_be_t<const T>> src, std::span<T> dst, bool is_primitive_restart_enabled, u32 primitive_restart_index)
@ -624,8 +651,7 @@ void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst,
switch (draw_mode)
{
case rsx::primitive_type::line_loop:
for (unsigned i = 0; i < count; ++i)
typedDst[i] = i;
iota16(typedDst, count);
typedDst[count] = 0;
return;
case rsx::primitive_type::triangle_fan:

View file

@ -20,29 +20,33 @@ protected:
template<int Alignment>
bool can_alloc(usz size) const
{
usz alloc_size = utils::align(size, Alignment);
usz aligned_put_pos = utils::align(m_put_pos, Alignment);
if (aligned_put_pos + alloc_size < m_size)
const usz alloc_size = utils::align(size, Alignment);
const usz aligned_put_pos = utils::align(m_put_pos, Alignment);
const usz alloc_end = aligned_put_pos + alloc_size;
if (alloc_end < m_size) [[ likely ]]
{
// range before get
if (aligned_put_pos + alloc_size < m_get_pos)
// Range before get
if (alloc_end < m_get_pos)
return true;
// range after get
// Range after get
if (aligned_put_pos > m_get_pos)
return true;
return false;
}
else
{
// ..]....[..get..
if (aligned_put_pos < m_get_pos)
return false;
// ..get..]...[...
// Actually all resources extending beyond heap space starts at 0
if (alloc_size > m_get_pos)
return false;
return true;
}
// ..]....[..get..
if (aligned_put_pos < m_get_pos)
return false;
// ..get..]...[...
// Actually all resources extending beyond heap space starts at 0
if (alloc_size > m_get_pos)
return false;
return true;
}
// Grow the buffer to hold at least size bytes
@ -53,10 +57,9 @@ protected:
}
usz m_size;
usz m_put_pos; // Start of free space
usz m_min_guard_size; //If an allocation touches the guard region, reset the heap to avoid going over budget
usz m_current_allocated_size;
usz m_largest_allocated_pool;
usz m_put_pos; // Start of free space
usz m_get_pos; // End of free space
usz m_min_guard_size; // If an allocation touches the guard region, reset the heap to avoid going over budget
char* m_name;
public:
@ -65,8 +68,6 @@ public:
data_heap(const data_heap&) = delete;
data_heap(data_heap&&) = delete;
usz m_get_pos; // End of free space
void init(usz heap_size, const char* buffer_name = "unnamed", usz min_guard_size=0x10000)
{
m_name = const_cast<char*>(buffer_name);
@ -75,10 +76,8 @@ public:
m_put_pos = 0;
m_get_pos = heap_size - 1;
//allocation stats
// Allocation stats
m_min_guard_size = min_guard_size;
m_current_allocated_size = 0;
m_largest_allocated_pool = 0;
}
template<int Alignment>
@ -89,24 +88,45 @@ public:
if (!can_alloc<Alignment>(size) && !grow(alloc_size))
{
fmt::throw_exception("[%s] Working buffer not big enough, buffer_length=%d allocated=%d requested=%d guard=%d largest_pool=%d",
m_name, m_size, m_current_allocated_size, size, m_min_guard_size, m_largest_allocated_pool);
fmt::throw_exception("[%s] Working buffer not big enough, buffer_length=%d requested=%d guard=%d",
m_name, m_size, size, m_min_guard_size);
}
const usz block_length = (aligned_put_pos - m_put_pos) + alloc_size;
m_current_allocated_size += block_length;
m_largest_allocated_pool = std::max(m_largest_allocated_pool, block_length);
if (aligned_put_pos + alloc_size < m_size)
const usz alloc_end = aligned_put_pos + alloc_size;
if (alloc_end < m_size)
{
m_put_pos = aligned_put_pos + alloc_size;
m_put_pos = alloc_end;
return aligned_put_pos;
}
else
m_put_pos = alloc_size;
return 0;
}
/*
* For use in cases where we take a fixed amount each time
*/
template<int Alignment, usz Size = Alignment>
usz static_alloc()
{
static_assert((Size & (Alignment - 1)) == 0);
ensure((m_put_pos & (Alignment - 1)) == 0);
if (!can_alloc<Alignment>(Size) && !grow(Size))
{
m_put_pos = alloc_size;
return 0;
fmt::throw_exception("[%s] Working buffer not big enough, buffer_length=%d requested=%d guard=%d",
m_name, m_size, Size, m_min_guard_size);
}
const usz alloc_end = m_put_pos + Size;
if (m_put_pos + Size < m_size)
{
m_put_pos = alloc_end;
return m_put_pos;
}
m_put_pos = Size;
return 0;
}
/**
@ -117,30 +137,20 @@ public:
return (m_put_pos > 0) ? m_put_pos - 1 : m_size - 1;
}
virtual bool is_critical() const
inline void set_get_pos(usz value)
{
const usz guard_length = std::max(m_min_guard_size, m_largest_allocated_pool);
return (m_current_allocated_size + guard_length) >= m_size;
m_get_pos = value;
}
void reset_allocation_stats()
{
m_current_allocated_size = 0;
m_largest_allocated_pool = 0;
m_get_pos = get_current_put_pos_minus_one();
}
// Updates the current_allocated_size metrics
void notify()
inline void notify()
{
if (m_get_pos == umax)
m_current_allocated_size = 0;
else if (m_get_pos < m_put_pos)
m_current_allocated_size = (m_put_pos - m_get_pos - 1);
else if (m_get_pos > m_put_pos)
m_current_allocated_size = (m_put_pos + (m_size - m_get_pos - 1));
else
fmt::throw_exception("m_put_pos == m_get_pos!");
// @unused
}
usz size() const

View file

@ -390,14 +390,22 @@ namespace rsx
}
bool ret = false;
for (auto ptr = _data, last = _data + _size - 1; ptr < last; ptr++)
for (auto ptr = _data, last = _data + _size - 1; ptr <= last; ptr++)
{
if (predicate(*ptr))
{
ret = true;
if (ptr == last)
{
// Popping the last entry from list. Just set the new size and exit
_size--;
break;
}
// Move item to the end of the list and shrink by 1
std::memcpy(ptr, last, sizeof(Ty));
last = _data + (--_size);
ret = true;
}
}

View file

@ -9,11 +9,11 @@ namespace rsx
using unordered_map = std::unordered_map<T, U>;
}
#else
#include "3rdparty/robin_hood/include/robin_hood.h"
#include "3rdparty/unordered_dense/include/unordered_dense.h"
namespace rsx
{
template<typename T, typename U>
using unordered_map = ::robin_hood::unordered_map<T, U>;
using unordered_map = ankerl::unordered_dense::map<T, U>;
}
#endif

View file

@ -4,7 +4,6 @@
#include "Emu/RSX/Common/BufferUtils.h"
#include "Emu/RSX/Common/buffer_stream.hpp"
#include "Emu/RSX/Common/io_buffer.h"
#include "Emu/RSX/Common/simple_array.hpp"
#include "Emu/RSX/NV47/HW/context_accessors.define.h"
#include "Emu/RSX/Program/GLSLCommon.h"
#include "Emu/RSX/rsx_methods.h"
@ -759,7 +758,8 @@ namespace rsx
ensure(draw_call.is_trivial_instanced_draw);
// Temp indirection table. Used to track "running" updates.
rsx::simple_array<u32> instancing_indirection_table;
auto& instancing_indirection_table = m_scratch_buffers.u32buf;
// indirection table size
const auto full_reupload = !prog || prog->has_indexed_constants;
const auto reloc_table = full_reupload ? decltype(prog->constant_ids){} : prog->constant_ids;
@ -767,7 +767,8 @@ namespace rsx
instancing_indirection_table.resize(redirection_table_size);
// Temp constants data
rsx::simple_array<u128> constants_data;
auto& constants_data = m_scratch_buffers.u128buf;
constants_data.clear();
constants_data.reserve(redirection_table_size * draw_call.pass_count());
// Allocate indirection buffer on GPU stream

View file

@ -2,6 +2,7 @@
#include <util/types.hpp>
#include "Emu/RSX/Common/simple_array.hpp"
#include "Emu/RSX/Core/RSXVertexTypes.h"
#include "Emu/RSX/NV47/FW/draw_call.hpp"
#include "Emu/RSX/Program/ProgramStateCache.h"
@ -28,6 +29,12 @@ namespace rsx
std::array<push_buffer_vertex_info, 16> m_vertex_push_buffers;
rsx::simple_array<u32> m_element_push_buffer;
struct
{
rsx::simple_array<u32> u32buf;
rsx::simple_array<u128> u128buf;
} mutable m_scratch_buffers;
public:
draw_command_processor() = default;

View file

@ -218,12 +218,12 @@ namespace gl
m_input_filter = gl::filter::linear;
}
gl::texture_view* ui_overlay_renderer::load_simple_image(rsx::overlays::image_info* desc, bool temp_resource, u32 owner_uid)
gl::texture_view* ui_overlay_renderer::load_simple_image(rsx::overlays::image_info_base* desc, bool temp_resource, u32 owner_uid)
{
auto tex = std::make_unique<gl::texture>(GL_TEXTURE_2D, desc->w, desc->h, 1, 1, 1, GL_RGBA8, RSX_FORMAT_CLASS_COLOR);
tex->copy_from(desc->get_data(), gl::texture::format::rgba, gl::texture::type::uint_8_8_8_8, {});
GLenum remap[] = { GL_RED, GL_ALPHA, GL_BLUE, GL_GREEN };
const GLenum remap[] = { GL_RED, GL_ALPHA, GL_BLUE, GL_GREEN };
auto view = std::make_unique<gl::texture_view>(tex.get(), remap);
auto result = view.get();
@ -234,7 +234,7 @@ namespace gl
}
else
{
u64 key = reinterpret_cast<u64>(desc);
const u64 key = reinterpret_cast<u64>(desc);
temp_image_cache[key] = std::make_pair(owner_uid, std::move(tex));
temp_view_cache[key] = std::move(view);
}
@ -249,7 +249,7 @@ namespace gl
rsx::overlays::resource_config configuration;
configuration.load_files();
for (const auto &res : configuration.texture_raw_data)
for (const auto& res : configuration.texture_raw_data)
{
load_simple_image(res.get(), false, -1);
}
@ -318,13 +318,22 @@ namespace gl
return result;
}
gl::texture_view* ui_overlay_renderer::find_temp_image(rsx::overlays::image_info* desc, u32 owner_uid)
gl::texture_view* ui_overlay_renderer::find_temp_image(rsx::overlays::image_info_base* desc, u32 owner_uid)
{
auto key = reinterpret_cast<u64>(desc);
const bool dirty = std::exchange(desc->dirty, false);
const u64 key = reinterpret_cast<u64>(desc);
auto cached = temp_view_cache.find(key);
if (cached != temp_view_cache.end())
{
return cached->second.get();
gl::texture_view* view = cached->second.get();
if (dirty)
{
view->image()->copy_from(desc->get_data(), gl::texture::format::rgba, gl::texture::type::uint_8_8_8_8, {});
}
return view;
}
return load_simple_image(desc, true, owner_uid);
@ -420,7 +429,7 @@ namespace gl
}
case rsx::overlays::image_resource_id::raw_image:
{
cmd_->bind_texture(31, GL_TEXTURE_2D, find_temp_image(static_cast<rsx::overlays::image_info*>(cmd.config.external_data_ref), ui.uid)->id());
cmd_->bind_texture(31, GL_TEXTURE_2D, find_temp_image(static_cast<rsx::overlays::image_info_base*>(cmd.config.external_data_ref), ui.uid)->id());
break;
}
case rsx::overlays::image_resource_id::font_file:

View file

@ -75,7 +75,7 @@ namespace gl
ui_overlay_renderer();
gl::texture_view* load_simple_image(rsx::overlays::image_info* desc, bool temp_resource, u32 owner_uid);
gl::texture_view* load_simple_image(rsx::overlays::image_info_base* desc, bool temp_resource, u32 owner_uid);
void create();
void destroy();
@ -84,7 +84,7 @@ namespace gl
gl::texture_view* find_font(rsx::overlays::font* font);
gl::texture_view* find_temp_image(rsx::overlays::image_info* desc, u32 owner_uid);
gl::texture_view* find_temp_image(rsx::overlays::image_info_base* desc, u32 owner_uid);
void set_primitive_type(rsx::overlays::primitive_type type);

View file

@ -44,6 +44,8 @@ namespace rsx
}
};
draw_command_barrier_mask |= (1u << type);
if (type == primitive_restart_barrier)
{
// Rasterization flow barrier
@ -97,48 +99,32 @@ namespace rsx
return false;
}
// For instancing all draw calls must be identical
const auto& ref = draw_command_ranges.front();
for (const auto& range : draw_command_ranges)
{
if (range.first != ref.first || range.count != ref.count)
{
return false;
}
}
if (draw_command_barriers.empty())
{
// Raise alarm here for investigation, we may be missing a corner case.
rsx_log.error("Instanced draw detected, but no command barriers found!");
return false;
}
// Barriers must exist, but can only involve updating transform constants (for now)
for (const auto& barrier : draw_command_barriers)
{
if (barrier.type != rsx::transform_constant_load_modifier_barrier &&
barrier.type != rsx::transform_constant_update_barrier)
{
ensure(barrier.draw_id < ::size32(draw_command_ranges));
if (draw_command_ranges[barrier.draw_id].count == 0)
{
// Dangling command barriers are ignored. We're also at the end of the command, so abort.
break;
}
const u32 compatible_barrier_mask =
(1u << rsx::transform_constant_load_modifier_barrier) |
(1u << rsx::transform_constant_update_barrier);
// Fail. Only transform constant instancing is supported at the moment.
return false;
}
if (draw_command_barrier_mask & ~compatible_barrier_mask)
{
return false;
}
return true;
// For instancing all draw calls must be identical
// FIXME: This requirement can be easily lifted by chunking contiguous chunks.
const auto& ref = draw_command_ranges.front();
return !draw_command_ranges.any(FN(x.first != ref.first || x.count != ref.count));
}
void draw_clause::reset(primitive_type type)
{
current_range_index = ~0u;
last_execution_barrier_index = 0;
draw_command_barrier_mask = 0;
command = draw_command::none;
primitive = type;
@ -152,6 +138,47 @@ namespace rsx
is_disjoint_primitive = is_primitive_disjointed(primitive);
}
simple_array<draw_range_t> draw_clause::get_subranges() const
{
ensure(!is_single_draw());
const auto range = get_range();
const auto limit = range.first + range.count;
const auto _pass_count = pass_count();
simple_array<draw_range_t> ret;
ret.reserve(_pass_count);
u32 previous_barrier = range.first;
u32 vertex_counter = 0;
for (auto it = current_barrier_it;
it != draw_command_barriers.end() && it->draw_id == current_range_index;
it++)
{
const auto& barrier = *it;
if (barrier.type != primitive_restart_barrier)
continue;
if (barrier.address <= range.first)
continue;
if (barrier.address >= limit)
break;
const u32 count = barrier.address - previous_barrier;
ret.push_back({ 0, vertex_counter, count });
previous_barrier = barrier.address;
vertex_counter += count;
}
ensure(!ret.empty());
ensure(previous_barrier < limit);
ret.push_back({ 0, vertex_counter, limit - previous_barrier });
return ret;
}
u32 draw_clause::execute_pipeline_dependencies(context* ctx, instanced_draw_config_t* instance_config) const
{
u32 result = 0u;

View file

@ -29,6 +29,9 @@ namespace rsx
// Location of last execution barrier
u32 last_execution_barrier_index{};
// Mask of all active barriers
u32 draw_command_barrier_mask = 0;
// Draw-time iterator to the draw_command_barriers struct
mutable simple_array<barrier_t>::iterator current_barrier_it;
@ -282,48 +285,19 @@ namespace rsx
*/
u32 execute_pipeline_dependencies(struct context* ctx, instanced_draw_config_t* instance_config = nullptr) const;
/**
* Returns the first-count data for the current subdraw
*/
const draw_range_t& get_range() const
{
ensure(current_range_index < draw_command_ranges.size());
return draw_command_ranges[current_range_index];
}
simple_array<draw_range_t> get_subranges() const
{
ensure(!is_single_draw());
const auto range = get_range();
const auto limit = range.first + range.count;
simple_array<draw_range_t> ret;
u32 previous_barrier = range.first;
u32 vertex_counter = 0;
for (const auto& barrier : draw_command_barriers)
{
if (barrier.draw_id != current_range_index)
continue;
if (barrier.type != primitive_restart_barrier)
continue;
if (barrier.address <= range.first)
continue;
if (barrier.address >= limit)
break;
const u32 count = barrier.address - previous_barrier;
ret.push_back({ 0, vertex_counter, count });
previous_barrier = barrier.address;
vertex_counter += count;
}
ensure(!ret.empty());
ensure(previous_barrier < limit);
ret.push_back({ 0, vertex_counter, limit - previous_barrier });
return ret;
}
/*
* Returns a compiled list of all subdraws.
* NOTE: This is a non-trivial operation as it takes disjoint primitive boundaries into account.
*/
simple_array<draw_range_t> get_subranges() const;
};
}

View file

@ -15,7 +15,7 @@ namespace rsx
RSX(ctx)->sync();
// Write ref+get (get will be written again with the same value at command end)
auto& dma = vm::_ref<RsxDmaControl>(RSX(ctx)->dma_address);
auto& dma = *vm::_ptr<RsxDmaControl>(RSX(ctx)->dma_address);
dma.get.release(RSX(ctx)->fifo_ctrl->get_pos());
dma.ref.store(arg);
}
@ -28,7 +28,7 @@ namespace rsx
// Syncronization point, may be associated with memory changes without actually changing addresses
RSX(ctx)->m_graphics_state |= rsx::pipeline_state::fragment_program_needs_rehash;
const auto& sema = vm::_ref<RsxSemaphore>(addr).val;
const auto& sema = vm::_ref<RsxSemaphore>(addr);
if (sema == arg)
{

View file

@ -566,7 +566,7 @@ namespace rsx
default:
rsx_log.error("NV4097_GET_REPORT: Bad type %d", type);
vm::_ref<atomic_t<CellGcmReportData>>(address_ptr).atomic_op([&](CellGcmReportData& data)
vm::_ptr<atomic_t<CellGcmReportData>>(address_ptr)->atomic_op([&](CellGcmReportData& data)
{
data.timer = RSX(ctx)->timestamp();
data.padding = 0;
@ -651,7 +651,7 @@ namespace rsx
ensure(addr != umax);
vm::_ref<atomic_t<RsxNotify>>(addr).store(
vm::_ptr<atomic_t<RsxNotify>>(addr)->store(
{
RSX(ctx)->timestamp(),
0

View file

@ -21,7 +21,7 @@ namespace rsx
// First, queue the GPU work. If it flushes the queue for us, the following routines will be faster.
const bool handled = RSX(ctx)->get_backend_config().supports_host_gpu_labels && RSX(ctx)->release_GCM_label(address, data);
if (vm::_ref<RsxSemaphore>(address).val == data)
if (vm::_ref<RsxSemaphore>(address) == data)
{
// It's a no-op to write the same value (although there is a delay in real-hw so it's more accurate to allow GPU label in this case)
return;
@ -57,7 +57,7 @@ namespace rsx
}
}
vm::_ref<RsxSemaphore>(address).val = data;
vm::write<atomic_t<RsxSemaphore>>(address, data);
}
}
}

View file

@ -40,7 +40,7 @@ namespace rsx
{
update_value();
if (!is_compiled)
if (!is_compiled())
{
const f32 col = m_last_value ? 1.0f : 0.3f;
const f32 bkg = m_last_value ? 0.3f : 1.0f;

View file

@ -64,7 +64,7 @@ namespace rsx
if (const T new_value = m_setting->get(); new_value != m_last_value || initializing)
{
m_last_value = new_value;
is_compiled = false;
m_is_compiled = false;
}
}
}
@ -101,7 +101,7 @@ namespace rsx
{
this->update_value();
if (!this->is_compiled)
if (!this->is_compiled())
{
const std::string value_text = Emu.GetCallbacks().get_localized_setting(home_menu_setting<T, cfg::_enum<T>>::m_setting, static_cast<u32>(this->m_last_value));
m_dropdown.set_text(value_text);
@ -145,7 +145,7 @@ namespace rsx
{
this->update_value();
if (!this->is_compiled)
if (!this->is_compiled())
{
const f64 percentage = std::clamp((this->m_last_value - static_cast<T>(m_minimum)) / std::fabs(m_maximum - m_minimum), 0.0, 1.0);
m_slider.set_pos(m_slider.x, this->y + (this->h - m_slider.h) / 2);

View file

@ -44,7 +44,7 @@ namespace rsx
compiled_resource& home_menu_message_box::get_compiled()
{
if (!is_compiled)
if (!is_compiled())
{
compiled_resource& compiled = overlay_element::get_compiled();
compiled.add(m_label.get_compiled());

View file

@ -258,9 +258,9 @@ namespace rsx
compiled_resource& home_menu_page::get_compiled()
{
if (!is_compiled || (m_message_box && !m_message_box->is_compiled))
if (!is_compiled() || (m_message_box && !m_message_box->is_compiled()))
{
is_compiled = false;
m_is_compiled = false;
if (home_menu_page* page = get_current_page(false))
{
@ -281,7 +281,7 @@ namespace rsx
}
}
is_compiled = true;
m_is_compiled = true;
}
return compiled_resources;

View file

@ -58,7 +58,7 @@ namespace rsx
compiled_resource& animated_icon::get_compiled()
{
if (!is_compiled)
if (!is_compiled())
{
compiled_resources = image_view::get_compiled();
}

View file

@ -302,7 +302,7 @@ namespace rsx
void overlay_element::refresh()
{
// Just invalidate for draw when get_compiled() is called
is_compiled = false;
m_is_compiled = false;
}
void overlay_element::translate(s16 _x, s16 _y)
@ -310,7 +310,7 @@ namespace rsx
x += _x;
y += _y;
is_compiled = false;
m_is_compiled = false;
}
void overlay_element::scale(f32 _x, f32 _y, bool origin_scaling)
@ -324,7 +324,7 @@ namespace rsx
w = static_cast<u16>(_x * w);
h = static_cast<u16>(_y * h);
is_compiled = false;
m_is_compiled = false;
}
void overlay_element::set_pos(s16 _x, s16 _y)
@ -332,7 +332,7 @@ namespace rsx
x = _x;
y = _y;
is_compiled = false;
m_is_compiled = false;
}
void overlay_element::set_size(u16 _w, u16 _h)
@ -340,7 +340,7 @@ namespace rsx
w = _w;
h = _h;
is_compiled = false;
m_is_compiled = false;
}
void overlay_element::set_padding(u16 left, u16 right, u16 top, u16 bottom)
@ -350,13 +350,13 @@ namespace rsx
padding_top = top;
padding_bottom = bottom;
is_compiled = false;
m_is_compiled = false;
}
void overlay_element::set_padding(u16 padding)
{
padding_left = padding_right = padding_top = padding_bottom = padding;
is_compiled = false;
m_is_compiled = false;
}
// NOTE: Functions as a simple position offset. Top left corner is the anchor.
@ -365,25 +365,36 @@ namespace rsx
margin_left = left;
margin_top = top;
is_compiled = false;
m_is_compiled = false;
}
void overlay_element::set_margin(u16 margin)
{
margin_left = margin_top = margin;
is_compiled = false;
m_is_compiled = false;
}
void overlay_element::set_text(const std::string& text)
{
this->text = utf8_to_u32string(text);
is_compiled = false;
std::u32string new_text = utf8_to_u32string(text);
const bool is_dirty = this->text != new_text;
this->text = std::move(new_text);
if (is_dirty)
{
m_is_compiled = false;
}
}
void overlay_element::set_unicode_text(const std::u32string& text)
{
const bool is_dirty = this->text != text;
this->text = text;
is_compiled = false;
if (is_dirty)
{
m_is_compiled = false;
}
}
void overlay_element::set_text(localized_string_id id)
@ -394,19 +405,19 @@ namespace rsx
void overlay_element::set_font(const char* font_name, u16 font_size)
{
font_ref = fontmgr::get(font_name, font_size);
is_compiled = false;
m_is_compiled = false;
}
void overlay_element::align_text(text_align align)
{
alignment = align;
is_compiled = false;
m_is_compiled = false;
}
void overlay_element::set_wrap_text(bool state)
{
wrap_text = state;
is_compiled = false;
m_is_compiled = false;
}
font* overlay_element::get_font() const
@ -563,7 +574,7 @@ namespace rsx
compiled_resource& overlay_element::get_compiled()
{
if (!is_compiled)
if (!is_compiled())
{
compiled_resources.clear();
@ -599,7 +610,7 @@ namespace rsx
compiled_resources.add(std::move(compiled_resources_temp), margin_left - horizontal_scroll_offset, margin_top - vertical_scroll_offset);
}
is_compiled = true;
m_is_compiled = true;
}
return compiled_resources;
@ -664,7 +675,7 @@ namespace rsx
{
overlay_element::translate(_x, _y);
for (auto &itm : m_items)
for (auto& itm : m_items)
itm->translate(_x, _y);
}
@ -675,13 +686,23 @@ namespace rsx
translate(dx, dy);
}
bool layout_container::is_compiled()
{
if (m_is_compiled && std::any_of(m_items.cbegin(), m_items.cend(), [](const auto& item){ return item && !item->is_compiled(); }))
{
m_is_compiled = false;
}
return m_is_compiled;
}
compiled_resource& layout_container::get_compiled()
{
if (!is_compiled)
if (!is_compiled())
{
compiled_resource result = overlay_element::get_compiled();
for (auto &itm : m_items)
for (auto& itm : m_items)
result.add(itm->get_compiled());
compiled_resources = result;
@ -716,7 +737,7 @@ namespace rsx
return m_items.back().get();
}
auto result = item.get();
overlay_element* result = item.get();
m_items.insert(m_items.begin() + offset, std::move(item));
return result;
}
@ -726,12 +747,12 @@ namespace rsx
if (scroll_offset_value == 0 && auto_resize)
return layout_container::get_compiled();
if (!is_compiled)
if (!is_compiled())
{
compiled_resource result = overlay_element::get_compiled();
const f32 global_y_offset = static_cast<f32>(-scroll_offset_value);
for (auto &item : m_items)
for (auto& item : m_items)
{
if (!item)
{
@ -808,7 +829,7 @@ namespace rsx
if (scroll_offset_value == 0 && auto_resize)
return layout_container::get_compiled();
if (!is_compiled)
if (!is_compiled())
{
compiled_resource result = overlay_element::get_compiled();
const f32 global_x_offset = static_cast<f32>(-scroll_offset_value);
@ -862,7 +883,7 @@ namespace rsx
compiled_resource& image_view::get_compiled()
{
if (!is_compiled)
if (!is_compiled())
{
auto& result = overlay_element::get_compiled();
auto& cmd_img = result.draw_commands.front();
@ -880,7 +901,7 @@ namespace rsx
verts[2] += vertex(padding_left, -padding_top, 0, 0);
verts[3] += vertex(-padding_right, -padding_top, 0, 0);
is_compiled = true;
m_is_compiled = true;
}
return compiled_resources;
@ -892,7 +913,7 @@ namespace rsx
external_ref = nullptr;
}
void image_view::set_raw_image(image_info* raw_image)
void image_view::set_raw_image(image_info_base* raw_image)
{
image_resource_ref = image_resource_id::raw_image;
external_ref = raw_image;
@ -935,7 +956,7 @@ namespace rsx
compiled_resource& image_button::get_compiled()
{
if (!is_compiled)
if (!is_compiled())
{
auto& compiled = image_view::get_compiled();
for (auto& cmd : compiled.draw_commands)
@ -987,7 +1008,7 @@ namespace rsx
compiled_resource& rounded_rect::get_compiled()
{
if (!is_compiled)
if (!is_compiled())
{
compiled_resources.clear();
@ -1068,7 +1089,7 @@ namespace rsx
compiled_resources.add(std::move(compiled_resources_temp), margin_left, margin_top);
}
is_compiled = true;
m_is_compiled = true;
}
return compiled_resources;

View file

@ -30,23 +30,32 @@ namespace rsx
triangle_fan = 4
};
struct image_info
struct image_info_base
{
int w = 0, h = 0, channels = 0;
int bpp = 0;
bool dirty = false;
image_info_base() {}
virtual ~image_info_base() {}
virtual const u8* get_data() const = 0;
};
struct image_info : public image_info_base
{
private:
u8* data = nullptr;
std::vector<u8> data_grey;
public:
int w = 0, h = 0, channels = 0;
int bpp = 0;
using image_info_base::image_info_base;
image_info(image_info&) = delete;
image_info(const std::string& filename, bool grayscaled = false);
image_info(const std::vector<u8>& bytes, bool grayscaled = false);
~image_info();
virtual ~image_info();
void load_data(const std::vector<u8>& bytes, bool grayscaled = false);
const u8* get_data() const { return channels == 4 ? data : data_grey.empty() ? nullptr : data_grey.data(); }
const u8* get_data() const override { return channels == 4 ? data : data_grey.empty() ? nullptr : data_grey.data(); }
};
struct resource_config
@ -165,7 +174,6 @@ namespace rsx
void set_sinus_offset(f32 sinus_modifier);
compiled_resource compiled_resources;
bool is_compiled = false;
bool visible = true;
@ -185,6 +193,7 @@ namespace rsx
virtual ~overlay_element() = default;
virtual void refresh();
virtual bool is_compiled() { return m_is_compiled; }
virtual void translate(s16 _x, s16 _y);
virtual void scale(f32 _x, f32 _y, bool origin_scaling);
virtual void set_pos(s16 _x, s16 _y);
@ -204,6 +213,10 @@ namespace rsx
virtual std::vector<vertex> render_text(const char32_t* string, f32 x, f32 y);
virtual compiled_resource& get_compiled();
void measure_text(u16& width, u16& height, bool ignore_word_wrap = false) const;
virtual void set_selected(bool selected) { static_cast<void>(selected); }
protected:
bool m_is_compiled = false; // Only use m_is_compiled as a getter in is_compiled() if possible
};
struct layout_container : public overlay_element
@ -221,6 +234,8 @@ namespace rsx
void translate(s16 _x, s16 _y) override;
void set_pos(s16 _x, s16 _y) override;
bool is_compiled() override;
compiled_resource& get_compiled() override;
virtual u16 get_scroll_offset_px() = 0;
@ -248,6 +263,7 @@ namespace rsx
compiled_resource& get_compiled() override
{
// No draw
m_is_compiled = true;
return compiled_resources;
}
};
@ -263,7 +279,7 @@ namespace rsx
struct image_view : public overlay_element
{
private:
protected:
u8 image_resource_ref = image_resource_id::none;
void* external_ref = nullptr;
@ -276,7 +292,7 @@ namespace rsx
compiled_resource& get_compiled() override;
void set_image_resource(u8 resource_id);
void set_raw_image(image_info* raw_image);
void set_raw_image(image_info_base* raw_image);
void clear_image();
void set_blur_strength(u8 strength);
};

View file

@ -196,7 +196,7 @@ namespace rsx
compiled_resource& edit_text::get_compiled()
{
if (!is_compiled)
if (!is_compiled())
{
auto renderer = get_font();
const auto [caret_x, caret_y] = renderer->get_char_offset(text.c_str(), caret_position, clip_text ? w : -1, wrap_text);
@ -252,7 +252,7 @@ namespace rsx
cmd.config.clip_rect = {static_cast<f32>(x), static_cast<f32>(y), static_cast<f32>(x + w), static_cast<f32>(y + h)};
}
is_compiled = true;
m_is_compiled = true;
}
return compiled_resources;

View file

@ -91,6 +91,15 @@ namespace rsx
void list_view::update_selection()
{
const overlay_element* current_element = get_selected_entry();
for (auto& item : m_items)
{
if (item)
{
item->set_selected(item.get() == current_element);
}
}
if (!current_element)
{
return; // Ideally unreachable but it should still be possible to recover by user interaction.
@ -195,7 +204,7 @@ namespace rsx
m_cancel_btn->set_pos(x + 180, y + h + 20);
m_cancel_only = cancel_only;
is_compiled = false;
m_is_compiled = false;
}
bool list_view::get_cancel_only() const
@ -219,7 +228,7 @@ namespace rsx
compiled_resource& list_view::get_compiled()
{
if (!is_compiled)
if (!is_compiled())
{
auto& compiled = vertical_layout::get_compiled();
compiled.add(m_highlight_box->get_compiled());

View file

@ -100,7 +100,7 @@ namespace rsx
}
// Disable caching
is_compiled = false;
m_is_compiled = false;
compiled_resources = rounded_rect::get_compiled();
compiled_resources.add(m_text.get_compiled());

View file

@ -814,7 +814,7 @@ namespace rsx
compiled_resource& graph::get_compiled()
{
if (is_compiled)
if (is_compiled())
{
return compiled_resources;
}

View file

@ -23,7 +23,7 @@ namespace rsx
void progress_bar::set_limit(f32 limit)
{
m_limit = limit;
is_compiled = false;
m_is_compiled = false;
}
void progress_bar::set_value(f32 value)
@ -32,7 +32,7 @@ namespace rsx
f32 indicator_width = (w * m_value) / m_limit;
indicator.set_size(static_cast<u16>(indicator_width), h);
is_compiled = false;
m_is_compiled = false;
}
void progress_bar::set_pos(s16 _x, s16 _y)
@ -68,12 +68,12 @@ namespace rsx
text_view.set_size(w, text_h);
set_pos(text_view.x, text_view.y);
is_compiled = false;
m_is_compiled = false;
}
compiled_resource& progress_bar::get_compiled()
{
if (!is_compiled)
if (!is_compiled())
{
auto& compiled = overlay_element::get_compiled();
compiled.add(text_view.get_compiled());

View file

@ -1,5 +1,6 @@
#include "stdafx.h"
#include "overlay_save_dialog.h"
#include "overlay_video.h"
#include "Utilities/date_time.h"
#include "Emu/System.h"
@ -7,26 +8,18 @@ namespace rsx
{
namespace overlays
{
save_dialog::save_dialog_entry::save_dialog_entry(const std::string& text1, const std::string& text2, const std::string& text3, u8 resource_id, const std::vector<u8>& icon_buf)
save_dialog::save_dialog_entry::save_dialog_entry(const std::string& text1, const std::string& text2, const std::string& text3, u8 resource_id, const std::vector<u8>& icon_buf, const std::string& video_path)
{
std::unique_ptr<overlay_element> image = std::make_unique<image_view>();
std::unique_ptr<overlay_element> image = resource_id != image_resource_id::raw_image
? std::make_unique<video_view>(video_path, resource_id)
: !icon_buf.empty() ? std::make_unique<video_view>(video_path, icon_buf)
: std::make_unique<video_view>(video_path, resource_config::standard_image_resource::save); // Fallback
image->set_size(160, 110);
image->set_padding(36, 36, 11, 11); // Square image, 88x88
if (resource_id != image_resource_id::raw_image)
{
static_cast<image_view*>(image.get())->set_image_resource(resource_id);
}
else if (!icon_buf.empty())
if (resource_id == image_resource_id::raw_image && !icon_buf.empty())
{
image->set_padding(0, 0, 11, 11); // Half sized icon, 320x176->160x88
icon_data = std::make_unique<image_info>(icon_buf);
static_cast<image_view*>(image.get())->set_raw_image(icon_data.get());
}
else
{
// Fallback
static_cast<image_view*>(image.get())->set_image_resource(resource_config::standard_image_resource::save);
}
std::unique_ptr<overlay_element> text_stack = std::make_unique<vertical_layout>();
@ -74,10 +67,18 @@ namespace rsx
// Pack
this->pack_padding = 15;
add_element(image);
m_image = add_element(image);
add_element(text_stack);
}
void save_dialog::save_dialog_entry::set_selected(bool selected)
{
if (m_image)
{
static_cast<video_view*>(m_image)->set_active(selected);
}
}
save_dialog::save_dialog()
{
m_dim_background = std::make_unique<overlay_element>();
@ -197,7 +198,7 @@ namespace rsx
return result;
}
s32 save_dialog::show(std::vector<SaveDataEntry>& save_entries, u32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay)
s32 save_dialog::show(const std::string& base_dir, std::vector<SaveDataEntry>& save_entries, u32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay)
{
rsx_log.notice("Showing native UI save_dialog (save_entries=%d, focused=%d, op=0x%x, listSet=*0x%x, enable_overlay=%d)", save_entries.size(), focused, op, listSet, enable_overlay);
@ -218,7 +219,7 @@ namespace rsx
{
const std::string date_and_size = fmt::format("%s %s", entry.date(), entry.data_size());
std::unique_ptr<overlay_element> e;
e = std::make_unique<save_dialog_entry>(entry.subtitle, date_and_size, entry.details, image_resource_id::raw_image, entry.iconBuf);
e = std::make_unique<save_dialog_entry>(entry.subtitle, date_and_size, entry.details, image_resource_id::raw_image, entry.iconBuf, base_dir + entry.dirName + "/ICON1.PAM");
entries.emplace_back(std::move(e));
}
@ -270,7 +271,7 @@ namespace rsx
id = image_resource_id::raw_image;
}
std::unique_ptr<overlay_element> new_stub = std::make_unique<save_dialog_entry>(title, get_localized_string(localized_string_id::CELL_SAVEDATA_NEW_SAVED_DATA_SUB_TITLE), "", id, icon);
std::unique_ptr<overlay_element> new_stub = std::make_unique<save_dialog_entry>(title, get_localized_string(localized_string_id::CELL_SAVEDATA_NEW_SAVED_DATA_SUB_TITLE), "", id, icon, "");
m_list->add_entry(new_stub);
}

View file

@ -13,11 +13,12 @@ namespace rsx
private:
struct save_dialog_entry : horizontal_layout
{
private:
std::unique_ptr<image_info> icon_data;
public:
save_dialog_entry(const std::string& text1, const std::string& text2, const std::string& text3, u8 resource_id, const std::vector<u8>& icon_buf);
save_dialog_entry(const std::string& text1, const std::string& text2, const std::string& text3, u8 resource_id, const std::vector<u8>& icon_buf, const std::string& video_path);
void set_selected(bool selected) override;
private:
overlay_element* m_image = nullptr;
};
std::unique_ptr<overlay_element> m_dim_background;
@ -38,7 +39,7 @@ namespace rsx
compiled_resource get_compiled() override;
s32 show(std::vector<SaveDataEntry>& save_entries, u32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay);
s32 show(const std::string& base_dir, std::vector<SaveDataEntry>& save_entries, u32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet, bool enable_overlay);
};
}
}

View file

@ -0,0 +1,116 @@
#include "stdafx.h"
#include "overlay_video.h"
#include "Emu/System.h"
namespace rsx
{
namespace overlays
{
video_view::video_view(const std::string& video_path, const std::string& thumbnail_path)
{
init_video(video_path);
if (!thumbnail_path.empty())
{
m_thumbnail_info = std::make_unique<image_info>(thumbnail_path);
set_raw_image(m_thumbnail_info.get());
}
}
video_view::video_view(const std::string& video_path, const std::vector<u8>& thumbnail_buf)
{
init_video(video_path);
if (!thumbnail_buf.empty())
{
m_thumbnail_info = std::make_unique<image_info>(thumbnail_buf);
set_raw_image(m_thumbnail_info.get());
}
}
video_view::video_view(const std::string& video_path, u8 thumbnail_id)
: m_thumbnail_id(thumbnail_id)
{
init_video(video_path);
set_image_resource(thumbnail_id);
}
video_view::~video_view()
{
}
void video_view::init_video(const std::string& video_path)
{
if (video_path.empty()) return;
m_video_source = Emu.GetCallbacks().make_video_source();
ensure(!!m_video_source);
m_video_source->set_update_callback([this]()
{
if (m_video_active)
{
m_is_compiled = false;
}
});
m_video_source->set_video_path(video_path);
}
void video_view::set_active(bool active)
{
if (m_video_source)
{
m_video_source->set_active(active);
m_video_active = active;
m_is_compiled = false;
}
}
void video_view::update()
{
if (m_video_active && m_video_source && m_video_source->get_active())
{
if (!m_video_source->has_new())
{
return;
}
m_buffer_index = (m_buffer_index + 1) % m_video_info.size();
auto& info = m_video_info.at(m_buffer_index);
if (!info)
{
info = std::make_unique<video_info>();
}
m_video_source->get_image(info->data, info->w, info->h, info->channels, info->bpp);
info->dirty = true;
set_raw_image(info.get());
m_is_compiled = false;
return;
}
if (m_thumbnail_info && m_thumbnail_info.get() != external_ref)
{
set_raw_image(m_thumbnail_info.get());
m_is_compiled = false;
return;
}
if (m_thumbnail_id != image_resource_id::none && m_thumbnail_id != image_resource_ref)
{
set_image_resource(m_thumbnail_id);
m_is_compiled = false;
return;
}
}
compiled_resource& video_view::get_compiled()
{
update();
return external_ref ? image_view::get_compiled() : overlay_element::get_compiled();
}
}
}

View file

@ -0,0 +1,43 @@
#pragma once
#include "overlay_controls.h"
#include "util/video_source.h"
namespace rsx
{
namespace overlays
{
struct video_info : public image_info_base
{
using image_info_base::image_info_base;
virtual ~video_info() {}
const u8* get_data() const override { return data.empty() ? nullptr : data.data(); }
std::vector<u8> data;
};
class video_view final : public image_view
{
public:
video_view(const std::string& video_path, const std::string& thumbnail_path);
video_view(const std::string& video_path, const std::vector<u8>& thumbnail_buf);
video_view(const std::string& video_path, u8 thumbnail_id);
virtual ~video_view();
void set_active(bool active);
void update();
compiled_resource& get_compiled() override;
private:
void init_video(const std::string& video_path);
usz m_buffer_index = 0;
std::array<std::unique_ptr<video_info>, 2> m_video_info; // double buffer
std::unique_ptr<video_source> m_video_source;
std::unique_ptr<image_info> m_thumbnail_info;
u8 m_thumbnail_id = image_resource_id::none;
bool m_video_active = false; // This is the expected state. The actual state is found in the video source.
};
}
}

View file

@ -76,6 +76,8 @@ vec4 _fetch_constant(const in uint base_offset)
// uint override
return _fetch_constant(int(base_offset));
}
#elif defined(VULKAN)
#define _fetch_constant(x) vc[x + xform_constants_offset]
#else
#define _fetch_constant(x) vc[x]
#endif

View file

@ -23,10 +23,6 @@
#endif
#endif
#ifdef ARCH_ARM64
#define AVX512_ICL_FUNC
#endif
#ifdef _MSC_VER
#define AVX512_ICL_FUNC
#else

View file

@ -1212,7 +1212,7 @@ namespace rsx
if (const u64 get_put = new_get_put.exchange(u64{umax});
get_put != umax)
{
vm::_ref<atomic_be_t<u64>>(dma_address + ::offset32(&RsxDmaControl::put)).release(get_put);
vm::_ptr<atomic_be_t<u64>>(dma_address + ::offset32(&RsxDmaControl::put))->release(get_put);
fifo_ctrl->set_get(static_cast<u32>(get_put));
fifo_ctrl->abort();
fifo_ret_addr = RSX_CALL_STACK_EMPTY;
@ -2457,7 +2457,7 @@ namespace rsx
}
rsx::reservation_lock<true> lock(sink, 16);
vm::_ref<atomic_t<CellGcmReportData>>(sink).store({timestamp(), value, 0});
vm::_ptr<atomic_t<CellGcmReportData>>(sink)->store({timestamp(), value, 0});
}
u32 thread::copy_zcull_stats(u32 memory_range_start, u32 memory_range, u32 destination)

View file

@ -50,7 +50,7 @@ namespace vk
idx++;
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
bindings[idx].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
bindings[idx].descriptorCount = 1;
bindings[idx].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
bindings[idx].binding = binding_table.vertex_constant_buffers_bind_slot;
@ -101,7 +101,8 @@ namespace vk
return bindings;
}
std::tuple<VkPipelineLayout, VkDescriptorSetLayout> get_common_pipeline_layout(VkDevice dev)
std::tuple<VkPipelineLayout, VkDescriptorSetLayout, rsx::simple_array<VkDescriptorSetLayoutBinding>>
get_common_pipeline_layout(VkDevice dev)
{
const auto& binding_table = vk::get_current_renderer()->get_pipeline_binding_table();
auto bindings = get_common_binding_table();
@ -135,13 +136,13 @@ namespace vk
std::array<VkPushConstantRange, 1> push_constants;
push_constants[0].offset = 0;
push_constants[0].size = 16;
push_constants[0].size = 20;
push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
if (vk::emulate_conditional_rendering())
{
// Conditional render toggle
push_constants[0].size = 20;
push_constants[0].size = 24;
}
const auto set_layout = vk::descriptors::create_layout(bindings);
@ -155,6 +156,25 @@ namespace vk
VkPipelineLayout result;
CHECK_RESULT(vkCreatePipelineLayout(dev, &layout_info, nullptr, &result));
return std::make_tuple(result, set_layout);
return std::make_tuple(result, set_layout, bindings);
}
rsx::simple_array<VkDescriptorPoolSize> get_descriptor_pool_sizes(const rsx::simple_array<VkDescriptorSetLayoutBinding>& bindings)
{
// Compile descriptor pool sizes
const u32 num_ubo = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ? y.descriptorCount : 0)));
const u32 num_texel_buffers = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ? y.descriptorCount : 0)));
const u32 num_combined_image_sampler = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ? y.descriptorCount : 0)));
const u32 num_ssbo = bindings.reduce(0, FN(x + (y.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ? y.descriptorCount : 0)));
ensure(num_ubo > 0 && num_texel_buffers > 0 && num_combined_image_sampler > 0 && num_ssbo > 0);
return
{
{ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER , num_ubo },
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER , num_texel_buffers },
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER , num_combined_image_sampler },
{ VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, num_ssbo }
};
}
}

View file

@ -7,8 +7,11 @@ namespace vk
{
// Grab standard layout for decompiled RSX programs. Also used by the interpreter.
// FIXME: This generates a bloated monstrosity that needs to die.
std::tuple<VkPipelineLayout, VkDescriptorSetLayout> get_common_pipeline_layout(VkDevice dev);
std::tuple<VkPipelineLayout, VkDescriptorSetLayout, rsx::simple_array<VkDescriptorSetLayoutBinding>> get_common_pipeline_layout(VkDevice dev);
// Returns the standard binding layout without texture slots. Those have special handling depending on the consumer.
rsx::simple_array<VkDescriptorSetLayoutBinding> get_common_binding_table();
// Returns an array of pool sizes that can be used to generate a proper descriptor pool
rsx::simple_array<VkDescriptorPoolSize> get_descriptor_pool_sizes(const rsx::simple_array<VkDescriptorSetLayoutBinding>& bindings);
}

View file

@ -0,0 +1,66 @@
#include "stdafx.h"
#include "VKDataHeapManager.h"
#include "vkutils/data_heap.h"
#include <unordered_set>
namespace vk::data_heap_manager
{
std::unordered_set<vk::data_heap*> g_managed_heaps;
void register_ring_buffer(vk::data_heap& heap)
{
g_managed_heaps.insert(&heap);
}
void register_ring_buffers(std::initializer_list<std::reference_wrapper<vk::data_heap>> heaps)
{
for (auto&& heap : heaps)
{
register_ring_buffer(heap);
}
}
managed_heap_snapshot_t get_heap_snapshot()
{
managed_heap_snapshot_t result{};
for (auto& heap : g_managed_heaps)
{
result[heap] = heap->get_current_put_pos_minus_one();
}
return result;
}
void restore_snapshot(const managed_heap_snapshot_t& snapshot)
{
for (auto& heap : g_managed_heaps)
{
const auto found = snapshot.find(heap);
if (found == snapshot.end())
{
continue;
}
heap->set_get_pos(found->second);
heap->notify();
}
}
void reset_heap_allocations()
{
for (auto& heap : g_managed_heaps)
{
heap->reset_allocation_stats();
}
}
void reset()
{
for (auto& heap : g_managed_heaps)
{
heap->destroy();
}
g_managed_heaps.clear();
}
}

View file

@ -0,0 +1,33 @@
#pragma once
#include <util/types.hpp>
#include <unordered_map>
namespace vk
{
class data_heap;
namespace data_heap_manager
{
using managed_heap_snapshot_t = std::unordered_map<const vk::data_heap*, s64>;
// Submit ring buffer for management
void register_ring_buffer(vk::data_heap& heap);
// Bulk registration
void register_ring_buffers(std::initializer_list<std::reference_wrapper<vk::data_heap>> heaps);
// Capture managed ring buffers snapshot at current time
managed_heap_snapshot_t get_heap_snapshot();
// Synchronize heap with snapshot
void restore_snapshot(const managed_heap_snapshot_t& snapshot);
// Reset all managed heap allocations
void reset_heap_allocations();
// Cleanup
void reset();
}
}

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